1 /* eclipse_tt.c: Eclipse console terminal simulator
3 Copyright (c) 1998-2005, Charles E Owen
4 Portions copyright (c) 1993-2002, Robert M Supnik
5 Written by Charles Owen, used by gracious permission
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 and/or sell copies of the Software, and to permit persons to whom the
12 Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 Except as contained in this notice, the name of the author shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from the author.
31 25-Apr-03 RMS Revised for extended file support
32 03-Oct-02 RMS Added DIBs
33 30-May-02 RMS Widened POS to 32b
34 28-Jan-02 RMS Cleaned up compiler warnings
37 #include "nova_defs.h"
39 #define UNIT_V_DASHER (UNIT_V_UF + 0) /* Dasher mode */
40 #define UNIT_DASHER (1 << UNIT_V_DASHER)
42 extern int32 int_req
, dev_busy
, dev_done
, dev_disable
;
44 int32
tti (int32 pulse
, int32 code
, int32 AC
);
45 int32
tto (int32 pulse
, int32 code
, int32 AC
);
46 t_stat
tti_svc (UNIT
*uptr
);
47 t_stat
tto_svc (UNIT
*uptr
);
48 t_stat
tti_reset (DEVICE
*dptr
);
49 t_stat
tto_reset (DEVICE
*dptr
);
50 t_stat
ttx_setmod (UNIT
*uptr
, int32 value
, char *cptr
, void *desc
);
52 int32
translate_out(int32 c
);
53 int32
putseq(char *seq
);
55 /* TTI data structures
57 tti_dev TTI device descriptor
58 tti_unit TTI unit descriptor
59 tti_reg TTI register list
60 ttx_mod TTI/TTO modifiers list
63 DIB tti_dib
= { DEV_TTI
, INT_TTI
, PI_TTI
, &tti
};
65 UNIT tti_unit
= { UDATA (&tti_svc
, 0, 0), KBD_POLL_WAIT
};
68 { ORDATA (BUF
, tti_unit
.buf
, 8) },
69 { FLDATA (BUSY
, dev_busy
, INT_V_TTI
) },
70 { FLDATA (DONE
, dev_done
, INT_V_TTI
) },
71 { FLDATA (DISABLE
, dev_disable
, INT_V_TTI
) },
72 { FLDATA (INT
, int_req
, INT_V_TTI
) },
73 { DRDATA (POS
, tti_unit
.pos
, T_ADDR_W
), PV_LEFT
},
74 { DRDATA (TIME
, tti_unit
.wait
, 24), REG_NZ
+ PV_LEFT
},
79 { UNIT_DASHER
, 0, "ANSI", "ANSI", &ttx_setmod
},
80 { UNIT_DASHER
, UNIT_DASHER
, "Dasher", "DASHER", &ttx_setmod
},
85 "TTI", &tti_unit
, tti_reg
, ttx_mod
,
87 NULL
, NULL
, &tti_reset
,
92 /* TTO data structures
94 tto_dev TTO device descriptor
95 tto_unit TTO unit descriptor
96 tto_reg TTO register list
99 DIB tto_dib
= { DEV_TTO
, INT_TTO
, PI_TTO
, &tto
};
101 UNIT tto_unit
= { UDATA (&tto_svc
, 0, 0), SERIAL_OUT_WAIT
};
104 { ORDATA (BUF
, tto_unit
.buf
, 8) },
105 { FLDATA (BUSY
, dev_busy
, INT_V_TTO
) },
106 { FLDATA (DONE
, dev_done
, INT_V_TTO
) },
107 { FLDATA (DISABLE
, dev_disable
, INT_V_TTO
) },
108 { FLDATA (INT
, int_req
, INT_V_TTO
) },
109 { DRDATA (POS
, tto_unit
.pos
, T_ADDR_W
), PV_LEFT
},
110 { DRDATA (TIME
, tto_unit
.wait
, 24), PV_LEFT
},
115 "TTO", &tto_unit
, tto_reg
, ttx_mod
,
117 NULL
, NULL
, &tto_reset
,
124 /* Terminal input: IOT routine */
126 int32
tti (int32 pulse
, int32 code
, int32 AC
)
130 iodata
= (code
== ioDIA
)? tti_unit
.buf
& 0377: 0;
131 switch (pulse
) { /* decode IR<8:9> */
133 case iopS
: /* start */
134 dev_busy
= dev_busy
| INT_TTI
; /* set busy */
135 dev_done
= dev_done
& ~INT_TTI
; /* clear done, int */
136 int_req
= int_req
& ~INT_TTI
;
139 case iopC
: /* clear */
140 dev_busy
= dev_busy
& ~INT_TTI
; /* clear busy */
141 dev_done
= dev_done
& ~INT_TTI
; /* clear done, int */
142 int_req
= int_req
& ~INT_TTI
;
151 t_stat
tti_svc (UNIT
*uptr
)
155 sim_activate (&tti_unit
, tti_unit
.wait
); /* continue poll */
156 if ((temp
= sim_poll_kbd ()) < SCPE_KFLAG
) return temp
; /* no char or error? */
157 tti_unit
.buf
= temp
& 0177;
158 /* --- BEGIN MODIFIED CODE --- */
159 if (tti_unit
.flags
& UNIT_DASHER
) /* translate input */
161 /* --- END MODIFIED CODE --- */
162 dev_busy
= dev_busy
& ~INT_TTI
; /* clear busy */
163 dev_done
= dev_done
| INT_TTI
; /* set done */
164 int_req
= (int_req
& ~INT_DEV
) | (dev_done
& ~dev_disable
);
165 tti_unit
.pos
= tti_unit
.pos
+ 1;
169 /* -------------------- BEGIN INSERTION -----------------------*/
171 int curpos
= 0; /* used by translate_out() */
172 int row
= 0, col
= 0; /* ditto - for cursor positioning */
173 int spec200
= 0; /* signals next char is 'special' */
175 /* Translation: VT100 input to D200 keycodes. */
181 if (tti_unit
.buf
== '\r')
183 if (tti_unit
.buf
== '\n')
189 /* -------------------- END INSERTION -----------------------*/
193 t_stat
tti_reset (DEVICE
*dptr
)
196 dev_busy
= dev_busy
& ~INT_TTI
; /* clear busy */
197 dev_done
= dev_done
& ~INT_TTI
; /* clear done, int */
198 int_req
= int_req
& ~INT_TTI
;
199 sim_activate (&tti_unit
, tti_unit
.wait
); /* activate unit */
203 /* Terminal output: IOT routine */
205 int32
tto (int32 pulse
, int32 code
, int32 AC
)
207 if (code
== ioDOA
) tto_unit
.buf
= AC
& 0377;
208 switch (pulse
) { /* decode IR<8:9> */
210 case iopS
: /* start */
211 dev_busy
= dev_busy
| INT_TTO
; /* set busy */
212 dev_done
= dev_done
& ~INT_TTO
; /* clear done, int */
213 int_req
= int_req
& ~INT_TTO
;
214 sim_activate (&tto_unit
, tto_unit
.wait
); /* activate unit */
217 case iopC
: /* clear */
218 dev_busy
= dev_busy
& ~INT_TTO
; /* clear busy */
219 dev_done
= dev_done
& ~INT_TTO
; /* clear done, int */
220 int_req
= int_req
& ~INT_TTO
;
221 sim_cancel (&tto_unit
); /* deactivate unit */
230 t_stat
tto_svc (UNIT
*uptr
)
234 dev_busy
= dev_busy
& ~INT_TTO
; /* clear busy */
235 dev_done
= dev_done
| INT_TTO
; /* set done */
236 int_req
= (int_req
& ~INT_DEV
) | (dev_done
& ~dev_disable
);
237 c
= tto_unit
.buf
& 0177;
238 /* --- BEGIN MODIFIED CODE --- */
239 if (tto_unit
.flags
& UNIT_DASHER
) {
240 if ((temp
= translate_out(c
)) != SCPE_OK
) return temp
;
242 if ((temp
= sim_putchar (c
)) != SCPE_OK
) return temp
;
243 tto_unit
.pos
= tto_unit
.pos
+ 1;
245 /* --- END MODIFIED CODE --- */
249 /* -------------------- BEGIN INSERTION -----------------------*/
251 /* Translation routine - D200 screen controls to VT-100 controls. */
253 int32
translate_out(int32 c
)
258 if (spec200
== 1) { /* Special terminal control seq */
261 case 'C': /* read model ID */
263 case 'E': /* Reverse video off */
265 case 'D': /* Reverse video on */
271 if (curpos
== 1) { /* 2nd char of cursor position */
276 if (curpos
== 2) { /* 3rd char of cursor position */
279 sprintf(outstr
, "\033[%d;%dH", row
+1, col
+1);
280 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
283 switch (c
) { /* Single-char command or data */
284 case 003: /* Blink enable */
286 case 004: /* Blink disable */
288 case 005: /* Read cursor address */
290 case 010: /* Cursor home */
291 sprintf(outstr
, "\033[1;1H");
292 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
295 case 012: /* Newline */
296 if ((temp
= sim_putchar('\r')) != SCPE_OK
) return temp
;
298 if ((temp
= sim_putchar(c
)) != SCPE_OK
) return temp
;
302 if (row
> 24) row
= 1;
304 case 013: /* Erase EOL */
305 sprintf(outstr
, "\033[K");
306 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
308 case 014: /* Erase screen */
309 sprintf(outstr
, "\033[1;1H\033[2J");
310 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
314 if ((temp
= sim_putchar(c
)) != SCPE_OK
) return temp
;
318 case 016: /* Blink On */
319 sprintf(outstr
, "\033[5m");
320 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
322 case 017: /* Blink off */
323 sprintf(outstr
, "\033[25m");
324 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
326 case 020: /* Write cursor address */
329 case 024: /* underscore on */
330 sprintf(outstr
, "\033[4m");
331 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
333 case 025: /* underscore off */
334 sprintf(outstr
, "\033[24m");
335 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
338 case 027: /* cursor up */
339 sprintf(outstr
, "\033[A");
340 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
342 if (row
< 1) row
= 24;
344 case 030: /* cursor right */
345 sprintf(outstr
, "\033[C");
346 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
351 if (row
> 24) row
= 1;
354 case 031: /* Cursor left */
355 sprintf(outstr
, "\033[D");
356 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
362 if (row
< 1) row
= 24;
365 case 032: /* Cursor down */
366 sprintf(outstr
, "\033[B");
367 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
369 if (row
> 24) row
= 1;
371 case 034: /* Dim on */
372 sprintf(outstr
, "\033[22m");
373 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
375 case 035: /* Dim off */
376 sprintf(outstr
, "\033[1m");
377 if ((temp
= putseq(outstr
)) != SCPE_OK
) return temp
;
379 case 036: /* Special sequence */
382 default: /* ..A character of data */
383 if ((temp
= sim_putchar(c
)) != SCPE_OK
) return temp
;
389 if (row
> 24) row
= 24;
396 int32
putseq(char *seq
)
401 for (i
= 0; i
< len
; i
++) {
402 if ((temp
= sim_putchar(seq
[i
])) != SCPE_OK
)
409 /* -------------------- END INSERTION -----------------------*/
413 t_stat
tto_reset (DEVICE
*dptr
)
416 dev_busy
= dev_busy
& ~INT_TTO
; /* clear busy */
417 dev_done
= dev_done
& ~INT_TTO
; /* clear done, int */
418 int_req
= int_req
& ~INT_TTO
;
419 sim_cancel (&tto_unit
); /* deactivate unit */
423 t_stat
ttx_setmod (UNIT
*uptr
, int32 value
, char *cptr
, void *desc
)
425 tti_unit
.flags
= (tti_unit
.flags
& ~UNIT_DASHER
) | value
;
426 tto_unit
.flags
= (tto_unit
.flags
& ~UNIT_DASHER
) | value
;