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