First Commit of my working state
[simh.git] / PDP8 / pdp8_tt.c
CommitLineData
196ba1fc
PH
1/* pdp8_tt.c: PDP-8 console terminal simulator\r
2\r
3 Copyright (c) 1993-2007, 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,tto KL8E terminal input/output\r
27\r
28 18-Jun-07 RMS Added UNIT_IDLE flag to console input\r
29 18-Oct-06 RMS Synced keyboard to clock\r
30 30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode\r
31 22-Nov-05 RMS Revised for new terminal processing routines\r
32 28-May-04 RMS Removed SET TTI CTRL-C\r
33 29-Dec-03 RMS Added console output backpressure support\r
34 25-Apr-03 RMS Revised for extended file support\r
35 02-Mar-02 RMS Added SET TTI CTRL-C\r
36 22-Dec-02 RMS Added break support\r
37 01-Nov-02 RMS Added 7B/8B support\r
38 04-Oct-02 RMS Added DIBs, device number support\r
39 30-May-02 RMS Widened POS to 32b\r
40 07-Sep-01 RMS Moved function prototypes\r
41*/\r
42\r
43#include "pdp8_defs.h"\r
44#include <ctype.h>\r
45\r
46extern int32 int_req, int_enable, dev_done, stop_inst;\r
47extern int32 tmxr_poll;\r
48\r
49int32 tti (int32 IR, int32 AC);\r
50int32 tto (int32 IR, int32 AC);\r
51t_stat tti_svc (UNIT *uptr);\r
52t_stat tto_svc (UNIT *uptr);\r
53t_stat tti_reset (DEVICE *dptr);\r
54t_stat tto_reset (DEVICE *dptr);\r
55t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc);\r
56\r
57/* TTI data structures\r
58\r
59 tti_dev TTI device descriptor\r
60 tti_unit TTI unit descriptor\r
61 tti_reg TTI register list\r
62 tti_mod TTI modifiers list\r
63*/\r
64\r
65DIB tti_dib = { DEV_TTI, 1, { &tti } };\r
66\r
67UNIT tti_unit = { UDATA (&tti_svc, UNIT_IDLE|TT_MODE_KSR, 0), 0 };\r
68\r
69REG tti_reg[] = {\r
70 { ORDATA (BUF, tti_unit.buf, 8) },\r
71 { FLDATA (DONE, dev_done, INT_V_TTI) },\r
72 { FLDATA (ENABLE, int_enable, INT_V_TTI) },\r
73 { FLDATA (INT, int_req, INT_V_TTI) },\r
74 { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },\r
75 { DRDATA (TIME, tti_unit.wait, 24), PV_LEFT },\r
76 { NULL }\r
77 };\r
78\r
79MTAB tti_mod[] = {\r
80 { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode },\r
81 { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },\r
82 { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },\r
83 { TT_MODE, TT_MODE_7P, "7b", NULL, NULL },\r
84 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev, NULL },\r
85 { 0 }\r
86 };\r
87\r
88DEVICE tti_dev = {\r
89 "TTI", &tti_unit, tti_reg, tti_mod,\r
90 1, 10, 31, 1, 8, 8,\r
91 NULL, NULL, &tti_reset,\r
92 NULL, NULL, NULL,\r
93 &tti_dib, 0\r
94 };\r
95\r
96/* TTO data structures\r
97\r
98 tto_dev TTO device descriptor\r
99 tto_unit TTO unit descriptor\r
100 tto_reg TTO register list\r
101*/\r
102\r
103DIB tto_dib = { DEV_TTO, 1, { &tto } };\r
104\r
105UNIT tto_unit = { UDATA (&tto_svc, TT_MODE_KSR, 0), SERIAL_OUT_WAIT };\r
106\r
107REG tto_reg[] = {\r
108 { ORDATA (BUF, tto_unit.buf, 8) },\r
109 { FLDATA (DONE, dev_done, INT_V_TTO) },\r
110 { FLDATA (ENABLE, int_enable, INT_V_TTO) },\r
111 { FLDATA (INT, int_req, INT_V_TTO) },\r
112 { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },\r
113 { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },\r
114 { NULL }\r
115 };\r
116\r
117MTAB tto_mod[] = {\r
118 { TT_MODE, TT_MODE_KSR, "KSR", "KSR", &tty_set_mode },\r
119 { TT_MODE, TT_MODE_7B, "7b", "7B", &tty_set_mode },\r
120 { TT_MODE, TT_MODE_8B, "8b", "8B", &tty_set_mode },\r
121 { TT_MODE, TT_MODE_7P, "7p", "7P", &tty_set_mode },\r
122 { MTAB_XTD|MTAB_VDV, 0, "DEVNO", NULL, NULL, &show_dev },\r
123 { 0 }\r
124 };\r
125\r
126DEVICE tto_dev = {\r
127 "TTO", &tto_unit, tto_reg, tto_mod,\r
128 1, 10, 31, 1, 8, 8,\r
129 NULL, NULL, &tto_reset, \r
130 NULL, NULL, NULL,\r
131 &tto_dib, 0\r
132 };\r
133\r
134/* Terminal input: IOT routine */\r
135\r
136int32 tti (int32 IR, int32 AC)\r
137{\r
138switch (IR & 07) { /* decode IR<9:11> */\r
139 case 0: /* KCF */\r
140 dev_done = dev_done & ~INT_TTI; /* clear flag */\r
141 int_req = int_req & ~INT_TTI;\r
142 return AC;\r
143\r
144 case 1: /* KSF */\r
145 return (dev_done & INT_TTI)? IOT_SKP + AC: AC;\r
146\r
147 case 2: /* KCC */\r
148 dev_done = dev_done & ~INT_TTI; /* clear flag */\r
149 int_req = int_req & ~INT_TTI;\r
150 return 0; /* clear AC */\r
151\r
152 case 4: /* KRS */\r
153 return (AC | tti_unit.buf); /* return buffer */\r
154\r
155 case 5: /* KIE */\r
156 if (AC & 1) int_enable = int_enable | (INT_TTI+INT_TTO);\r
157 else int_enable = int_enable & ~(INT_TTI+INT_TTO);\r
158 int_req = INT_UPDATE; /* update interrupts */\r
159 return AC;\r
160\r
161 case 6: /* KRB */\r
162 dev_done = dev_done & ~INT_TTI; /* clear flag */\r
163 int_req = int_req & ~INT_TTI;\r
164 return (tti_unit.buf); /* return buffer */\r
165\r
166 default:\r
167 return (stop_inst << IOT_V_REASON) + AC;\r
168 } /* end switch */\r
169}\r
170\r
171/* Unit service */\r
172\r
173t_stat tti_svc (UNIT *uptr)\r
174{\r
175int32 c;\r
176\r
177sim_activate (uptr, KBD_WAIT (uptr->wait, tmxr_poll)); /* continue poll */\r
178if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */\r
179if (c & SCPE_BREAK) uptr->buf = 0; /* break? */\r
180else uptr->buf = sim_tt_inpcvt (c, TT_GET_MODE (uptr->flags) | TTUF_KSR);\r
181uptr->pos = uptr->pos + 1;\r
182dev_done = dev_done | INT_TTI; /* set done */\r
183int_req = INT_UPDATE; /* update interrupts */\r
184return SCPE_OK;\r
185}\r
186\r
187/* Reset routine */\r
188\r
189t_stat tti_reset (DEVICE *dptr)\r
190{\r
191tti_unit.buf = 0;\r
192dev_done = dev_done & ~INT_TTI; /* clear done, int */\r
193int_req = int_req & ~INT_TTI;\r
194int_enable = int_enable | INT_TTI; /* set enable */\r
195sim_activate_abs (&tti_unit, KBD_WAIT (tti_unit.wait, tmxr_poll));\r
196return SCPE_OK;\r
197}\r
198\r
199/* Terminal output: IOT routine */\r
200\r
201int32 tto (int32 IR, int32 AC)\r
202{\r
203switch (IR & 07) { /* decode IR<9:11> */\r
204\r
205 case 0: /* TLF */\r
206 dev_done = dev_done | INT_TTO; /* set flag */\r
207 int_req = INT_UPDATE; /* update interrupts */\r
208 return AC;\r
209\r
210 case 1: /* TSF */\r
211 return (dev_done & INT_TTO)? IOT_SKP + AC: AC;\r
212\r
213 case 2: /* TCF */\r
214 dev_done = dev_done & ~INT_TTO; /* clear flag */\r
215 int_req = int_req & ~INT_TTO; /* clear int req */\r
216 return AC;\r
217\r
218 case 5: /* SPI */\r
219 return (int_req & (INT_TTI+INT_TTO))? IOT_SKP + AC: AC;\r
220\r
221 case 6: /* TLS */\r
222 dev_done = dev_done & ~INT_TTO; /* clear flag */\r
223 int_req = int_req & ~INT_TTO; /* clear int req */\r
224 case 4: /* TPC */\r
225 sim_activate (&tto_unit, tto_unit.wait); /* activate unit */\r
226 tto_unit.buf = AC; /* load buffer */\r
227 return AC;\r
228\r
229 default:\r
230 return (stop_inst << IOT_V_REASON) + AC;\r
231 } /* end switch */\r
232}\r
233\r
234/* Unit service */\r
235\r
236t_stat tto_svc (UNIT *uptr)\r
237{\r
238int32 c;\r
239t_stat r;\r
240\r
241c = sim_tt_outcvt (uptr->buf, TT_GET_MODE (uptr->flags) | TTUF_KSR);\r
242if (c >= 0) {\r
243 if ((r = sim_putchar_s (c)) != SCPE_OK) { /* output char; error? */\r
244 sim_activate (uptr, uptr->wait); /* try again */\r
245 return ((r == SCPE_STALL)? SCPE_OK: r); /* if !stall, report */\r
246 }\r
247 }\r
248dev_done = dev_done | INT_TTO; /* set done */\r
249int_req = INT_UPDATE; /* update interrupts */\r
250uptr->pos = uptr->pos + 1;\r
251return SCPE_OK;\r
252}\r
253\r
254/* Reset routine */\r
255\r
256t_stat tto_reset (DEVICE *dptr)\r
257{\r
258tto_unit.buf = 0;\r
259dev_done = dev_done & ~INT_TTO; /* clear done, int */\r
260int_req = int_req & ~INT_TTO;\r
261int_enable = int_enable | INT_TTO; /* set enable */\r
262sim_cancel (&tto_unit); /* deactivate unit */\r
263return SCPE_OK;\r
264}\r
265\r
266t_stat tty_set_mode (UNIT *uptr, int32 val, char *cptr, void *desc)\r
267{\r
268tti_unit.flags = (tti_unit.flags & ~TT_MODE) | val;\r
269tto_unit.flags = (tto_unit.flags & ~TT_MODE) | val;\r
270return SCPE_OK;\r
271}\r