456527772654fa671b37e1b9bb79e0f1ba486ae9
1 /* h316_stddev.c: Honeywell 316/516 standard devices
3 Copyright (c) 1999-2007, 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 ptr 316/516-50 paper tape reader
27 ptp 316/516-52 paper tape punch
28 tty 316/516-33 teleprinter
29 clk/options 316/516-12 real time clocks/internal options
31 09-Jun-07 RMS Fixed bug in clock increment (found by Theo Engel)
32 30-Sep-06 RMS Fixed handling of non-printable characters in KSR mode
33 03-Apr-06 RMS Fixed bugs in punch state handling (from Theo Engel)
34 22-Nov-05 RMS Revised for new terminal processing routines
35 05-Feb-05 RMS Fixed bug in OCP '0001 (found by Philipp Hachtmann)
36 31-Jan-05 RMS Fixed bug in TTY print (found by Philipp Hachtmann)
37 01-Dec-04 RMS Fixed problem in SKS '104 (reported by Philipp Hachtmann)
39 Added PTR detach routine, stops motion
40 Added PTR/PTP ASCII file support
42 24-Oct-03 RMS Added DMA/DMC support
43 25-Apr-03 RMS Revised for extended file support
44 01-Mar-03 RMS Added SET/SHOW CLK FREQ support
45 22-Dec-02 RMS Added break support
46 01-Nov-02 RMS Added 7b/8b support to terminal
47 30-May-02 RMS Widened POS to 32b
48 03-Nov-01 RMS Implemented upper case for console output
49 29-Nov-01 RMS Added read only unit support
50 07-Sep-01 RMS Moved function prototypes
52 The ASR-33/35 reader/punch logic, and the ASCII file support for all paper tape
53 devices, logic is taken, with grateful thanks, from Adrian Wise's H316 emulator.
55 Teletype reader transitions:
57 - SET TTY2 START puts the reader in RUN
58 - XOFF from keyboard/reader stops the reader after 1-2 more characters are read
59 - XON from program starts the reader
60 - Detach, SET TTY2 STOP, or end of file stops the reader
62 Teletype punch transitions:
64 - SET TTY3 START puts the punch in RUN
65 - XOFF from program stops the punch after 1 more character is punched
66 - TAPE from program starts the punch after 1 character delay
67 - Detach or SET TTY3 STOP stops the punch
70 #include "h316_defs.h"
73 #define UNIT_V_ASC (TTUF_V_UF + 0) /* ASCII */
74 #define UNIT_V_UASC (TTUF_V_UF + 1) /* Unix ASCII */
75 #define UNIT_ASC (1 << UNIT_V_ASC)
76 #define UNIT_UASC (1 << UNIT_V_UASC)
77 #define STA u3 /* state bits */
78 #define LF_PEND 01 /* lf pending */
79 #define RUNNING 02 /* tape running */
88 extern int32 stop_inst
;
89 extern int32 C
, dp
, ext
, extoff_pending
, sc
;
90 extern int32 dev_int
, dev_enb
;
91 extern int32 sim_switches
;
94 uint32 ptr_motion
= 0; /* read motion */
95 uint32 ptr_stopioe
= 0; /* stop on error */
96 uint32 ptp_stopioe
= 0;
97 uint32 ptp_power
= 0; /* punch power, time */
99 uint32 ttr_stopioe
= 0;
100 uint32 tty_mode
= 0; /* input (0), output (1) */
101 uint32 tty_buf
= 0; /* tty buffer */
102 uint32 ttr_xoff_read
= 0;
103 uint32 ttp_tape_rcvd
= 0;
104 uint32 ttp_xoff_rcvd
= 0;
105 int32 clk_tps
= 60; /* ticks per second */
107 int32
ptrio (int32 inst
, int32 fnc
, int32 dat
, int32 dev
);
108 t_stat
ptr_svc (UNIT
*uptr
);
109 t_stat
ptr_reset (DEVICE
*dptr
);
110 t_stat
ptr_boot (int32 unitno
, DEVICE
*dptr
);
111 int32
ptpio (int32 inst
, int32 fnc
, int32 dat
, int32 dev
);
112 t_stat
ptp_svc (UNIT
*uptr
);
113 t_stat
ptp_reset (DEVICE
*dptr
);
114 int32
ttyio (int32 inst
, int32 fnc
, int32 dat
, int32 dev
);
115 t_stat
tti_svc (UNIT
*uptr
);
116 t_stat
tto_svc (UNIT
*uptr
);
117 t_stat
tty_reset (DEVICE
*dptr
);
118 t_stat
ttio_set_mode (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
119 t_stat
ttrp_set_mode (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
120 t_stat
ttrp_set_start_stop (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
121 int32
clkio (int32 inst
, int32 fnc
, int32 dat
, int32 dev
);
122 t_stat
clk_svc (UNIT
*uptr
);
123 t_stat
clk_reset (DEVICE
*dptr
);
124 t_stat
clk_set_freq (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
);
125 t_stat
clk_show_freq (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
);
126 t_stat
pt_attach (UNIT
*uptr
, char *cptr
);
127 t_stat
pt_detach (UNIT
*uptr
);
128 t_stat
tto_write (int32 c
);
129 t_stat
ttp_write (int32 c
);
131 /* PTR data structures
133 ptr_dev PTR device descriptor
134 ptr_unit PTR unit descriptor
135 ptr_mod PTR modifiers
136 ptr_reg PTR register list
139 DIB ptr_dib
= { PTR
, IOBUS
, 1, &ptrio
};
142 UDATA (&ptr_svc
, UNIT_SEQ
+UNIT_ATTABLE
+UNIT_ROABLE
, 0),
147 { ORDATA (BUF
, ptr_unit
.buf
, 8) },
148 { FLDATA (READY
, dev_int
, INT_V_PTR
) },
149 { FLDATA (ENABLE
, dev_enb
, INT_V_PTR
) },
150 { FLDATA (MOTION
, ptr_motion
, 0) },
151 { DRDATA (POS
, ptr_unit
.pos
, T_ADDR_W
), PV_LEFT
},
152 { DRDATA (TIME
, ptr_unit
.wait
, 24), PV_LEFT
},
153 { ORDATA (RSTATE
, ptr_unit
.STA
, 2), REG_HIDDEN
},
154 { FLDATA (STOP_IOE
, ptr_stopioe
, 0) },
159 { UNIT_ATT
+UNIT_ASC
+UNIT_UASC
, UNIT_ATT
+UNIT_ASC
, "ASCII", NULL
},
160 { UNIT_ATT
+UNIT_ASC
+UNIT_UASC
, UNIT_ATT
+UNIT_ASC
+UNIT_UASC
, "Unix ASCII", NULL
},
165 "PTR", &ptr_unit
, ptr_reg
, pt_mod
,
167 NULL
, NULL
, &ptr_reset
,
168 &ptr_boot
, &pt_attach
, &pt_detach
,
172 /* PTP data structures
174 ptp_dev PTP device descriptor
175 ptp_unit PTP unit descriptor
176 ptp_mod PTP modifiers
177 ptp_reg PTP register list
180 DIB ptp_dib
= { PTP
, IOBUS
, 1, &ptpio
};
183 UDATA (&ptp_svc
, UNIT_SEQ
+UNIT_ATTABLE
, 0), SERIAL_OUT_WAIT
187 { ORDATA (BUF
, ptp_unit
.buf
, 8) },
188 { FLDATA (READY
, dev_int
, INT_V_PTP
) },
189 { FLDATA (ENABLE
, dev_enb
, INT_V_PTP
) },
190 { FLDATA (POWER
, ptp_power
, 0) },
191 { DRDATA (POS
, ptp_unit
.pos
, T_ADDR_W
), PV_LEFT
},
192 { ORDATA (PSTATE
, ptp_unit
.STA
, 2), REG_HIDDEN
},
193 { DRDATA (TIME
, ptp_unit
.wait
, 24), PV_LEFT
},
194 { DRDATA (PWRTIME
, ptp_ptime
, 24), PV_LEFT
},
195 { FLDATA (STOP_IOE
, ptp_stopioe
, 0) },
200 "PTP", &ptp_unit
, ptp_reg
, pt_mod
,
202 NULL
, NULL
, &ptp_reset
,
203 NULL
, &pt_attach
, NULL
,
207 /* TTY data structures
209 tty_dev TTY device descriptor
210 tty_unit TTY unit descriptor
211 tty_reg TTY register list
212 tty_mod TTy modifiers list
220 DIB tty_dib
= { TTY
, IOBUS
, 1, &ttyio
};
223 { UDATA (&tti_svc
, TT_MODE_KSR
, 0), KBD_POLL_WAIT
},
224 { UDATA (&tto_svc
, TT_MODE_KSR
, 0), SERIAL_OUT_WAIT
},
225 { UDATA (NULL
, UNIT_SEQ
+UNIT_ATTABLE
+UNIT_ROABLE
, 0) },
226 { UDATA (NULL
, UNIT_SEQ
+UNIT_ATTABLE
, 0) }
230 { ORDATA (BUF
, tty_buf
, 8) },
231 { FLDATA (MODE
, tty_mode
, 0) },
232 { FLDATA (READY
, dev_int
, INT_V_TTY
) },
233 { FLDATA (ENABLE
, dev_enb
, INT_V_TTY
) },
234 { DRDATA (KPOS
, tty_unit
[TTI
].pos
, T_ADDR_W
), PV_LEFT
},
235 { DRDATA (KTIME
, tty_unit
[TTI
].wait
, 24), REG_NZ
+ PV_LEFT
},
236 { DRDATA (TPOS
, tty_unit
[TTO
].pos
, T_ADDR_W
), PV_LEFT
},
237 { DRDATA (TTIME
, tty_unit
[TTO
].wait
, 24), REG_NZ
+ PV_LEFT
},
238 { ORDATA (RXOFF
, ttr_xoff_read
, 2), REG_HIDDEN
},
239 { ORDATA (RSTATE
, tty_unit
[TTR
].STA
, 2), REG_HIDDEN
},
240 { DRDATA (RPOS
, tty_unit
[TTR
].pos
, T_ADDR_W
), PV_LEFT
},
241 { ORDATA (PTAPE
, ttp_tape_rcvd
, 2), REG_HIDDEN
},
242 { ORDATA (PXOFF
, ttp_xoff_rcvd
, 2), REG_HIDDEN
},
243 { ORDATA (PSTATE
, tty_unit
[TTP
].STA
, 2), REG_HIDDEN
},
244 { DRDATA (PPOS
, tty_unit
[TTP
].pos
, T_ADDR_W
), PV_LEFT
},
245 { FLDATA (STOP_IOE
, ttr_stopioe
, 0) },
250 { TT_MODE
, TT_MODE_KSR
, "KSR", "KSR", &ttio_set_mode
},
251 { TT_MODE
, TT_MODE_7B
, "7b", "7B", &ttio_set_mode
},
252 { TT_MODE
, TT_MODE_8B
, "8b", "8B", &ttio_set_mode
},
253 { TT_MODE
, TT_MODE_7P
, "7p", "7P", &ttio_set_mode
},
254 { UNIT_ATTABLE
+UNIT_ASC
+UNIT_UASC
, UNIT_ATTABLE
, NULL
, "BINARY",
256 { UNIT_ATTABLE
+UNIT_ASC
+UNIT_UASC
, UNIT_ATTABLE
+UNIT_ASC
, "ASCII", "ASCII",
258 { UNIT_ATTABLE
+UNIT_ASC
+UNIT_UASC
, UNIT_ATTABLE
+UNIT_ASC
+UNIT_UASC
, "Unix ASCII", "UASCII",
260 { MTAB_XTD
|MTAB_VUN
|MTAB_NMO
, 1, NULL
, "START", &ttrp_set_start_stop
},
261 { MTAB_XTD
|MTAB_VUN
|MTAB_NMO
, 0, NULL
, "STOP", &ttrp_set_start_stop
},
266 "TTY", tty_unit
, tty_reg
, tty_mod
,
268 NULL
, NULL
, &tty_reset
,
269 NULL
, &pt_attach
, &pt_detach
,
273 /* CLK data structures
275 clk_dev CLK device descriptor
276 clk_unit CLK unit descriptor
277 clk_mod CLK modifiers
278 clk_reg CLK register list
281 DIB clk_dib
= { CLK_KEYS
, IOBUS
, 1, &clkio
};
283 UNIT clk_unit
= { UDATA (&clk_svc
, 0, 0), 16000 };
286 { FLDATA (READY
, dev_int
, INT_V_CLK
) },
287 { FLDATA (ENABLE
, dev_enb
, INT_V_CLK
) },
288 { DRDATA (TIME
, clk_unit
.wait
, 24), REG_NZ
+ PV_LEFT
},
289 { DRDATA (TPS
, clk_tps
, 8), PV_LEFT
+ REG_HRO
},
294 { MTAB_XTD
|MTAB_VDV
, 50, NULL
, "50HZ",
295 &clk_set_freq
, NULL
, NULL
},
296 { MTAB_XTD
|MTAB_VDV
, 60, NULL
, "60HZ",
297 &clk_set_freq
, NULL
, NULL
},
298 { MTAB_XTD
|MTAB_VDV
, 0, "FREQUENCY", NULL
,
299 NULL
, &clk_show_freq
, NULL
},
304 "CLK", &clk_unit
, clk_reg
, clk_mod
,
306 NULL
, NULL
, &clk_reset
,
311 /* Paper tape reader: IO routine */
313 int32
ptrio (int32 inst
, int32 fnc
, int32 dat
, int32 dev
)
315 switch (inst
) { /* case on opcode */
317 case ioOCP
: /* OCP */
318 if (fnc
& 016) return IOBADFNC (dat
); /* only fnc 0,1 */
319 ptr_motion
= fnc
^ 1;
320 if (fnc
) sim_cancel (&ptr_unit
); /* fnc 1? stop */
321 else sim_activate (&ptr_unit
, ptr_unit
.wait
); /* fnc 0? start */
324 case ioSKS
: /* SKS */
325 if (fnc
& 013) return IOBADFNC (dat
); /* only fnc 0,4 */
326 if (((fnc
== 000) && TST_INT (INT_PTR
)) || /* fnc 0? skip rdy */
327 ((fnc
== 004) && !TST_INTREQ (INT_PTR
))) /* fnc 4? skip !int */
331 case ioINA
: /* INA */
332 if (fnc
) return IOBADFNC (dat
); /* only fnc 0 */
333 if (TST_INT (INT_PTR
)) { /* ready? */
334 CLR_INT (INT_PTR
); /* clear ready */
335 if (ptr_motion
) /* if motion, restart */
336 sim_activate (&ptr_unit
, ptr_unit
.wait
);
337 return IOSKIP (ptr_unit
.buf
| dat
); /* ret buf, skip */
347 t_stat
ptr_svc (UNIT
*uptr
)
351 if ((uptr
->flags
& UNIT_ATT
) == 0) /* attached? */
352 return IORETURN (ptr_stopioe
, SCPE_UNATT
);
353 if (uptr
->STA
& LF_PEND
) { /* lf pending? */
354 uptr
->STA
&= ~LF_PEND
; /* clear flag */
355 c
= 0212; /* insert LF */
358 if ((c
= getc (uptr
->fileref
)) == EOF
) { /* read byte */
359 if (feof (uptr
->fileref
)) {
360 if (ptr_stopioe
) printf ("PTR end of file\n");
363 else perror ("PTR I/O error");
364 clearerr (uptr
->fileref
);
367 if ((uptr
->flags
& UNIT_UASC
) && (c
== '\n')) { /* Unix newline? */
368 c
= 0215; /* insert CR */
369 uptr
->STA
|= LF_PEND
; /* lf pending */
371 else if ((uptr
->flags
& UNIT_ASC
) && (c
!= 0)) /* ASCII? */
373 uptr
->pos
= ftell (uptr
->fileref
); /* update pos */
375 SET_INT (INT_PTR
); /* set ready flag */
376 uptr
->buf
= c
& 0377; /* get byte */
380 /* Paper tape attach routine - set or clear ASC/UASC flags if specified */
382 t_stat
pt_attach (UNIT
*uptr
, char *cptr
)
386 if (!(uptr
->flags
& UNIT_ATTABLE
)) return SCPE_NOFNC
;
387 if (r
= attach_unit (uptr
, cptr
)) return r
;
388 if (sim_switches
& SWMASK ('A')) /* -a? ASCII */
389 uptr
->flags
|= UNIT_ASC
;
390 else if (sim_switches
& SWMASK ('U')) /* -u? Unix ASCII */
391 uptr
->flags
|= (UNIT_ASC
|UNIT_UASC
);
392 else if (sim_switches
& SWMASK ('B')) /* -b? binary */
393 uptr
->flags
&= ~(UNIT_ASC
|UNIT_UASC
);
398 /* Detach routine - stop motion if not restore */
400 t_stat
pt_detach (UNIT
*uptr
)
402 if (!(sim_switches
& SIM_SW_REST
)) sim_cancel (uptr
); /* stop motion */
404 return detach_unit (uptr
);
409 t_stat
ptr_reset (DEVICE
*dptr
)
411 CLR_INT (INT_PTR
); /* clear ready, enb */
413 ptr_unit
.buf
= 0; /* clear buffer */
415 ptr_motion
= 0; /* unit stopped */
416 sim_cancel (&ptr_unit
); /* deactivate unit */
420 /* Paper tape reader bootstrap routine */
422 #define PBOOT_START 1
423 #define PBOOT_SIZE (sizeof (pboot) / sizeof (int32))
425 static const int32 pboot
[] = {
426 0010057, /* STA 57 */
428 0131001, /* READ, INA 1001 */
429 0002003, /* JMP READ */
431 0002003, /* JMP READ */
433 0131001, /* READ1, INA 1001 */
434 0002010, /* JMP READ1 */
436 0130001, /* READ2, INA 1 */
437 0002013, /* JMP READ2 */
438 0110000, /* STA* 0 */
443 t_stat
ptr_boot (int32 unitno
, DEVICE
*dptr
)
447 for (i
= 0; i
< PBOOT_SIZE
; i
++) /* copy bootstrap */
448 M
[PBOOT_START
+ i
] = pboot
[i
];
453 /* Paper tape punch: IO routine */
455 int32
ptpio (int32 inst
, int32 fnc
, int32 dat
, int32 dev
)
457 switch (inst
) { /* case on opcode */
459 case ioOCP
: /* OCP */
460 if (fnc
& 016) return IOBADFNC (dat
); /* only fnc 0,1 */
461 if (fnc
) { /* fnc 1? pwr off */
462 CLR_INT (INT_PTP
); /* not ready */
463 ptp_power
= 0; /* turn off power */
464 sim_cancel (&ptp_unit
); /* stop punch */
466 else if (ptp_power
== 0) /* fnc 0? start */
467 sim_activate (&ptp_unit
, ptp_ptime
);
470 case ioSKS
: /* SKS */
471 if ((fnc
& 012) || (fnc
== 005)) /* only 0, 1, 4 */
472 return IOBADFNC (dat
);
473 if (((fnc
== 000) && TST_INT (INT_PTP
)) || /* fnc 0? skip rdy */
474 ((fnc
== 001) && /* fnc 1? skip ptp on */
475 (ptp_power
|| sim_is_active (&ptp_unit
))) ||
476 ((fnc
== 004) && !TST_INTREQ (INT_PTP
))) /* fnc 4? skip !int */
480 case ioOTA
: /* OTA */
481 if (fnc
) return IOBADFNC (dat
); /* only fnc 0 */
482 if (TST_INT (INT_PTP
)) { /* if ptp ready */
483 CLR_INT (INT_PTP
); /* clear ready */
484 ptp_unit
.buf
= dat
& 0377; /* store byte */
485 sim_activate (&ptp_unit
, ptp_unit
.wait
);
486 return IOSKIP (dat
); /* skip return */
496 t_stat
ptp_svc (UNIT
*uptr
)
500 SET_INT (INT_PTP
); /* set flag */
501 if (ptp_power
== 0) { /* power on? */
502 ptp_power
= 1; /* ptp is ready */
505 if ((uptr
->flags
& UNIT_ATT
) == 0) /* attached? */
506 return IORETURN (ptp_stopioe
, SCPE_UNATT
);
507 if (uptr
->flags
& UNIT_ASC
) { /* ASCII? */
508 c
= uptr
->buf
& 0177; /* mask to 7b */
509 if ((uptr
->flags
& UNIT_UASC
) && (c
== 015)) /* cr? drop if Unix */
511 else if (c
== 012) c
= '\n'; /* lf? cvt to nl */
513 else c
= uptr
->buf
& 0377; /* no, binary */
514 if (putc (c
, uptr
->fileref
) == EOF
) { /* output byte */
515 perror ("PTP I/O error");
516 clearerr (uptr
->fileref
);
519 uptr
->pos
= ftell (uptr
->fileref
); /* update pos */
525 t_stat
ptp_reset (DEVICE
*dptr
)
527 CLR_INT (INT_PTP
); /* clear ready, enb */
529 ptp_power
= 0; /* power off */
530 ptp_unit
.buf
= 0; /* clear buffer */
532 sim_cancel (&ptp_unit
); /* deactivate unit */
536 /* Terminal: IO routine */
538 int32
ttyio (int32 inst
, int32 fnc
, int32 dat
, int32 dev
)
540 switch (inst
) { /* case on opcode */
542 case ioOCP
: /* OCP */
543 if (fnc
& 016) return IOBADFNC (dat
); /* only fnc 0,1 */
544 if (fnc
&& (tty_mode
== 0)) { /* input to output? */
545 if (!sim_is_active (&tty_unit
[TTO
])) /* set ready */
547 tty_mode
= 1; /* mode is output */
549 else if ((fnc
== 0) && tty_mode
) { /* output to input? */
550 CLR_INT (INT_TTY
); /* clear ready */
551 tty_mode
= 0; /* mode is input */
555 case ioSKS
: /* SKS */
556 if (fnc
& 012) return IOBADFNC (dat
); /* fnc 0,1,4,5 */
557 if (((fnc
== 000) && TST_INT (INT_TTY
)) || /* fnc 0? skip rdy */
558 ((fnc
== 001) && /* fnc 1? skip !busy */
559 (!tty_mode
|| !sim_is_active (&tty_unit
[TTO
]))) ||
560 ((fnc
== 004) && !TST_INTREQ (INT_TTY
)) || /* fnc 4? skip !int */
561 ((fnc
== 005) && (tty_mode
|| /* fnc 5? skip !xoff */
562 ((tty_buf
& 0177) != XOFF
)))) /* input & XOFF char */
566 case ioINA
: /* INA */
567 if (fnc
& 005) return IOBADFNC (dat
); /* only 0,2 */
568 if (TST_INT (INT_TTY
)) { /* ready? */
569 if (tty_mode
== 0) CLR_INT (INT_TTY
); /* inp? clear rdy */
571 (tty_buf
& ((fnc
& 002)? 077: 0377)));
576 if (fnc
& 015) return IOBADFNC (dat
); /* only 0,2 */
577 if (TST_INT (INT_TTY
)) { /* ready? */
578 tty_buf
= dat
& 0377; /* store char */
579 if (fnc
& 002) { /* binary mode? */
580 tty_buf
= tty_buf
| 0100; /* set ch 7 */
581 if (tty_buf
& 040) tty_buf
= tty_buf
& 0277;
584 sim_activate (&tty_unit
[TTO
], tty_unit
[TTO
].wait
);
595 /* Input service - keyboard and reader */
597 t_stat
tti_svc (UNIT
*uptr
)
600 UNIT
*ruptr
= &tty_unit
[TTR
];
602 sim_activate (uptr
, uptr
->wait
); /* continue poll */
603 if ((c
= sim_poll_kbd ()) >= SCPE_KFLAG
) { /* character? */
604 out
= c
& 0177; /* mask echo to 7b */
605 if (c
& SCPE_BREAK
) c
= 0; /* break? */
606 else c
= sim_tt_inpcvt (c
, TT_GET_MODE (uptr
->flags
) | TTUF_KSR
);
607 uptr
->pos
= uptr
->pos
+ 1;
609 else if (c
!= SCPE_OK
) return c
; /* error? */
610 else if ((ruptr
->flags
& UNIT_ATT
) && /* TTR attached */
611 (ruptr
->STA
& RUNNING
)) { /* and running? */
612 if (ruptr
->STA
& LF_PEND
) { /* lf pending? */
613 c
= 0212; /* char is lf */
614 ruptr
->STA
&= ~LF_PEND
; /* clear flag */
616 else { /* normal read */
617 if ((c
= getc (ruptr
->fileref
)) == EOF
) { /* read byte */
618 if (feof (ruptr
->fileref
)) { /* EOF? */
619 ruptr
->STA
&= ~RUNNING
; /* stop reader */
620 if (ttr_stopioe
) printf ("TTR end of file\n");
623 else perror ("TTR I/O error");
624 clearerr (ruptr
->fileref
);
627 if ((ruptr
->flags
& UNIT_UASC
) && (c
== '\n')) {
628 c
= 0215; /* Unix ASCII NL? */
629 ruptr
->STA
|= LF_PEND
; /* LF pending */
631 else if ((ruptr
->flags
& UNIT_ASC
) && (c
!= 0))
632 c
= c
| 0200; /* ASCII nz? cvt */
633 ruptr
->pos
= ftell (ruptr
->fileref
);
635 if (ttr_xoff_read
!= 0) { /* reader stopping? */
636 if (c
== RUBOUT
) ttr_xoff_read
= 0; /* rubout? stop */
637 else ttr_xoff_read
--; /* else decr state */
638 if (ttr_xoff_read
== 0) /* delay done? */
639 ruptr
->STA
&= ~RUNNING
; /* stop reader */
641 else if ((c
& 0177) == XOFF
) ttr_xoff_read
= 2; /* XOFF read? */
642 out
= c
; /* echo char */
644 else return SCPE_OK
; /* no char */
645 if (tty_mode
== 0) { /* input mode? */
646 tty_buf
= c
& 0377; /* put char in buf */
647 SET_INT (INT_TTY
); /* set flag */
649 tto_write (out
); /* echo to printer */
650 return ttp_write (out
); /* and punch */
653 /* Output service - printer and punch */
655 t_stat
tto_svc (UNIT
*uptr
)
658 UNIT
*ruptr
= &tty_unit
[TTR
];
659 UNIT
*puptr
= &tty_unit
[TTP
];
662 c7b
= tty_buf
& 0177;
663 if (ttp_tape_rcvd
!= 0) { /* prev = tape? */
664 ttp_tape_rcvd
--; /* decrement state */
665 if ((ttp_tape_rcvd
== 0) && (puptr
->flags
& UNIT_ATT
))
666 puptr
->STA
|= RUNNING
; /* start after delay */
668 else if (c7b
== TAPE
) ttp_tape_rcvd
= 2; /* char = TAPE? */
669 if (ttp_xoff_rcvd
!= 0) { /* prev = XOFF? */
670 ttp_xoff_rcvd
--; /* decrement state */
671 if (ttp_xoff_rcvd
== 0) puptr
->STA
&= ~RUNNING
; /* stop after delay */
673 else if (c7b
== XOFF
) ttp_xoff_rcvd
= 2; /* char = XOFF? */
674 if ((c7b
== XON
) && (ruptr
->flags
& UNIT_ATT
)) { /* char = XON? */
675 ruptr
->STA
|= RUNNING
; /* start reader */
676 ttr_xoff_read
= 0; /* cancel stop */
678 if ((r
= tto_write (tty_buf
)) != SCPE_OK
) { /* print; error? */
679 sim_activate (uptr
, uptr
->wait
); /* try again */
680 return ((r
== SCPE_STALL
)? SCPE_OK
: r
); /* !stall? report */
682 if ((r
= ttp_write (tty_buf
)) != SCPE_OK
) return r
; /* punch; error? */
683 SET_INT (INT_TTY
); /* set done flag */
687 /* Output to printer */
689 t_stat
tto_write (int32 c
)
691 UNIT
*tuptr
= &tty_unit
[TTO
];
693 c
= sim_tt_outcvt (c
, TT_GET_MODE (tuptr
->flags
) | TTUF_KSR
);
694 tuptr
->pos
= tuptr
->pos
+ 1;
695 if (c
>= 0) return sim_putchar_s (c
);
699 /* Output to punch */
701 t_stat
ttp_write (int32 c
)
704 UNIT
*puptr
= &tty_unit
[TTP
];
706 if ((puptr
->flags
& UNIT_ATT
) && /* TTP attached */
707 (puptr
->STA
& RUNNING
)) { /* and running? */
709 if (!(puptr
->flags
& UNIT_UASC
) || (c7b
!= 015)) {
710 if (puptr
->flags
& UNIT_ASC
) { /* ASCII? */
711 if (c7b
== 012) p
= '\n'; /* cvt LF */
712 else p
= c7b
; /* else 7b */
714 else p
= c
; /* untouched */
715 if (putc (p
, puptr
->fileref
) == EOF
) { /* output byte */
716 perror ("TTP I/O error");
717 clearerr (puptr
->fileref
);
720 puptr
->pos
= ftell (puptr
->fileref
); /* update pos */
728 t_stat
tty_reset (DEVICE
*dptr
)
730 CLR_INT (INT_TTY
); /* clear ready, enb */
732 tty_mode
= 0; /* mode = input */
734 ttr_xoff_read
= 0; /* clr TTR, TTP flags */
737 tty_unit
[TTR
].STA
= 0;
738 tty_unit
[TTP
].STA
= 0;
739 sim_activate (&tty_unit
[TTI
], tty_unit
[TTI
].wait
); /* activate poll */
740 sim_cancel (&tty_unit
[TTO
]); /* cancel output */
744 /* Set keyboard/printer mode - make sure flags agree */
746 t_stat
ttio_set_mode (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
748 if (uptr
->flags
& UNIT_ATTABLE
) return SCPE_NOFNC
; /* not TTR, TTP */
749 tty_unit
[TTO
].flags
= (tty_unit
[TTO
].flags
& ~TT_MODE
) | val
;
750 if (val
== TT_MODE_7P
) val
= TT_MODE_7B
;
751 tty_unit
[TTI
].flags
= (tty_unit
[TTI
].flags
& ~TT_MODE
) | val
;
755 /* Set reader/punch mode */
757 t_stat
ttrp_set_mode (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
759 if (!(uptr
->flags
& UNIT_ATTABLE
)) return SCPE_NOFNC
; /* TTR, TTP only */
760 if (!(val
& UNIT_UASC
)) uptr
->STA
&= ~LF_PEND
;
764 /* Set reader/punch start/stop */
766 t_stat
ttrp_set_start_stop (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
768 if (!(uptr
->flags
& UNIT_ATTABLE
)) return SCPE_NOFNC
; /* TTR, TTP only */
769 if (!(uptr
->flags
& UNIT_ATT
)) return SCPE_UNATT
; /* must be attached */
770 if (val
) uptr
->STA
|= RUNNING
; /* start? set running */
771 else uptr
->STA
&= ~RUNNING
; /* stop? clr running */
772 if (uptr
->flags
& UNIT_ROABLE
) ttr_xoff_read
= 0; /* TTR? cancel stop */
773 else ttp_tape_rcvd
= ttp_xoff_rcvd
= 0; /* TTP? cancel all */
777 /* Clock/options: IO routine */
779 int32
clkio (int32 inst
, int32 fnc
, int32 dat
, int32 dev
)
781 switch (inst
) { /* case on opcode */
783 case ioOCP
: /* OCP */
784 if (fnc
& 015) return IOBADFNC (dat
); /* only fnc 0,2 */
785 CLR_INT (INT_CLK
); /* reset ready */
786 if (fnc
) sim_cancel (&clk_unit
); /* fnc = 2? stop */
787 else { /* fnc = 0? */
788 if (!sim_is_active (&clk_unit
))
789 sim_activate (&clk_unit
, /* activate */
790 sim_rtc_init (clk_unit
.wait
)); /* init calibr */
794 case ioSKS
: /* SKS */
795 if (fnc
== 000) { /* clock skip !int */
796 if (!TST_INTREQ (INT_CLK
)) return IOSKIP (dat
);
798 else if ((fnc
& 007) == 002) { /* mem parity? */
799 if (((fnc
== 002) && !TST_INT (INT_MPE
)) ||
800 ((fnc
== 012) && TST_INT (INT_MPE
)))
803 else return IOBADFNC (dat
); /* invalid fnc */
806 case ioOTA
: /* OTA */
807 if (fnc
== 000) dev_enb
= dat
; /* SMK */
808 else if (fnc
== 010) { /* OTK */
809 C
= (dat
>> 15) & 1; /* set C */
810 if (cpu_unit
.flags
& UNIT_HSA
) /* HSA included? */
811 dp
= (dat
>> 14) & 1; /* set dp */
812 if (cpu_unit
.flags
& UNIT_EXT
) { /* ext opt? */
813 if (dat
& 020000) { /* ext set? */
814 ext
= 1; /* yes, set */
817 else extoff_pending
= 1; /* no, clr later */
819 sc
= dat
& 037; /* set sc */
821 else return IOBADFNC (dat
);
830 t_stat
clk_svc (UNIT
*uptr
)
833 M
[M_CLK
] = (M
[M_CLK
] + 1) & DMASK
; /* increment mem ctr */
834 if (M
[M_CLK
] == 0) SET_INT (INT_CLK
); /* = 0? set flag */
835 sim_activate (&clk_unit
, sim_rtc_calb (clk_tps
)); /* reactivate */
841 t_stat
clk_reset (DEVICE
*dptr
)
843 CLR_INT (INT_CLK
); /* clear ready, enb */
845 sim_cancel (&clk_unit
); /* deactivate unit */
851 t_stat
clk_set_freq (UNIT
*uptr
, int32 val
, char *cptr
, void *desc
)
853 if (cptr
) return SCPE_ARG
;
854 if ((val
!= 50) && (val
!= 60)) return SCPE_IERR
;
861 t_stat
clk_show_freq (FILE *st
, UNIT
*uptr
, int32 val
, void *desc
)
863 fprintf (st
, (clk_tps
== 50)? "50Hz": "60Hz");