First Commit of my working state
[simh.git] / LGP / lgp_stddev.c
1 /* lgp_stddev.c: LGP-30 standard devices
2
3 Copyright (c) 2004-2005, 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 tti typewriter input (keyboard and reader)
27 tto typewriter output (printer and punch)
28 ptr high speed reader
29 ptpp high speed punch
30 */
31
32 #include "lgp_defs.h"
33 #include <ctype.h>
34
35 uint32 tt_wait = WPS / 10;
36 uint32 tti_buf = 0;
37 uint32 tti_rdy = 0;
38 uint32 tto_uc = 0;
39 uint32 tto_buf = 0;
40 uint32 ttr_stopioe = 1;
41 uint32 ptr_rdy = 0;
42 uint32 ptr_stopioe = 1;
43 uint32 ptp_stopioe = 1;
44
45 extern uint32 A;
46 extern uint32 inp_strt, inp_done;
47 extern uint32 out_strt, out_done;
48 extern UNIT cpu_unit;
49 extern int32 sim_switches;
50
51 t_stat tti_svc (UNIT *uptr);
52 t_stat ttr_svc (UNIT *uptr);
53 t_stat tto_svc (UNIT *uptr);
54 t_stat tti_reset (DEVICE *uptr);
55 t_stat tto_reset (DEVICE *uptr);
56 t_stat ptr_svc (UNIT *uptr);
57 t_stat ptp_svc (UNIT *uptr);
58 t_stat ptr_reset (DEVICE *uptr);
59 t_stat ptp_reset (DEVICE *uptr);
60 t_stat tap_attach (UNIT *uptr, char *cptr);
61 t_stat tap_attable (UNIT *uptr, int32 val, char *cptr, void *desc);
62 t_stat read_reader (UNIT *uptr, int32 stop, int32 *c);
63 t_stat write_tto (int32 flex);
64 t_stat write_punch (UNIT *uptr, int32 flex);
65 t_stat tti_rdrss (UNIT *uptr, int32 val, char *cptr, void *desc);
66 t_stat punch_feed (UNIT *uptr, int32 val, char *cptr, void *desc);
67 t_stat send_start (UNIT *uptr, int32 val, char *cptr, void *desc);
68
69 extern uint32 shift_in (uint32 a, uint32 dat, uint32 sh4);
70
71 /* Conversion tables */
72
73 const int32 flex_to_ascii[128] = {
74 -1 , 'z', '0', ' ', '>', 'b', '1', '-',
75 '<' , 'y', '2', '+', '|', 'r', '3', ';',
76 '\r', 'i', '4', '/','\\', 'd', '5', '.',
77 '\t', 'n', '6', ',', -1 , 'm', '7', 'v',
78 '\'', 'p', '8', 'o', -1 , 'e', '9', 'x',
79 -1 , 'u', 'f', -1 , -1 , 't', 'g', -1 ,
80 -1 , 'h', 'j', -1 , -1 , 'c', 'k', -1 ,
81 -1 , 'a', 'q', -1 , -1 , 's', 'w', 0 ,
82
83 -1 , 'Z', ')', ' ', -1 , 'B', 'L', '_',
84 -1 , 'Y', '*', '=', '|', 'R', '"', ':',
85 '\r', 'I', '^', '?','\\', 'D', '%', ']',
86 '\t', 'N', '$', '[', -1 , 'M', '~', 'V',
87 '\'', 'P', '#', 'O', -1 , 'E', '(', 'X',
88 -1 , 'U', 'F', -1 , -1 , 'T', 'G', -1 ,
89 -1 , 'H', 'J', -1 , -1 , 'C', 'K', -1 ,
90 -1 , 'A', 'Q', -1 , -1 , 'S', 'W', 0
91 };
92
93 const int32 ascii_to_flex[128] = {
94 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
95 024, 030, -1 , -1 , -1 , 020, -1 , -1 ,
96 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
97 -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
98 003, -1 , 016, 042, 032, 026, -1 , 040,
99 046, 001, 012, 013, 033, 007, 027, 023,
100 002, 006, 012, 016, 022, 026, 032, 036,
101 042, 046, 017, 017, 004, 013, 010, 023,
102 -1 , 071, 005, 065, 025, 045, 052, 056,
103 061, 021, 062, 066, 006, 035, 031, 043,
104 041, 072, 015, 075, 055, 051, 037, 076,
105 047, 011, 001, 033, -1 , 027, 022, 007,
106 - 1, 071, 005, 065, 025, 045, 052, 056,
107 061, 021, 062, 066, 006, 035, 031, 043,
108 041, 072, 015, 075, 055, 051, 037, 076,
109 047, 011, 001, -1 , 014, -1 , 036, 077
110 };
111
112 static const uint8 flex_inp_valid[64] = {
113 1, 1, 1, 1, 0, 1, 1, 1,
114 0, 1, 1, 1, 0, 1, 1, 1,
115 0, 1, 1, 1, 0, 1, 1, 1,
116 0, 1, 1, 1, 0, 1, 1, 1,
117 1, 1, 1, 1, 0, 1, 1, 1,
118 0, 1, 1, 1, 0, 1, 1, 1,
119 0, 1, 1, 1, 0, 1, 1, 1,
120 0, 1, 1, 1, 0, 1, 1, 1
121 };
122
123 /* TTI data structures
124
125 tti_dev TTI device descriptor
126 tti_unit TTI unit descriptor
127 tti_mod TTI modifier list
128 tti_reg TTI register list
129 */
130
131 UNIT tti_unit[] = {
132 { UDATA (&tti_svc, 0, 0) },
133 { UDATA (&ttr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) }
134 };
135
136 REG tti_reg[] = {
137 { HRDATA (BUF, tti_buf, 6) },
138 { FLDATA (RDY, tti_rdy, 0) },
139 { DRDATA (KPOS, tti_unit[0].pos, T_ADDR_W), PV_LEFT },
140 { DRDATA (RPOS, tti_unit[1].pos, T_ADDR_W), PV_LEFT },
141 { DRDATA (TIME, tt_wait, 24), REG_NZ + PV_LEFT },
142 { FLDATA (STOP_IOE, ttr_stopioe, 0) },
143 { NULL }
144 };
145
146 MTAB tti_mod[] = {
147 { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
148 { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
149 { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
150 "file is Flex", NULL },
151 { UNIT_ATT+UNIT_FLEX, UNIT_ATT,
152 "file is ASCII", NULL },
153 { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
154 "default is Flex", NULL },
155 { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
156 "default is ASCII", NULL },
157 { UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE+UNIT_NOCS,
158 "ignore conditional stop", "NOCSTOP", &tap_attable },
159 { UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE ,
160 NULL, "CSTOP", &tap_attable },
161 { MTAB_XTD|MTAB_VDV, 0, NULL, "START", &send_start },
162 { MTAB_XTD|MTAB_VDV, 1, NULL, "RSTART", &tti_rdrss },
163 { MTAB_XTD|MTAB_VDV, 0, NULL, "RSTOP", &tti_rdrss },
164 { 0 }
165 };
166
167 DEVICE tti_dev = {
168 "TTI", tti_unit, tti_reg, tti_mod,
169 2, 10, 31, 1, 16, 7,
170 NULL, NULL, &tti_reset,
171 NULL, &tap_attach, NULL
172 };
173
174 /* TTO data structures
175
176 tto_dev TTO device descriptor
177 tto_unit TTO unit descriptor
178 tto_mod TTO modifier list
179 tto_reg TTO register list
180 */
181
182 UNIT tto_unit[] = {
183 { UDATA (&tto_svc, 0, 0) },
184 { UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) }
185 };
186
187 REG tto_reg[] = {
188 { HRDATA (BUF, tto_buf, 6) },
189 { FLDATA (UC, tto_uc, 0) },
190 { DRDATA (TPOS, tto_unit[0].pos, T_ADDR_W), PV_LEFT },
191 { DRDATA (PPOS, tto_unit[1].pos, T_ADDR_W), PV_LEFT },
192 { DRDATA (TIME, tt_wait, 24), PV_LEFT },
193 { NULL }
194 };
195
196 MTAB tto_mod[] = {
197 { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
198 { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
199 { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
200 "file is Flex", NULL },
201 { UNIT_ATT+UNIT_FLEX, UNIT_ATT,
202 "file is ASCII", NULL },
203 { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
204 "default is Flex", NULL },
205 { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
206 "default is ASCII", NULL },
207 { MTAB_XTD|MTAB_VUN, 0, NULL, "FEED", &punch_feed },
208 { 0 }
209 };
210
211 DEVICE tto_dev = {
212 "TTO", tto_unit, tto_reg, tto_mod,
213 2, 10, 31, 1, 16, 7,
214 NULL, NULL, &tto_reset,
215 NULL, &tap_attach, NULL
216 };
217
218 /* PTR data structures
219
220 ptr_dev PTR device descriptor
221 ptr_unit PTR unit descriptor
222 ptr_mod PTR modifier list
223 ptr_reg PTR register list
224 */
225
226 UNIT ptr_unit = {
227 UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), WPS / 200
228 };
229
230 REG ptr_reg[] = {
231 { HRDATA (BUF, ptr_unit.buf, 6) },
232 { FLDATA (RDY, ptr_rdy, 0) },
233 { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
234 { DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT },
235 { FLDATA (STOP_IOE, ptr_stopioe, 0) },
236 { NULL }
237 };
238
239 MTAB ptr_mod[] = {
240 { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
241 { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
242 { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
243 "file is Flex", NULL },
244 { UNIT_ATT+UNIT_FLEX, UNIT_ATT,
245 "file is ASCII", NULL },
246 { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
247 "default is Flex", NULL },
248 { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
249 "default is ASCII", NULL },
250 { 0 }
251 };
252
253 DEVICE ptr_dev = {
254 "PTR", &ptr_unit, ptr_reg, ptr_mod,
255 1, 10, 31, 1, 16, 7,
256 NULL, NULL, &ptr_reset,
257 NULL, &tap_attach, NULL
258 };
259
260 /* PTP data structures
261
262 ptp_dev PTP device descriptor
263 ptp_unit PTP unit descriptor
264 ptp_mod PTP modifier list
265 ptp_reg PTP register list
266 */
267
268 UNIT ptp_unit = {
269 UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), WPS / 20
270 };
271
272 REG ptp_reg[] = {
273 { ORDATA (BUF, ptp_unit.buf, 8) },
274 { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
275 { DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
276 { FLDATA (STOP_IOE, ptp_stopioe, 0) },
277 { NULL }
278 };
279
280 MTAB ptp_mod[] = {
281 { UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
282 { UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
283 { UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
284 "file is Flex", NULL },
285 { UNIT_ATT+UNIT_FLEX, UNIT_ATT,
286 "file is ASCII", NULL },
287 { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
288 "default is Flex", NULL },
289 { UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
290 "default is ASCII", NULL },
291 { 0 }
292 };
293
294 DEVICE ptp_dev = {
295 "PTP", &ptp_unit, ptp_reg, ptp_mod,
296 1, 10, 31, 1, 16, 7,
297 NULL, NULL, &ptp_reset,
298 NULL, &tap_attach, NULL
299 };
300
301 /* Input instruction */
302
303 void op_i_strt (uint32 dev)
304 {
305 switch (dev) { /* case on device */
306
307 case DEV_PT: /* ptr */
308 sim_activate (&ptr_unit, ptr_unit.wait); /* activate */
309 break;
310
311 case DEV_TT: /* tti/ttr */
312 if (Q_MANI) sim_putchar ('`'); /* manual input? */
313 else sim_activate (&tti_unit[1], tt_wait); /* no, must be ttr */
314 break;
315 }
316 return;
317 }
318
319 t_stat op_i (uint32 dev, uint32 ch, uint32 sh4)
320 {
321 if (Q_LGP21 && out_strt) return STOP_STALL; /* LGP-21? must be idle */
322 if (!inp_strt) { /* input started? */
323 inp_strt = 1; /* no, set start */
324 inp_done = 0; /* clear done */
325 A = shift_in (A, ch, sh4);
326 tti_rdy = ptr_rdy = 0; /* no input */
327 if (Q_LGP21 || Q_INPT) op_i_strt (dev); /* LGP-21 or PTR? start */
328 }
329 switch (dev) { /* case on device */
330
331 case DEV_PT: /* ptr */
332 if (ptr_rdy) { /* char ready? */
333 ptr_rdy = 0; /* reset ready */
334 if ((ptr_unit.buf != FLEX_DEL) && /* ignore delete and */
335 (!Q_LGP21 || ((ptr_unit.buf & 3) == 2))) /* LGP-21 4b? zone != 2 */
336 A = shift_in (A, ptr_unit.buf, sh4); /* shift data in */
337 }
338 break;
339
340 case DEV_TT: /* tti/ttr */
341 if (tti_rdy) { /* char ready? */
342 tti_rdy = 0; /* reset ready */
343 if ((tti_buf != FLEX_DEL) && /* ignore delete and */
344 (!Q_LGP21 || ((tti_buf & 3) != 0))) /* LGP-21 4b? zone == 0 */
345 A = shift_in (A, tti_buf, sh4); /* shift data in */
346 }
347 break;
348
349 default: /* nx device */
350 return STOP_NXDEV; /* return error */
351 }
352
353 if (inp_done) { /* done? */
354 inp_strt = inp_done = 0; /* clear start, done */
355 return SCPE_OK; /* no stall */
356 }
357 return STOP_STALL; /* stall */
358 }
359
360 /* Terminal keyboard unit service */
361
362 t_stat tti_svc (UNIT *uptr)
363 {
364 int32 c, flex;
365
366 sim_activate (uptr, tt_wait); /* continue poll */
367 if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
368 flex = ascii_to_flex[c & 0x1FF]; /* cvt to flex */
369 if (flex > 0) { /* it's a typewriter... */
370 write_tto (flex); /* always echos */
371 if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
372 write_punch (&tto_unit[1], tto_buf); /* punch to ttp */
373 }
374 else write_tto ('\a'); /* don't echo bad */
375 if (Q_MANI && (flex > 0) && flex_inp_valid[flex]) { /* wanted, valid? */
376 if (flex == FLEX_CSTOP) inp_done = 1; /* conditional stop? */
377 else tti_rdy = 1; /* no, set ready */
378 tti_buf = flex; /* save char */
379 uptr->pos = uptr->pos + 1;
380 }
381 return SCPE_OK;
382 }
383
384 /* Terminal reader unit service */
385
386 t_stat ttr_svc (UNIT *uptr)
387 {
388 t_stat r;
389
390 if (r = read_reader (uptr, ttr_stopioe, (int32 *) &tti_buf)) return r;
391 if (!(uptr->flags & UNIT_NOCS) && /* cstop enable? */
392 (tti_buf == FLEX_CSTOP)) inp_done = 1; /* cond stop? */
393 else {
394 tti_rdy = 1; /* no, set ready */
395 sim_activate (uptr, tt_wait); /* cont reading */
396 }
397 write_tto (tti_buf); /* echo to tto */
398 if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
399 return write_punch (&tto_unit[1], tti_buf); /* punch to ttp */
400 return SCPE_OK;
401 }
402
403 /* Paper tape reader unit service */
404
405 t_stat ptr_svc (UNIT *uptr)
406 {
407 t_stat r;
408
409 if (r = read_reader (uptr, ptr_stopioe, &uptr->buf)) return r;
410 if (uptr->buf == FLEX_CSTOP) inp_done = 1; /* cond stop? */
411 else {
412 ptr_rdy = 1; /* no, set ready */
413 sim_activate (uptr, uptr->wait); /* cont reading */
414 }
415 return SCPE_OK;
416 }
417
418 /* Output instruction */
419
420 t_stat op_p (uint32 dev, uint32 ch)
421 {
422 switch (dev) { /* case on device */
423
424 case DEV_PT: /* paper tape punch */
425 if (sim_is_active (&ptp_unit)) /* busy? */
426 return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */
427 ptp_unit.buf = ch; /* save char */
428 sim_activate (&ptp_unit, ptp_unit.wait); /* activate ptp */
429 break;
430
431 case DEV_TT: /* typewriter */
432 if (ch == 0) { /* start input? */
433 if (!Q_LGP21 && !Q_INPT) /* ignore if LGP-21, ptr */
434 op_i_strt (DEV_TT); /* start tti */
435 return SCPE_OK; /* no stall */
436 }
437 if (sim_is_active (&tto_unit[0])) /* busy? */
438 return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */
439 tto_buf = ch; /* save char */
440 sim_activate (&tto_unit[0], tt_wait); /* activate tto */
441 break;
442
443 default: /* unknown */
444 return STOP_NXDEV; /* return error */
445 }
446
447 if (out_strt == 0) { /* output started? */
448 out_strt = 1; /* flag start */
449 out_done = 0; /* clear done */
450 }
451 return SCPE_OK; /* no stall */
452 }
453
454 /* Terminal printer unit service */
455
456 t_stat tto_svc (UNIT *uptr)
457 {
458 t_stat r;
459
460 if ((r = write_tto (tto_buf)) != SCPE_OK) { /* output; error? */
461 sim_activate (uptr, tt_wait); /* try again */
462 return ((r == SCPE_STALL)? SCPE_OK: r); /* !stall? report */
463 }
464 out_strt = 0;
465 out_done = 1;
466 if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
467 return write_punch (&tto_unit[1], tto_buf); /* punch to ttp */
468 return SCPE_OK;
469 }
470
471 /* Paper tape punch unit service */
472
473 t_stat ptp_svc (UNIT *uptr)
474 {
475 out_strt = 0;
476 out_done = 1;
477 if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
478 return IORETURN (ptp_stopioe, SCPE_UNATT); /* error */
479 return write_punch (uptr, uptr->buf); /* write to ptp */
480 }
481
482 /* Utility routines */
483
484 t_stat read_reader (UNIT *uptr, int32 stop, int32 *fl)
485 {
486 int32 ch, flex;
487
488 if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
489 return IORETURN (stop, SCPE_UNATT);
490 do {
491 if ((ch = getc (uptr->fileref)) == EOF) { /* read char */
492 if (feof (uptr->fileref)) { /* err or eof? */
493 if (stop) printf ("Reader end of file\n");
494 else return SCPE_OK;
495 }
496 else perror ("Reader I/O error");
497 clearerr (uptr->fileref);
498 return SCPE_IOERR;
499 }
500 if (uptr->flags & UNIT_FLEX) /* transposed flex? */
501 flex = ((ch << 1) | (ch >> 5)) & 0x3F; /* undo 612345 */
502 else if (ch == '#') { /* encoded? */
503 int32 d1 = getc (uptr->fileref); /* get 2 digits */
504 int32 d2 = getc (uptr->fileref);
505 if ((d1 == EOF) || (d2 == EOF)) { /* error? */
506 if (feof (uptr->fileref)) { /* eof? */
507 if (stop) printf ("Reader end of file\n");
508 else return SCPE_OK;
509 }
510 else perror ("Reader I/O error");
511 clearerr (uptr->fileref);
512 return SCPE_IOERR;
513 }
514 flex = (((d1 - '0') * 10) + (d2 - '0')) & 0x3F;
515 uptr->pos = uptr->pos + 2;
516 }
517 else flex = ascii_to_flex[ch & 0x7F]; /* convert */
518 uptr->pos = uptr->pos + 1;
519 } while (flex < 0); /* until valid */
520 *fl = flex; /* return char */
521 return SCPE_OK;
522 }
523
524 t_stat write_tto (int32 flex)
525 {
526 int32 ch;
527 t_stat r;
528
529 if (flex == FLEX_UC) tto_uc = 1; /* UC? set state */
530 else if (flex == FLEX_LC) tto_uc = 0; /* LC? set state */
531 else {
532 if (flex == FLEX_BS) ch = '\b'; /* backspace? */
533 else ch = flex_to_ascii[flex | (tto_uc << 6)]; /* cvt flex to ascii */
534 if (ch > 0) { /* legit? */
535 if (r = sim_putchar_s (ch)) return r; /* write char */
536 tto_unit[0].pos = tto_unit[0].pos + 1;
537 if (flex == FLEX_CR) { /* cr? */
538 sim_putchar ('\n'); /* add lf */
539 tto_unit[0].pos = tto_unit[0].pos + 1;
540 }
541 }
542 }
543 return SCPE_OK;
544 }
545
546 t_stat write_punch (UNIT *uptr, int32 flex)
547 {
548 int32 c, sta;
549
550 if (uptr->flags & UNIT_FLEX) /* transposed flex? */
551 c = ((flex >> 1) | (flex << 5)) & 0x3F; /* reorder to 612345 */
552 else c = flex_to_ascii[flex]; /* convert to ASCII */
553 if (c >= 0) sta = fputc (c, uptr->fileref); /* valid? */
554 else sta = fprintf (uptr->fileref, "#%02d", flex); /* no, encode */
555 if (sta == EOF) { /* error? */
556 perror ("Punch I/O error"); /* error? */
557 clearerr (uptr->fileref);
558 return SCPE_IOERR;
559 }
560 uptr->pos = uptr->pos + ((c >= 0)? 1: 3); /* incr position */
561 return SCPE_OK;
562 }
563
564 /* Reset routines */
565
566 t_stat tti_reset (DEVICE *dptr)
567 {
568 sim_activate (&tti_unit[0], tt_wait);
569 sim_cancel (&tti_unit[1]);
570 tti_buf = 0;
571 tti_rdy = 0;
572 return SCPE_OK;
573 }
574
575 t_stat tto_reset (DEVICE *dptr)
576 {
577 sim_cancel (&tto_unit[0]);
578 tto_buf = 0;
579 tto_uc = 0;
580 return SCPE_OK;
581 }
582
583 t_stat ptr_reset (DEVICE *dptr)
584 {
585 sim_cancel (&ptr_unit);
586 ptr_unit.buf = 0;
587 ptr_rdy = 0;
588 return SCPE_OK;
589 }
590
591 t_stat ptp_reset (DEVICE *dptr)
592 {
593 sim_cancel (&ptp_unit);
594 ptp_unit.buf = 0;
595 return SCPE_OK;
596 }
597
598 /* Attach paper tape unit */
599
600 t_stat tap_attach (UNIT *uptr, char *cptr)
601 {
602 t_stat r;
603
604 if ((r = attach_unit (uptr,cptr)) != SCPE_OK) return r;
605 if ((sim_switches & SWMASK ('F')) ||
606 ((uptr->flags & UNIT_FLEX_D) && !(sim_switches & SWMASK ('A'))))
607 uptr->flags = uptr->flags | UNIT_FLEX;
608 else uptr->flags = uptr->flags & ~UNIT_FLEX;
609 return SCPE_OK;
610 }
611
612 /* Validate unit is attachable */
613
614 t_stat tap_attable (UNIT *uptr, int32 val, char *cptr, void *desc)
615 {
616 if (uptr->flags & UNIT_ATTABLE) return SCPE_OK;
617 return SCPE_NOFNC;
618 }
619
620 /* Typewriter reader start/stop */
621
622 t_stat tti_rdrss (UNIT *uptr, int32 val, char *cptr, void *desc)
623 {
624 if (val) {
625 if ((tti_unit[1].flags & UNIT_ATT) == 0) return SCPE_UNATT;
626 sim_activate (&tti_unit[1], tt_wait);
627 }
628 else sim_cancel (&tti_unit[1]);
629 return SCPE_OK;
630 }
631
632 /* Punch feed routine */
633
634 t_stat punch_feed (UNIT *uptr, int32 val, char *cptr, void *desc)
635 {
636 int32 cnt;
637 t_stat r;
638
639 if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT;
640 if (cptr) {
641 cnt = (int32) get_uint (cptr, 10, 512, &r);
642 if ((r != SCPE_OK) || (cnt == 0)) return SCPE_ARG;
643 }
644 else cnt = 10;
645 while (cnt-- > 0) {
646 r = write_punch (uptr, 0);
647 if (r != SCPE_OK) return r;
648 }
649 return SCPE_OK;
650 }
651
652 /* Send start signal */
653
654 t_stat send_start (UNIT *uptr, int32 val, char *cptr, void *desc)
655 {
656 if (inp_strt) inp_done = 1;
657 else if (out_strt) out_done = 1;
658 return SCPE_OK;
659 }