First Commit of my working state
[simh.git] / PDP1 / pdp1_stddev.c
1 /* pdp1_stddev.c: PDP-1 standard devices
2
3 Copyright (c) 1993-2006, Robert M. Supnik
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of Robert M Supnik shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from Robert M Supnik.
25
26 ptr paper tape reader
27 ptp paper tape punch
28 tti keyboard
29 tto teleprinter
30
31 21-Dec-06 RMS Added 16-channel sequence break support
32 29-Oct-03 RMS Added PTR FIODEC-to-ASCII translation (from Phil Budne)
33 07-Sep-03 RMS Changed ioc to ios
34 30-Aug-03 RMS Revised PTR to conform to Maintenance Manual;
35 added deadlock prevention on errors
36 23-Jul-03 RMS Revised to detect I/O wait hang
37 25-Apr-03 RMS Revised for extended file support
38 22-Dec-02 RMS Added break support
39 29-Nov-02 RMS Fixed output flag initialization (found by Derek Peschel)
40 21-Nov-02 RMS Changed typewriter to half duplex (found by Derek Peschel)
41 06-Oct-02 RMS Revised for V2.10
42 30-May-02 RMS Widened POS to 32b
43 29-Nov-01 RMS Added read only unit support
44 07-Sep-01 RMS Moved function prototypes
45 10-Jun-01 RMS Fixed comment
46 30-Oct-00 RMS Standardized device naming
47
48 Note: PTP timeout must be >10X faster that TTY output timeout for Macro
49 to work correctly!
50 */
51
52 #include "pdp1_defs.h"
53
54 #define FIODEC_STOP 013 /* stop code */
55 #define FIODEC_UC 074
56 #define FIODEC_LC 072
57 #define UC_V 6 /* upper case */
58 #define UC (1 << UC_V)
59 #define BOTH (1 << (UC_V + 1)) /* both cases */
60 #define CW (1 << (UC_V + 2)) /* char waiting */
61 #define TT_WIDTH 077
62 #define UNIT_V_ASCII (UNIT_V_UF + 0) /* ASCII/binary mode */
63 #define UNIT_ASCII (1 << UNIT_V_ASCII)
64 #define PTR_LEADER 20 /* ASCII leader chars */
65
66 int32 ptr_state = 0;
67 int32 ptr_wait = 0;
68 int32 ptr_stopioe = 0;
69 int32 ptr_uc = 0; /* upper/lower case */
70 int32 ptr_hold = 0; /* holding buffer */
71 int32 ptr_leader = PTR_LEADER; /* leader count */
72 int32 ptr_sbs = 0; /* SBS level */
73 int32 ptp_stopioe = 0;
74 int32 ptp_sbs = 0; /* SBS level */
75 int32 tti_hold = 0; /* tti hold buf */
76 int32 tti_sbs = 0; /* SBS level */
77 int32 tty_buf = 0; /* tty buffer */
78 int32 tty_uc = 0; /* tty uc/lc */
79 int32 tto_sbs = 0;
80
81 extern int32 ios, ioh, cpls, iosta;
82 extern int32 PF, IO, PC, TA;
83 extern int32 M[];
84
85 int ptr_get_ascii (UNIT *uptr);
86 t_stat ptr_svc (UNIT *uptr);
87 t_stat ptp_svc (UNIT *uptr);
88 t_stat tti_svc (UNIT *uptr);
89 t_stat tto_svc (UNIT *uptr);
90 t_stat ptr_reset (DEVICE *dptr);
91 t_stat ptp_reset (DEVICE *dptr);
92 t_stat tty_reset (DEVICE *dptr);
93 t_stat ptr_boot (int32 unitno, DEVICE *dptr);
94 t_stat ptr_attach (UNIT *uptr, char *cptr);
95
96 /* Character translation tables */
97
98 int32 fiodec_to_ascii[128] = {
99 ' ', '1', '2', '3', '4', '5', '6', '7', /* lower case */
100 '8', '9', 0, 0, 0, 0, 0, 0,
101 '0', '/', 's', 't', 'u', 'v', 'w', 'x',
102 'y', 'z', 0, ',', 0, 0, '\t', 0,
103 '@', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
104 'q', 'r', 0, 0, '-', ')', '\\', '(',
105 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
106 'h', 'i', '{', '.', '}', '\b', 0, '\r',
107 ' ', '"', '\'', '~', '#', '!', '&', '<', /* upper case */
108 '>', '^', 0, 0, 0, 0, 0, 0,
109 '`', '?', 'S', 'T', 'U', 'V', 'W', 'X',
110 'Y', 'Z', 0, '=', 0, 0, '\t', 0,
111 '_', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
112 'Q', 'R', 0, 0, '+', ']', '|', '[',
113 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
114 'H', 'I', '{', '*', '}', '\b', 0, '\r'
115 };
116
117 int32 ascii_to_fiodec[128] = {
118 0, 0, 0, 0, 0, 0, 0, 0,
119 BOTH+075, BOTH+036, 0, 0, 0, BOTH+077, 0, 0,
120 0, 0, 0, 0, 0, 0, 0, 0,
121 0, 0, 0, 0, 0, 0, 0, 0,
122 BOTH+0, UC+005, UC+001, UC+004, 0, 0, UC+006, UC+002,
123 057, 055, UC+073, UC+054, 033, 054, 073, 021,
124 020, 001, 002, 003, 004, 005, 006, 007,
125 010, 011, 0, 0, UC+007, UC+033, UC+010, UC+021,
126 040, UC+061, UC+062, UC+063, UC+064, UC+065, UC+066, UC+067,
127 UC+070, UC+071, UC+041, UC+042, UC+043, UC+044, UC+045, UC+046,
128 UC+047, UC+050, UC+051, UC+022, UC+023, UC+024, UC+025, UC+026,
129 UC+027, UC+030, UC+031, UC+057, 056, UC+055, UC+011, UC+040,
130 UC+020, 061, 062, 063, 064, 065, 066, 067,
131 070, 071, 041, 042, 043, 044, 045, 046,
132 047, 050, 051, 022, 023, 024, 025, 026,
133 027, 030, 031, 0, UC+056, 0, UC+003, BOTH+075
134 };
135
136 /* PTR data structures
137
138 ptr_dev PTR device descriptor
139 ptr_unit PTR unit
140 ptr_reg PTR register list
141 */
142
143 UNIT ptr_unit = {
144 UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0),
145 SERIAL_IN_WAIT
146 };
147
148 REG ptr_reg[] = {
149 { ORDATA (BUF, ptr_unit.buf, 18) },
150 { FLDATA (UC, ptr_uc, UC_V) },
151 { FLDATA (DONE, iosta, IOS_V_PTR) },
152 { FLDATA (RPLS, cpls, CPLS_V_PTR) },
153 { ORDATA (HOLD, ptr_hold, 9), REG_HRO },
154 { ORDATA (STATE, ptr_state, 5), REG_HRO },
155 { FLDATA (WAIT, ptr_wait, 0), REG_HRO },
156 { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
157 { DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
158 { DRDATA (LEADER, ptr_leader, 6), REG_HRO },
159 { FLDATA (STOP_IOE, ptr_stopioe, 0) },
160 { DRDATA (SBSLVL, ptr_sbs, 4), REG_HRO },
161 { NULL }
162 };
163
164 MTAB ptr_mod[] = {
165 { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
166 &dev_set_sbs, &dev_show_sbs, (void *) &ptr_sbs },
167 { UNIT_ASCII, UNIT_ASCII, "ASCII", "ASCII", NULL },
168 { UNIT_ASCII, 0, "FIODEC", "FIODEC", NULL },
169 { 0 }
170 };
171
172 DEVICE ptr_dev = {
173 "PTR", &ptr_unit, ptr_reg, ptr_mod,
174 1, 10, 31, 1, 8, 8,
175 NULL, NULL, &ptr_reset,
176 &ptr_boot, &ptr_attach, NULL,
177 NULL, 0
178 };
179
180 /* PTP data structures
181
182 ptp_dev PTP device descriptor
183 ptp_unit PTP unit
184 ptp_reg PTP register list
185 */
186
187 UNIT ptp_unit = {
188 UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), SERIAL_OUT_WAIT
189 };
190
191 REG ptp_reg[] = {
192 { ORDATA (BUF, ptp_unit.buf, 8) },
193 { FLDATA (DONE, iosta, IOS_V_PTP) },
194 { FLDATA (RPLS, cpls, CPLS_V_PTP) },
195 { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
196 { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
197 { FLDATA (STOP_IOE, ptp_stopioe, 0) },
198 { DRDATA (SBSLVL, ptp_sbs, 4), REG_HRO },
199 { NULL }
200 };
201
202 MTAB ptp_mod[] = {
203 { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
204 &dev_set_sbs, &dev_show_sbs, (void *) &ptp_sbs },
205 { 0 }
206 };
207
208 DEVICE ptp_dev = {
209 "PTP", &ptp_unit, ptp_reg, ptp_mod,
210 1, 10, 31, 1, 8, 8,
211 NULL, NULL, &ptp_reset,
212 NULL, NULL, NULL,
213 NULL, 0
214 };
215
216 /* TTI data structures
217
218 tti_dev TTI device descriptor
219 tti_unit TTI unit
220 tti_reg TTI register list
221 */
222
223 UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };
224
225 REG tti_reg[] = {
226 { ORDATA (BUF, tty_buf, 6) },
227 { FLDATA (UC, tty_uc, UC_V) },
228 { ORDATA (HOLD, tti_hold, 9), REG_HRO },
229 { FLDATA (DONE, iosta, IOS_V_TTI) },
230 { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },
231 { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },
232 { DRDATA (SBSLVL, tti_sbs, 4), REG_HRO },
233 { NULL }
234 };
235
236 MTAB tti_mod[] = {
237 { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
238 &dev_set_sbs, &dev_show_sbs, (void *) &tti_sbs },
239 { 0 }
240 };
241
242 DEVICE tti_dev = {
243 "TTI", &tti_unit, tti_reg, tti_mod,
244 1, 10, 31, 1, 8, 8,
245 NULL, NULL, &tty_reset,
246 NULL, NULL, NULL,
247 NULL, 0
248 };
249
250 /* TTO data structures
251
252 tto_dev TTO device descriptor
253 tto_unit TTO unit
254 tto_reg TTO register list
255 */
256
257 UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT * 10 };
258
259 REG tto_reg[] = {
260 { ORDATA (BUF, tty_buf, 6) },
261 { FLDATA (UC, tty_uc, UC_V) },
262 { FLDATA (RPLS, cpls, CPLS_V_TTO) },
263 { FLDATA (DONE, iosta, IOS_V_TTO) },
264 { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },
265 { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },
266 { DRDATA (SBSLVL, tto_sbs, 4), REG_HRO },
267 { NULL }
268 };
269
270 MTAB tto_mod[] = {
271 { MTAB_XTD|MTAB_VDV, 0, "SBSLVL", "SBSLVL",
272 &dev_set_sbs, &dev_show_sbs, (void *) &tto_sbs },
273 { 0 }
274 };
275
276 DEVICE tto_dev = {
277 "TTO", &tto_unit, tto_reg, tto_mod,
278 1, 10, 31, 1, 8, 8,
279 NULL, NULL, &tty_reset,
280 NULL, NULL, NULL,
281 NULL, 0
282 };
283
284 /* Paper tape reader: IOT routine. Points to note:
285
286 - RPA (but not RPB) complements the reader clutch control. Thus,
287 if the reader is running, RPA will stop it.
288 - The status bit indicates data in the reader buffer that has not
289 been transfered to IO. It is cleared by any RB->IO operation,
290 including RRB and the completion pulse.
291 - A reader error on a wait mode operation could hang the simulator.
292 IOH is set; any retry (without RESET) will be NOP'd. Accordingly,
293 the PTR service routine clears IOH on any error during a rpa/rpb i.
294 */
295
296 int32 ptr (int32 inst, int32 dev, int32 dat)
297 {
298 if (dev == 0030) { /* RRB */
299 iosta = iosta & ~IOS_PTR; /* clear status */
300 return ptr_unit.buf; /* return data */
301 }
302 if (dev == 0002) ptr_state = 18; /* RPB, mode = binary */
303 else if (sim_is_active (&ptr_unit)) { /* RPA, running? */
304 sim_cancel (&ptr_unit); /* stop reader */
305 return dat;
306 }
307 else ptr_state = 0; /* mode = alpha */
308 ptr_unit.buf = 0; /* clear buffer */
309 if (inst & IO_WAIT) ptr_wait = 1; /* set ptr wait */
310 else ptr_wait = 0; /* from IR<5> */
311 if (GEN_CPLS (inst)) { /* comp pulse? */
312 ios = 0;
313 cpls = cpls | CPLS_PTR;
314 }
315 else cpls = cpls & ~CPLS_PTR;
316 sim_activate (&ptr_unit, ptr_unit.wait); /* start reader */
317 return dat;
318 }
319
320 /* Unit service */
321
322 t_stat ptr_svc (UNIT *uptr)
323 {
324 int32 temp;
325
326 if ((uptr->flags & UNIT_ATT) == 0) { /* attached? */
327 if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
328 if ((cpls & CPLS_PTR) || ptr_stopioe) return SCPE_UNATT;
329 return SCPE_OK;
330 }
331 if ((uptr->flags & UNIT_ASCII) && (ptr_state == 0)) /* ASCII mode, alpha read? */
332 temp = ptr_get_ascii (uptr); /* get processed char */
333 else if ((temp = getc (uptr->fileref)) != EOF) /* no, get raw char */
334 uptr->pos = uptr->pos + 1; /* if not eof, count */
335 if (temp == EOF) { /* end of file? */
336 if (ptr_wait) ptr_wait = ioh = 0; /* if wait, clr ioh */
337 if (feof (uptr->fileref)) {
338 if ((cpls & CPLS_PTR) || ptr_stopioe) printf ("PTR end of file\n");
339 else return SCPE_OK;
340 }
341 else perror ("PTR I/O error");
342 clearerr (uptr->fileref);
343 return SCPE_IOERR;
344 }
345 if (ptr_state == 0) uptr->buf = temp & 0377; /* alpha */
346 else if (temp & 0200) { /* binary */
347 ptr_state = ptr_state - 6;
348 uptr->buf = uptr->buf | ((temp & 077) << ptr_state);
349 }
350 if (ptr_state == 0) { /* done? */
351 if (cpls & CPLS_PTR) { /* completion pulse? */
352 iosta = iosta & ~IOS_PTR; /* clear flag */
353 IO = uptr->buf; /* fill IO */
354 ios = 1; /* restart */
355 cpls = cpls & ~CPLS_PTR;
356 }
357 else { /* no, interrupt */
358 iosta = iosta | IOS_PTR; /* set flag */
359 dev_req_int (ptr_sbs); /* req interrupt */
360 }
361 }
362 else sim_activate (uptr, uptr->wait); /* get next char */
363 return SCPE_OK;
364 }
365
366 /* Read next ASCII character */
367
368 int ptr_get_ascii (UNIT *uptr)
369 {
370 int c;
371 int32 in;
372
373 if (ptr_leader > 0) { /* leader? */
374 ptr_leader = ptr_leader - 1; /* count down */
375 return 0;
376 }
377 if (ptr_hold & CW) { /* char waiting? */
378 in = ptr_hold & TT_WIDTH; /* return char */
379 ptr_hold = 0; /* not waiting */
380 }
381 else {
382 for (;;) { /* until valid char */
383 if ((c = getc (uptr->fileref)) == EOF) /* get next char, EOF? */
384 return FIODEC_STOP; /* return STOP */
385 uptr->pos = uptr->pos + 1; /* count char */
386 c = c & 0177; /* cut to 7b */
387 if (c == '\n') c = '\r'; /* NL -> CR */
388 else if (c == '\r') continue; /* ignore CR */
389 in = ascii_to_fiodec[c]; /* convert char */
390 if ((in == 0) && (c != ' ')) continue; /* ignore unknowns */
391 if ((in & BOTH) || ((in & UC) == ptr_uc)) /* case match? */
392 in = in & TT_WIDTH; /* cut to 6b */
393 else { /* no, case shift */
394 ptr_hold = in | CW; /* set char waiting */
395 ptr_uc = in & UC; /* set case */
396 in = ptr_uc? FIODEC_UC: FIODEC_LC; /* return case */
397 } /* end else */
398 break;
399 } /* end for */
400 } /* end else */
401 in = in * 010040201; /* even parity from */
402 in = in | 027555555400; /* HACKMEM 167 */
403 in = in % (9 << 7);
404 return in & 0377;
405 }
406
407 /* Reset routine */
408
409 t_stat ptr_reset (DEVICE *dptr)
410 {
411 ptr_state = 0; /* clear state */
412 ptr_wait = 0;
413 ptr_hold = 0;
414 ptr_uc = 0;
415 ptr_unit.buf = 0;
416 cpls = cpls & ~CPLS_PTR;
417 iosta = iosta & ~IOS_PTR; /* clear flag */
418 sim_cancel (&ptr_unit); /* deactivate unit */
419 return SCPE_OK;
420 }
421
422 /* Attach routine */
423
424 t_stat ptr_attach (UNIT *uptr, char *cptr)
425 {
426 ptr_leader = PTR_LEADER; /* set up leader */
427 return attach_unit (uptr, cptr);
428 }
429
430 /* Bootstrap routine */
431
432 int32 ptr_getw (UNIT *uptr)
433 {
434 int32 i, tmp, word;
435
436 for (i = word = 0; i < 3;) {
437 if ((tmp = getc (uptr->fileref)) == EOF) return -1;
438 uptr->pos = uptr->pos + 1;
439 if (tmp & 0200) {
440 word = (word << 6) | (tmp & 077);
441 i++;
442 }
443 }
444 return word;
445 }
446
447 t_stat ptr_boot (int32 unitno, DEVICE *dptr)
448 {
449 int32 origin, val;
450 int32 fld = TA & EPCMASK;
451
452 for (;;) {
453 if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT;
454 if (((val & 0760000) == OP_DIO) || /* DIO? */
455 ((val & 0760000) == OP_DAC)) { /* hack - Macro1 err */
456 origin = val & DAMASK;
457 if ((val = ptr_getw (&ptr_unit)) < 0) return SCPE_FMT;
458 M[fld | origin] = val;
459 }
460 else if ((val & 0760000) == OP_JMP) { /* JMP? */
461 PC = fld | (val & DAMASK);
462 break;
463 }
464 else return SCPE_FMT; /* bad instr */
465 }
466 return SCPE_OK; /* done */
467 }
468
469 /* Paper tape punch: IOT routine */
470
471 int32 ptp (int32 inst, int32 dev, int32 dat)
472 {
473 iosta = iosta & ~IOS_PTP; /* clear flag */
474 ptp_unit.buf = (dev == 0006)? ((dat >> 12) | 0200): (dat & 0377);
475 if (GEN_CPLS (inst)) { /* comp pulse? */
476 ios = 0;
477 cpls = cpls | CPLS_PTP;
478 }
479 else cpls = cpls & ~CPLS_PTP;
480 sim_activate (&ptp_unit, ptp_unit.wait); /* start unit */
481 return dat;
482 }
483
484 /* Unit service */
485
486 t_stat ptp_svc (UNIT *uptr)
487 {
488 if (cpls & CPLS_PTP) { /* completion pulse? */
489 ios = 1; /* restart */
490 cpls = cpls & ~CPLS_PTP;
491 }
492 iosta = iosta | IOS_PTP; /* set flag */
493 dev_req_int (ptp_sbs); /* req interrupt */
494 if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
495 return IORETURN (ptp_stopioe, SCPE_UNATT);
496 if (putc (uptr->buf, uptr->fileref) == EOF) { /* I/O error? */
497 perror ("PTP I/O error");
498 clearerr (uptr->fileref);
499 return SCPE_IOERR;
500 }
501 uptr->pos = uptr->pos + 1;
502 return SCPE_OK;
503 }
504
505 /* Reset routine */
506
507 t_stat ptp_reset (DEVICE *dptr)
508 {
509 ptp_unit.buf = 0; /* clear state */
510 cpls = cpls & ~CPLS_PTP;
511 iosta = iosta & ~IOS_PTP; /* clear flag */
512 sim_cancel (&ptp_unit); /* deactivate unit */
513 return SCPE_OK;
514 }
515
516 /* Typewriter IOT routines */
517
518 int32 tti (int32 inst, int32 dev, int32 dat)
519 {
520 iosta = iosta & ~IOS_TTI; /* clear flag */
521 if (inst & (IO_WAIT | IO_CPLS)) /* wait or sync? */
522 return (STOP_RSRV << IOT_V_REASON) | (tty_buf & 077);
523 return tty_buf & 077;
524 }
525
526 int32 tto (int32 inst, int32 dev, int32 dat)
527 {
528 iosta = iosta & ~IOS_TTO; /* clear flag */
529 tty_buf = dat & TT_WIDTH; /* load buffer */
530 if (GEN_CPLS (inst)) { /* comp pulse? */
531 ios = 0;
532 cpls = cpls | CPLS_TTO;
533 }
534 else cpls = cpls & ~CPLS_TTO;
535 sim_activate (&tto_unit, tto_unit.wait); /* activate unit */
536 return dat;
537 }
538
539 /* Unit service routines */
540
541 t_stat tti_svc (UNIT *uptr)
542 {
543 int32 in, temp;
544
545 sim_activate (uptr, uptr->wait); /* continue poll */
546 if (tti_hold & CW) { /* char waiting? */
547 tty_buf = tti_hold & TT_WIDTH; /* return char */
548 tti_hold = 0; /* not waiting */
549 }
550 else {
551 if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp;
552 if (temp & SCPE_BREAK) return SCPE_OK; /* ignore break */
553 temp = temp & 0177;
554 if (temp == 0177) temp = '\b'; /* rubout? bs */
555 sim_putchar (temp); /* echo */
556 if (temp == '\r') sim_putchar ('\n'); /* cr? add nl */
557 in = ascii_to_fiodec[temp]; /* translate char */
558 if (in == 0) return SCPE_OK; /* no xlation? */
559 if ((in & BOTH) || ((in & UC) == (tty_uc & UC)))
560 tty_buf = in & TT_WIDTH;
561 else { /* must shift */
562 tty_uc = in & UC; /* new case */
563 tty_buf = tty_uc? FIODEC_UC: FIODEC_LC;
564 tti_hold = in | CW; /* set 2nd waiting */
565 }
566 }
567 iosta = iosta | IOS_TTI; /* set flag */
568 dev_req_int (tti_sbs); /* req interrupt */
569 PF = PF | PF_SS_1; /* set prog flag 1 */
570 uptr->pos = uptr->pos + 1;
571 return SCPE_OK;
572 }
573
574 t_stat tto_svc (UNIT *uptr)
575 {
576 int32 c;
577 t_stat r;
578
579 if (tty_buf == FIODEC_UC) tty_uc = UC; /* upper case? */
580 else if (tty_buf == FIODEC_LC) tty_uc = 0; /* lower case? */
581 else {
582 c = fiodec_to_ascii[tty_buf | tty_uc]; /* translate */
583 if (c && ((r = sim_putchar_s (c)) != SCPE_OK)) { /* output; error? */
584 sim_activate (uptr, uptr->wait); /* retry */
585 return ((r == SCPE_STALL)? SCPE_OK: r);
586 }
587 }
588 if (cpls & CPLS_TTO) { /* completion pulse? */
589 ios = 1; /* restart */
590 cpls = cpls & ~CPLS_TTO;
591 }
592 iosta = iosta | IOS_TTO; /* set flag */
593 dev_req_int (tto_sbs); /* req interrupt */
594 uptr->pos = uptr->pos + 1;
595 if (c == '\r') { /* cr? add lf */
596 sim_putchar ('\n');
597 uptr->pos = uptr->pos + 1;
598 }
599 return SCPE_OK;
600 }
601
602 /* Reset routine */
603
604 t_stat tty_reset (DEVICE *dptr)
605 {
606 tty_buf = 0; /* clear buffer */
607 tty_uc = 0; /* clear case */
608 tti_hold = 0; /* clear hold buf */
609 cpls = cpls & ~CPLS_TTO;
610 iosta = (iosta & ~IOS_TTI) | IOS_TTO; /* clear flag */
611 sim_activate (&tti_unit, tti_unit.wait); /* activate keyboard */
612 sim_cancel (&tto_unit); /* stop printer */
613 return SCPE_OK;
614 }