First Commit of my working state
[simh.git] / NOVA / eclipse_tt.c
CommitLineData
196ba1fc
PH
1/* eclipse_tt.c: Eclipse console terminal simulator\r
2\r
3 Copyright (c) 1998-2005, Charles E Owen\r
4 Portions copyright (c) 1993-2002, Robert M Supnik\r
5 Written by Charles Owen, used by gracious permission\r
6\r
7 Permission is hereby granted, free of charge, to any person obtaining a\r
8 copy of this software and associated documentation files (the "Software"),\r
9 to deal in the Software without restriction, including without limitation\r
10 the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
11 and/or sell copies of the Software, and to permit persons to whom the\r
12 Software is furnished to do so, subject to the following conditions:\r
13\r
14 The above copyright notice and this permission notice shall be included in\r
15 all copies or substantial portions of the Software.\r
16\r
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\r
20 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
21 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
23\r
24 Except as contained in this notice, the name of the author shall not be\r
25 used in advertising or otherwise to promote the sale, use or other dealings\r
26 in this Software without prior written authorization from the author.\r
27\r
28 tti terminal input\r
29 tto terminal output\r
30\r
31 25-Apr-03 RMS Revised for extended file support\r
32 03-Oct-02 RMS Added DIBs\r
33 30-May-02 RMS Widened POS to 32b\r
34 28-Jan-02 RMS Cleaned up compiler warnings\r
35*/\r
36\r
37#include "nova_defs.h"\r
38\r
39#define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */\r
40#define UNIT_DASHER (1 << UNIT_V_DASHER)\r
41\r
42extern int32 int_req, dev_busy, dev_done, dev_disable;\r
43\r
44int32 tti (int32 pulse, int32 code, int32 AC);\r
45int32 tto (int32 pulse, int32 code, int32 AC);\r
46t_stat tti_svc (UNIT *uptr);\r
47t_stat tto_svc (UNIT *uptr);\r
48t_stat tti_reset (DEVICE *dptr);\r
49t_stat tto_reset (DEVICE *dptr);\r
50t_stat ttx_setmod (UNIT *uptr, int32 value, char *cptr, void *desc);\r
51void translate_in();\r
52int32 translate_out(int32 c);\r
53int32 putseq(char *seq);\r
54\r
55/* TTI data structures\r
56\r
57 tti_dev TTI device descriptor\r
58 tti_unit TTI unit descriptor\r
59 tti_reg TTI register list\r
60 ttx_mod TTI/TTO modifiers list\r
61*/\r
62\r
63DIB tti_dib = { DEV_TTI, INT_TTI, PI_TTI, &tti };\r
64\r
65UNIT tti_unit = { UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT };\r
66\r
67REG tti_reg[] = {\r
68 { ORDATA (BUF, tti_unit.buf, 8) },\r
69 { FLDATA (BUSY, dev_busy, INT_V_TTI) },\r
70 { FLDATA (DONE, dev_done, INT_V_TTI) },\r
71 { FLDATA (DISABLE, dev_disable, INT_V_TTI) },\r
72 { FLDATA (INT, int_req, INT_V_TTI) },\r
73 { DRDATA (POS, tti_unit.pos, T_ADDR_W), PV_LEFT },\r
74 { DRDATA (TIME, tti_unit.wait, 24), REG_NZ + PV_LEFT },\r
75 { NULL }\r
76 };\r
77\r
78MTAB ttx_mod[] = {\r
79 { UNIT_DASHER, 0, "ANSI", "ANSI", &ttx_setmod },\r
80 { UNIT_DASHER, UNIT_DASHER, "Dasher", "DASHER", &ttx_setmod },\r
81 { 0 }\r
82 };\r
83\r
84DEVICE tti_dev = {\r
85 "TTI", &tti_unit, tti_reg, ttx_mod,\r
86 1, 10, 31, 1, 8, 8,\r
87 NULL, NULL, &tti_reset,\r
88 NULL, NULL, NULL,\r
89 &tti_dib, 0\r
90 };\r
91\r
92/* TTO data structures\r
93\r
94 tto_dev TTO device descriptor\r
95 tto_unit TTO unit descriptor\r
96 tto_reg TTO register list\r
97*/\r
98\r
99DIB tto_dib = { DEV_TTO, INT_TTO, PI_TTO, &tto };\r
100\r
101UNIT tto_unit = { UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT };\r
102\r
103REG tto_reg[] = {\r
104 { ORDATA (BUF, tto_unit.buf, 8) },\r
105 { FLDATA (BUSY, dev_busy, INT_V_TTO) },\r
106 { FLDATA (DONE, dev_done, INT_V_TTO) },\r
107 { FLDATA (DISABLE, dev_disable, INT_V_TTO) },\r
108 { FLDATA (INT, int_req, INT_V_TTO) },\r
109 { DRDATA (POS, tto_unit.pos, T_ADDR_W), PV_LEFT },\r
110 { DRDATA (TIME, tto_unit.wait, 24), PV_LEFT },\r
111 { NULL }\r
112 };\r
113\r
114DEVICE tto_dev = {\r
115 "TTO", &tto_unit, tto_reg, ttx_mod,\r
116 1, 10, 31, 1, 8, 8,\r
117 NULL, NULL, &tto_reset,\r
118 NULL, NULL, NULL,\r
119 &tto_dib, 0\r
120 };\r
121 \r
122 \r
123\r
124/* Terminal input: IOT routine */\r
125\r
126int32 tti (int32 pulse, int32 code, int32 AC)\r
127{\r
128int32 iodata;\r
129\r
130iodata = (code == ioDIA)? tti_unit.buf & 0377: 0;\r
131switch (pulse) { /* decode IR<8:9> */\r
132\r
133 case iopS: /* start */\r
134 dev_busy = dev_busy | INT_TTI; /* set busy */\r
135 dev_done = dev_done & ~INT_TTI; /* clear done, int */\r
136 int_req = int_req & ~INT_TTI;\r
137 break;\r
138\r
139 case iopC: /* clear */\r
140 dev_busy = dev_busy & ~INT_TTI; /* clear busy */\r
141 dev_done = dev_done & ~INT_TTI; /* clear done, int */\r
142 int_req = int_req & ~INT_TTI;\r
143 break;\r
144 } /* end switch */\r
145\r
146return iodata;\r
147}\r
148\r
149/* Unit service */\r
150\r
151t_stat tti_svc (UNIT *uptr)\r
152{\r
153int32 temp;\r
154\r
155sim_activate (&tti_unit, tti_unit.wait); /* continue poll */\r
156if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) return temp; /* no char or error? */\r
157tti_unit.buf = temp & 0177;\r
158/* --- BEGIN MODIFIED CODE --- */\r
159if (tti_unit.flags & UNIT_DASHER) /* translate input */\r
160 translate_in();\r
161/* --- END MODIFIED CODE --- */ \r
162dev_busy = dev_busy & ~INT_TTI; /* clear busy */\r
163dev_done = dev_done | INT_TTI; /* set done */\r
164int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);\r
165tti_unit.pos = tti_unit.pos + 1;\r
166return SCPE_OK;\r
167}\r
168\r
169/* -------------------- BEGIN INSERTION -----------------------*/\r
170\r
171int curpos = 0; /* used by translate_out() */\r
172int row = 0, col = 0; /* ditto - for cursor positioning */\r
173int spec200 = 0; /* signals next char is 'special' */\r
174\r
175/* Translation: VT100 input to D200 keycodes. */\r
176\r
177void translate_in()\r
178{\r
179 char rev = 0;\r
180 \r
181 if (tti_unit.buf == '\r')\r
182 rev = '\n'; \r
183 if (tti_unit.buf == '\n')\r
184 rev = '\r'; \r
185 if (rev)\r
186 tti_unit.buf = rev; \r
187}\r
188\r
189/* -------------------- END INSERTION -----------------------*/\r
190\r
191/* Reset routine */\r
192\r
193t_stat tti_reset (DEVICE *dptr)\r
194{\r
195tti_unit.buf = 0;\r
196dev_busy = dev_busy & ~INT_TTI; /* clear busy */\r
197dev_done = dev_done & ~INT_TTI; /* clear done, int */\r
198int_req = int_req & ~INT_TTI;\r
199sim_activate (&tti_unit, tti_unit.wait); /* activate unit */\r
200return SCPE_OK;\r
201}\r
202\r
203/* Terminal output: IOT routine */\r
204\r
205int32 tto (int32 pulse, int32 code, int32 AC)\r
206{\r
207if (code == ioDOA) tto_unit.buf = AC & 0377;\r
208switch (pulse) { /* decode IR<8:9> */\r
209\r
210 case iopS: /* start */\r
211 dev_busy = dev_busy | INT_TTO; /* set busy */\r
212 dev_done = dev_done & ~INT_TTO; /* clear done, int */\r
213 int_req = int_req & ~INT_TTO;\r
214 sim_activate (&tto_unit, tto_unit.wait); /* activate unit */\r
215 break;\r
216\r
217 case iopC: /* clear */\r
218 dev_busy = dev_busy & ~INT_TTO; /* clear busy */\r
219 dev_done = dev_done & ~INT_TTO; /* clear done, int */\r
220 int_req = int_req & ~INT_TTO;\r
221 sim_cancel (&tto_unit); /* deactivate unit */\r
222 break;\r
223 } /* end switch */\r
224\r
225return 0;\r
226}\r
227\r
228/* Unit service */\r
229\r
230t_stat tto_svc (UNIT *uptr)\r
231{\r
232int32 c, temp;\r
233\r
234dev_busy = dev_busy & ~INT_TTO; /* clear busy */\r
235dev_done = dev_done | INT_TTO; /* set done */\r
236int_req = (int_req & ~INT_DEV) | (dev_done & ~dev_disable);\r
237c = tto_unit.buf & 0177;\r
238/* --- BEGIN MODIFIED CODE --- */\r
239if (tto_unit.flags & UNIT_DASHER) {\r
240 if ((temp = translate_out(c)) != SCPE_OK) return temp;\r
241} else { \r
242 if ((temp = sim_putchar (c)) != SCPE_OK) return temp;\r
243 tto_unit.pos = tto_unit.pos + 1;\r
244} \r
245/* --- END MODIFIED CODE --- */ \r
246return SCPE_OK;\r
247}\r
248\r
249/* -------------------- BEGIN INSERTION -----------------------*/\r
250\r
251/* Translation routine - D200 screen controls to VT-100 controls. */\r
252\r
253int32 translate_out(int32 c)\r
254{\r
255 int32 temp;\r
256 char outstr[32];\r
257 \r
258 if (spec200 == 1) { /* Special terminal control seq */\r
259 spec200 = 0;\r
260 switch (c) {\r
261 case 'C': /* read model ID */\r
262 return SCPE_OK;\r
263 case 'E': /* Reverse video off */\r
264 return SCPE_OK;\r
265 case 'D': /* Reverse video on */\r
266 return SCPE_OK;\r
267 default:\r
268 return SCPE_OK; \r
269 }\r
270 }\r
271 if (curpos == 1) { /* 2nd char of cursor position */\r
272 col = c & 0x7f;\r
273 curpos++;\r
274 return (SCPE_OK);\r
275 } \r
276 if (curpos == 2) { /* 3rd char of cursor position */\r
277 row = c & 0x7f;\r
278 curpos = 0;\r
279 sprintf(outstr, "\033[%d;%dH", row+1, col+1);\r
280 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
281 return (SCPE_OK);\r
282 } \r
283 switch (c) { /* Single-char command or data */\r
284 case 003: /* Blink enable */\r
285 break;\r
286 case 004: /* Blink disable */\r
287 break;\r
288 case 005: /* Read cursor address */\r
289 break; \r
290 case 010: /* Cursor home */\r
291 sprintf(outstr, "\033[1;1H");\r
292 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
293 row = col = 0;\r
294 return (SCPE_OK);\r
295 case 012: /* Newline */\r
296 if ((temp = sim_putchar('\r')) != SCPE_OK) return temp;\r
297 tto_unit.pos += 1;\r
298 if ((temp = sim_putchar(c)) != SCPE_OK) return temp;\r
299 tto_unit.pos += 1;\r
300 col = 1;\r
301 row++;\r
302 if (row > 24) row = 1;\r
303 return (SCPE_OK);\r
304 case 013: /* Erase EOL */\r
305 sprintf(outstr, "\033[K");\r
306 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
307 return (SCPE_OK);\r
308 case 014: /* Erase screen */\r
309 sprintf(outstr, "\033[1;1H\033[2J");\r
310 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
311 row = col = 0;\r
312 return (SCPE_OK);\r
313 case 015: /* CR */\r
314 if ((temp = sim_putchar(c)) != SCPE_OK) return temp;\r
315 tto_unit.pos += 1;\r
316 col = 1;\r
317 return (SCPE_OK);\r
318 case 016: /* Blink On */\r
319 sprintf(outstr, "\033[5m");\r
320 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
321 return (SCPE_OK);\r
322 case 017: /* Blink off */\r
323 sprintf(outstr, "\033[25m");\r
324 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
325 return (SCPE_OK);\r
326 case 020: /* Write cursor address */\r
327 curpos = 1;\r
328 return SCPE_OK;\r
329 case 024: /* underscore on */\r
330 sprintf(outstr, "\033[4m");\r
331 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
332 return (SCPE_OK);\r
333 case 025: /* underscore off */\r
334 sprintf(outstr, "\033[24m");\r
335 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
336 return (SCPE_OK);\r
337 break;\r
338 case 027: /* cursor up */\r
339 sprintf(outstr, "\033[A");\r
340 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
341 row--;\r
342 if (row < 1) row = 24;\r
343 return (SCPE_OK);\r
344 case 030: /* cursor right */\r
345 sprintf(outstr, "\033[C");\r
346 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
347 col++;\r
348 if (col > 80) {\r
349 col = 1;\r
350 row++;\r
351 if (row > 24) row = 1;\r
352 } \r
353 return (SCPE_OK);\r
354 case 031: /* Cursor left */\r
355 sprintf(outstr, "\033[D");\r
356 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
357 tto_unit.pos += 1;\r
358 col--;\r
359 if (col < 1) {\r
360 col = 80;\r
361 row--;\r
362 if (row < 1) row = 24;\r
363 } \r
364 return (SCPE_OK);\r
365 case 032: /* Cursor down */\r
366 sprintf(outstr, "\033[B");\r
367 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
368 row++;\r
369 if (row > 24) row = 1;\r
370 return (SCPE_OK);\r
371 case 034: /* Dim on */\r
372 sprintf(outstr, "\033[22m");\r
373 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
374 return (SCPE_OK);\r
375 case 035: /* Dim off */\r
376 sprintf(outstr, "\033[1m");\r
377 if ((temp = putseq(outstr)) != SCPE_OK) return temp;\r
378 return (SCPE_OK);\r
379 case 036: /* Special sequence */\r
380 spec200 = 1;\r
381 return SCPE_OK; \r
382 default: /* ..A character of data */\r
383 if ((temp = sim_putchar(c)) != SCPE_OK) return temp;\r
384 tto_unit.pos += 1;\r
385 col++;\r
386 if (col > 80) {\r
387 col = 1;\r
388 row++;\r
389 if (row > 24) row = 24;\r
390 } \r
391 return (SCPE_OK);\r
392 }\r
393 return SCPE_OK;\r
394}\r
395\r
396int32 putseq(char *seq)\r
397{\r
398 int i, len, temp;\r
399 \r
400 len = strlen(seq);\r
401 for (i = 0; i < len; i++) {\r
402 if ((temp = sim_putchar(seq[i])) != SCPE_OK) \r
403 return temp;\r
404 tto_unit.pos += 1;\r
405 }\r
406 return SCPE_OK; \r
407}\r
408\r
409/* -------------------- END INSERTION -----------------------*/\r
410\r
411/* Reset routine */\r
412\r
413t_stat tto_reset (DEVICE *dptr)\r
414{\r
415tto_unit.buf = 0;\r
416dev_busy = dev_busy & ~INT_TTO; /* clear busy */\r
417dev_done = dev_done & ~INT_TTO; /* clear done, int */\r
418int_req = int_req & ~INT_TTO;\r
419sim_cancel (&tto_unit); /* deactivate unit */\r
420return SCPE_OK;\r
421}\r
422\r
423t_stat ttx_setmod (UNIT *uptr, int32 value, char *cptr, void *desc)\r
424{\r
425tti_unit.flags = (tti_unit.flags & ~UNIT_DASHER) | value;\r
426tto_unit.flags = (tto_unit.flags & ~UNIT_DASHER) | value;\r
427return SCPE_OK;\r
428}\r