1 /* i1620_tty.c: IBM 1620 typewriter
3 Copyright (c) 2002-2005, Robert M. Supnik
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:
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
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.
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.
26 tty console typewriter
28 21-Sep-05 RMS Revised translation tables for 7094/1401 compatibility
29 22-Dec-02 RMS Added break test
32 #include "i1620_defs.h"
38 extern uint8 M
[MAXMEMSIZE
];
39 extern uint8 ind
[NUM_IND
];
41 extern uint32 io_stop
;
43 void tti_unlock (void);
44 t_stat
tti_rnum (int8
*c
);
45 t_stat
tti_ralp (int8
*c
);
46 t_stat
tti_read (int8
*c
);
47 t_stat
tto_num (uint32 pa
, uint32 len
);
48 t_stat
tto_write (uint32 c
);
49 t_stat
tty_svc (UNIT
*uptr
);
50 t_stat
tty_reset (DEVICE
*dptr
);
52 /* TTY data structures
54 tty_dev TTY device descriptor
55 tty_unit TTY unit descriptor
56 tty_reg TTY register list
59 UNIT tty_unit
= { UDATA (&tty_svc
, 0, 0), KBD_POLL_WAIT
};
62 { DRDATA (COL
, tto_col
, 7) },
63 { DRDATA (TIME
, tty_unit
.wait
, 24), REG_NZ
+ PV_LEFT
},
68 "TTY", &tty_unit
, tty_reg
, NULL
,
70 NULL
, NULL
, &tty_reset
,
76 /* Keyboard to numeric */
78 const char *tti_to_num
= "0123456789|=@:;}";
80 /* Keyboard to alphameric (digit pair) - translates LC to UC */
82 const int8 tti_to_alp
[128] = {
83 -1, -1, -1, -1, -1, -1, -1, -1, /* 00 */
84 -1, -1, -1, -1, -1, -1, -1, -1,
85 -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
86 -1, -1, -1, -1, -1, -1, -1, -1,
87 0x00, 0x02, -1, 0x33, 0x13, 0x24, 0x10, 0x34, /* !"#$%&' */
88 0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */
89 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */
90 0x78, 0x79, -1, -1, -1, 0x33, -1, -1, /* 89:;<=>? */
91 0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
92 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */
93 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */
94 0x67, 0x68, 0x69, -1, -1, -1, -1, -1, /* XYZ[\]^_ */
95 -1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* `abcdefg */
96 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */
97 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */
98 0x67, 0x68, 0x69, -1, -1, 0x0F, -1, -1 /* xyz{|}~ */
101 /* Numeric (digit) to typewriter */
103 const char num_to_tto
[16] = {
104 '0', '1', '2', '3', '4', '5', '6', '7',
105 '8', '9', '|', '=', '@', ':', ';', '}'
108 /* Alphameric (digit pair) to typewriter */
110 const char alp_to_tto
[256] = {
111 ' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */
112 -1, -1, -1, -1, -1, -1, -1, -1,
113 '+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */
114 -1, -1, -1, -1, -1, -1, -1, -1,
115 '-', '/', '|', ',', '(', -1, -1, -1, /* 20 */
116 -1, -1, -1, -1, -1, -1, -1, -1,
117 -1, -1, '0', '=', '@', ':', -1, -1, /* 30 */
118 -1, -1, -1, -1, -1, -1, -1, -1,
119 -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */
120 'H', 'I', -1, -1, -1, -1, -1, -1,
121 '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */
122 'Q', 'R', -1, -1, -1, -1, -1, -1,
123 -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */
124 'Y', 'Z', -1, -1, -1, -1, -1, -1,
125 '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */
126 '8', '9', -1, -1, -1, -1, -1, -1,
127 -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
128 -1, -1, -1, -1, -1, -1, -1, -1,
129 -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
130 -1, -1, -1, -1, -1, -1, -1, -1,
131 -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */
132 -1, -1, -1, -1, -1, -1, -1, -1,
133 -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */
134 -1, -1, -1, -1, -1, -1, -1, -1,
135 -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */
136 -1, -1, -1, -1, -1, -1, -1, -1,
137 -1, -1, -1, -1, -1, -1, -1, -1, /* D0 */
138 -1, -1, -1, -1, -1, -1, -1, -1,
139 -1, -1, -1, -1, -1, -1, -1, -1, /* E0 */
140 -1, -1, -1, -1, -1, -1, -1, -1,
141 -1, -1, -1, -1, -1, -1, -1, -1, /* F0 */
142 -1, -1, -1, -1, -1, -1, -1, -1
147 - On input, parity errors cannot occur.
148 - On input, release-start does NOT cause a record mark to be stored.
149 - On output, invalid characters type an invalid character and set WRCHK.
150 If IO stop is set, the system halts at the end of the operation.
153 t_stat
tty (uint32 op
, uint32 pa
, uint32 f0
, uint32 f1
)
161 switch (op
) { /* case on op */
163 case OP_K
: /* control */
164 switch (f1
) { /* case on control */
171 case 3: /* backspace */
172 if ((cpu_unit
.flags
& IF_MII
) == 0) return STOP_INVFNC
;
176 if ((cpu_unit
.flags
& IF_MII
) == 0) return STOP_INVFNC
;
187 case OP_RN
: /* read numeric */
188 tti_unlock (); /* unlock keyboard */
189 for (i
= 0; i
< MEMSIZE
; i
++) { /* (stop runaway) */
190 r
= tti_rnum (&ttc
); /* read char */
191 if (r
!= SCPE_OK
) return r
; /* error? */
192 if (ttc
== 0x7F) return SCPE_OK
; /* end record? */
193 M
[pa
] = ttc
& (FLAG
| DIGIT
); /* store char */
194 PP (pa
); /* incr mem addr */
198 case OP_RA
: /* read alphameric */
200 for (i
= 0; i
< MEMSIZE
; i
= i
+ 2) { /* (stop runaway) */
201 r
= tti_ralp (&ttc
); /* read char */
202 if (r
!= SCPE_OK
) return r
; /* error? */
203 if (ttc
== 0x7F) return SCPE_OK
; /* end record? */
204 M
[pa
] = (M
[pa
] & FLAG
) | (ttc
& DIGIT
); /* store 2 digits */
205 M
[pa
- 1] = (M
[pa
- 1] & FLAG
) | ((ttc
>> 4) & DIGIT
);
206 pa
= ADDR_A (pa
, 2); /* incr mem addr */
211 return tto_num (pa
, 20000 - (pa
% 20000)); /* dump numeric */
214 return tto_num (pa
, 0); /* type numeric */
217 for (i
= 0; i
< MEMSIZE
; i
= i
+ 2) { /* stop runaway */
218 d
= M
[pa
] & DIGIT
; /* get digit */
219 if ((d
& 0xA) == REC_MARK
) return sta
; /* 8-2 char? done */
220 d
= ((M
[pa
- 1] & DIGIT
) << 4) | d
; /* get digit pair */
221 ttc
= alp_to_tto
[d
]; /* translate */
222 if (ttc
< 0) { /* bad char? */
223 ind
[IN_WRCHK
] = 1; /* set write check */
224 if (io_stop
) sta
= STOP_INVCHR
; /* set return status */
226 tto_write (ttc
& 0x7F); /* write */
227 pa
= ADDR_A (pa
, 2); /* incr mem addr */
231 default: /* invalid function */
238 /* Read numerically - cannot generate parity errors */
240 t_stat
tti_rnum (int8
*c
)
246 *c
= -1; /* no char yet */
248 r
= tti_read (&raw
); /* get char */
249 if (r
!= SCPE_OK
) return r
; /* error? */
250 if (raw
== '\r') *c
= 0x7F; /* return? mark */
251 else if ((raw
== '~') || (raw
== '`')) flg
= FLAG
; /* flag? mark */
252 else if (cp
= strchr (tti_to_num
, raw
)) /* legal? */
253 *c
= ((int8
) (cp
- tti_to_num
)) | flg
; /* assemble char */
254 else raw
= 007; /* beep! */
255 tto_write (raw
); /* echo */
260 /* Read alphamerically - cannot generate parity errors */
262 t_stat
tti_ralp (int8
*c
)
267 *c
= -1; /* no char yet */
269 r
= tti_read (&raw
); /* get char */
270 if (r
!= SCPE_OK
) return r
; /* error? */
271 if (raw
== '\r') *c
= 0x7F; /* return? mark */
272 else if (tti_to_alp
[raw
] >= 0) /* legal char? */
273 *c
= tti_to_alp
[raw
]; /* xlate */
274 else raw
= 007; /* beep! */
275 tto_write (raw
); /* echo */
280 /* Read from keyboard */
282 t_stat
tti_read (int8
*c
)
287 t
= sim_poll_kbd (); /* get character */
288 } while ((t
== SCPE_OK
) || (t
& SCPE_BREAK
)); /* ignore break */
289 if (t
< SCPE_KFLAG
) return t
; /* error? */
290 *c
= t
& 0177; /* store character */
294 /* Write numerically - cannot generate parity errors */
296 t_stat
tto_num (uint32 pa
, uint32 len
)
303 for (i
= 0; i
< MEMSIZE
; i
++) { /* (stop runaway) */
304 d
= M
[pa
]; /* get char */
305 if (len
? (pa
>= end
): /* dump: end reached? */
306 ((d
& REC_MARK
) == REC_MARK
)) /* write: rec mark? */
307 return SCPE_OK
; /* end operation */
308 if (d
& FLAG
) tto_write ('`'); /* flag? */
309 r
= tto_write (num_to_tto
[d
& DIGIT
]); /* write */
310 if (r
!= SCPE_OK
) return r
; /* error? */
311 PP (pa
); /* incr mem addr */
316 /* Write, maintaining position */
318 t_stat
tto_write (uint32 c
)
322 if (c
== '\t') { /* tab? */
323 rpt
= 8 - (tto_col
% 8); /* distance to next */
324 tto_col
= tto_col
+ rpt
; /* tab over */
325 while (rpt
-- > 0) sim_putchar (' '); /* use spaces */
328 if (c
== '\r') { /* return? */
329 sim_putchar ('\r'); /* crlf */
331 tto_col
= 0; /* clear colcnt */
334 if ((c
== '\n') || (c
== 007)) { /* non-spacing? */
338 if (c
== '\b') tto_col
= tto_col
? tto_col
- 1: 0; /* backspace? */
339 else tto_col
++; /* normal */
340 if (tto_col
> TTO_COLMAX
) { /* line wrap? */
349 /* Unit service - polls for WRU */
351 t_stat
tty_svc (UNIT
*uptr
)
355 sim_activate (&tty_unit
, tty_unit
.wait
); /* continue poll */
356 if ((temp
= sim_poll_kbd ()) < SCPE_KFLAG
) return temp
; /* no char or error? */
362 t_stat
tty_reset (DEVICE
*dptr
)
364 sim_activate (&tty_unit
, tty_unit
.wait
); /* activate poll */
369 /* TTI unlock - signals that we are ready for keyboard input */
371 void tti_unlock (void)