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