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