simh-testsetgenerator/LGP/lgp_stddev.c
Bob Supnik 26aa6de663 Notes For V3.2-0
RESTRICTION: The PDP-15 FPP is only partially debugged.  Do NOT
enable this feature for normal operations.

WARNING: The core simulator files (scp.c, sim_*.c) have been
reorganized.  Unzip V3.2-0 to an empty directory before attempting
to compile the source.

IMPORTANT: If you are compiling for UNIX, please read the notes
for Ethernet very carefully.  You may need to download a new
version of the pcap library, or make changes to the makefile,
to get Ethernet support to work.

1. New Features in 3.2-0

1.1 SCP and libraries

- Added SHOW <device> RADIX command.
- Added SHOW <device> MODIFIERS command.
- Added SHOW <device> NAMES command.
- Added SET/SHOW <device> DEBUG command.
- Added sim_vm_parse_addr and sim_vm_fprint_addr optional interfaces.
- Added REG_VMAD flag.
- Split SCP into separate libraries for easier modification.
- Added more room to the device and unit flag fields.
- Changed terminal multiplexor library to support unlimited.
  number of async lines.

1.2 All DECtapes

- Added STOP_EOR flag to enable end-of-reel error stop
- Added device debug support.

1.3 Nova and Eclipse

- Added QTY and ALM multiplexors (Bruce Ray).

1.4 LGP-30

- Added LGP-30/LGP-21 simulator.

1.5 PDP-11

- Added format, address increment inhibit, transfer overrun
  detection to RK.
- Added device debug support to HK, RP, TM, TQ, TS.
- Added DEUNA/DELUA (XU) support (Dave Hittner).
- Add DZ per-line logging.

1.6 18b PDP's

- Added support for 1-4 (PDP-9)/1-16 (PDP-15) additional
  terminals.

1.7 PDP-10

- Added DEUNA/DELUA (XU) support (Dave Hittner).

1.8 VAX

- Added extended memory to 512MB (Mark Pizzolato).
- Added RXV21 support.

2. Bugs Fixed in 3.2-0

2.1 SCP

- Fixed double logging of SHOW BREAK (found by Mark Pizzolato).
- Fixed implementation of REG_VMIO.

2.2 Nova and Eclipse

- Fixed device enable/disable support (found by Bruce Ray).

2.3 PDP-1

- Fixed bug in LOAD (found by Mark Crispin).

2.4 PDP-10

- Fixed bug in floating point unpack.
- Fixed bug in FIXR (found by Phil Stone, fixed by Chris Smith).

2.6 PDP-11

- Fixed bug in RQ interrupt control (found by Tom Evans).

2.6 PDP-18B

- Fixed bug in PDP-15 XVM g_mode implementation.
- Fixed bug in PDP-15 indexed address calculation.
- Fixed bug in PDP-15 autoindexed address calculation.
- Fixed bugs in FPP-15 instruction decode.
- Fixed clock response to CAF.
- Fixed bug in hardware read-in mode bootstrap.
- Fixed PDP-15 XVM instruction decoding errors.

2.7 VAX

- Fixed PC read fault in EXTxV.
- Fixed PC write fault in INSV.
2011-04-15 08:34:26 -07:00

597 lines
18 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* lgp_stddev.c: LGP-30 standard devices
Copyright (c) 2004, Robert M Supnik
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Robert M Supnik shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from Robert M Supnik.
tti typewriter input (keyboard and reader)
tto typewriter output (printer and punch)
ptr high speed reader
ptpp high speed punch
*/
#include "lgp_defs.h"
#include <ctype.h>
uint32 tt_wait = WPS / 10;
uint32 tti_buf = 0;
uint32 tti_rdy = 0;
uint32 tto_uc = 0;
uint32 tto_buf = 0;
uint32 ttr_stopioe = 1;
uint32 ptr_rdy = 0;
uint32 ptr_stopioe = 1;
uint32 ptp_stopioe = 1;
extern uint32 A;
extern uint32 inp_strt, inp_done;
extern uint32 out_strt, out_done;
extern UNIT cpu_unit;
extern int32 sim_switches;
t_stat tti_svc (UNIT *uptr);
t_stat ttr_svc (UNIT *uptr);
t_stat tto_svc (UNIT *uptr);
t_stat tti_reset (DEVICE *uptr);
t_stat tto_reset (DEVICE *uptr);
t_stat ptr_svc (UNIT *uptr);
t_stat ptp_svc (UNIT *uptr);
t_stat ptr_reset (DEVICE *uptr);
t_stat ptp_reset (DEVICE *uptr);
t_stat tap_attach (UNIT *uptr, char *cptr);
t_stat tap_attable (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat read_reader (UNIT *uptr, int32 stop, int32 *c);
t_stat write_tto (int32 flex);
t_stat write_punch (UNIT *uptr, int32 flex);
t_stat tti_rdrss (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat punch_feed (UNIT *uptr, int32 val, char *cptr, void *desc);
t_stat send_start (UNIT *uptr, int32 val, char *cptr, void *desc);
extern uint32 shift_in (uint32 a, uint32 dat, uint32 sh4);
/* Conversion tables */
const int32 flex_to_ascii[128] = {
-1 , 'z', '0', ' ', '>', 'b', '1', '-',
'<' , 'y', '2', '+', '|', 'r', '3', ';',
'\r', 'i', '4', '/','\\', 'd', '5', '.',
'\t', 'n', '6', ',', -1 , 'm', '7', 'v',
'\'', 'p', '8', 'o', -1 , 'e', '9', 'x',
-1 , 'u', 'f', -1 , -1 , 't', 'g', -1 ,
-1 , 'h', 'j', -1 , -1 , 'c', 'k', -1 ,
-1 , 'a', 'q', -1 , -1 , 's', 'w', 0 ,
-1 , 'Z', ')', ' ', -1 , 'B', 'L', '_',
-1 , 'Y', '*', '=', '|', 'R', '"', ':',
'\r', 'I', '^', '?','\\', 'D', '%', ']',
'\t', 'N', '$', '[', -1 , 'M', '~', 'V',
'\'', 'P', '#', 'O', -1 , 'E', '(', 'X',
-1 , 'U', 'F', -1 , -1 , 'T', 'G', -1 ,
-1 , 'H', 'J', -1 , -1 , 'C', 'K', -1 ,
-1 , 'A', 'Q', -1 , -1 , 'S', 'W', 0 };
const int32 ascii_to_flex[128] = {
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
024, 030, -1 , -1 , -1 , 020, -1 , -1 ,
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 ,
003, -1 , 016, 042, 032, 026, -1 , 040,
046, 001, 012, 013, 033, 007, 027, 023,
002, 006, 012, 016, 022, 026, 032, 036,
042, 046, 017, 017, 004, 013, 010, 023,
-1 , 071, 005, 065, 025, 045, 052, 056,
061, 021, 062, 066, 006, 035, 031, 043,
041, 072, 015, 075, 055, 051, 037, 076,
047, 011, 001, 033, -1 , 027, 022, 007,
- 1, 071, 005, 065, 025, 045, 052, 056,
061, 021, 062, 066, 006, 035, 031, 043,
041, 072, 015, 075, 055, 051, 037, 076,
047, 011, 001, -1 , 014, -1 , 036, 077 };
static const uint8 flex_inp_valid[64] = {
1, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1,
0, 1, 1, 1, 0, 1, 1, 1 };
/* TTI data structures
tti_dev TTI device descriptor
tti_unit TTI unit descriptor
tti_mod TTI modifier list
tti_reg TTI register list
*/
UNIT tti_unit[] = {
{ UDATA (&tti_svc, 0, 0) },
{ UDATA (&ttr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) } };
REG tti_reg[] = {
{ HRDATA (BUF, tti_buf, 6) },
{ FLDATA (RDY, tti_rdy, 0) },
{ DRDATA (KPOS, tti_unit[0].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (RPOS, tti_unit[1].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tt_wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ttr_stopioe, 0) },
{ NULL } };
MTAB tti_mod[] = {
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE+UNIT_NOCS,
"ignore conditional stop", "NOCSTOP", &tap_attable },
{ UNIT_ATTABLE+UNIT_NOCS, UNIT_ATTABLE ,
NULL, "CSTOP", &tap_attable },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "START", &send_start },
{ MTAB_XTD|MTAB_VDV, 1, NULL, "RSTART", &tti_rdrss },
{ MTAB_XTD|MTAB_VDV, 0, NULL, "RSTOP", &tti_rdrss },
{ 0, 0 } };
DEVICE tti_dev = {
"TTI", tti_unit, tti_reg, tti_mod,
2, 10, 31, 1, 16, 7,
NULL, NULL, &tti_reset,
NULL, &tap_attach, NULL };
/* TTO data structures
tto_dev TTO device descriptor
tto_unit TTO unit descriptor
tto_mod TTO modifier list
tto_reg TTO register list
*/
UNIT tto_unit[] = {
{ UDATA (&tto_svc, 0, 0) },
{ UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) } };
REG tto_reg[] = {
{ HRDATA (BUF, tto_buf, 6) },
{ FLDATA (UC, tto_uc, 0) },
{ DRDATA (TPOS, tto_unit[0].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (PPOS, tto_unit[1].pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, tt_wait, 24), PV_LEFT },
{ NULL } };
MTAB tto_mod[] = {
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ MTAB_XTD|MTAB_VUN, 0, NULL, "FEED", &punch_feed },
{ 0, 0 } };
DEVICE tto_dev = {
"TTO", tto_unit, tto_reg, tto_mod,
2, 10, 31, 1, 16, 7,
NULL, NULL, &tto_reset,
NULL, &tap_attach, NULL };
/* PTR data structures
ptr_dev PTR device descriptor
ptr_unit PTR unit descriptor
ptr_mod PTR modifier list
ptr_reg PTR register list
*/
UNIT ptr_unit = {
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), WPS / 200 };
REG ptr_reg[] = {
{ HRDATA (BUF, ptr_unit.buf, 6) },
{ FLDATA (RDY, ptr_rdy, 0) },
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptr_unit.wait, 24), REG_NZ + PV_LEFT },
{ FLDATA (STOP_IOE, ptr_stopioe, 0) },
{ NULL } };
MTAB ptr_mod[] = {
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ 0, 0 } };
DEVICE ptr_dev = {
"PTR", &ptr_unit, ptr_reg, ptr_mod,
1, 10, 31, 1, 16, 7,
NULL, NULL, &ptr_reset,
NULL, &tap_attach, NULL };
/* PTP data structures
ptp_dev PTP device descriptor
ptp_unit PTP unit descriptor
ptp_mod PTP modifier list
ptp_reg PTP register list
*/
UNIT ptp_unit = {
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, 0), WPS / 20 };
REG ptp_reg[] = {
{ ORDATA (BUF, ptp_unit.buf, 8) },
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, ptp_stopioe, 0) },
{ NULL } };
MTAB ptp_mod[] = {
{ UNIT_FLEX_D, UNIT_FLEX_D, NULL, "FLEX", &tap_attable },
{ UNIT_FLEX_D, 0, NULL, "ASCII", &tap_attable },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT+UNIT_FLEX,
"file is Flex", NULL },
{ UNIT_ATT+UNIT_FLEX, UNIT_ATT,
"file is ASCII", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE+UNIT_FLEX,
"default is Flex", NULL },
{ UNIT_ATTABLE+UNIT_ATT+UNIT_FLEX, UNIT_ATTABLE,
"default is ASCII", NULL },
{ 0, 0 } };
DEVICE ptp_dev = {
"PTP", &ptp_unit, ptp_reg, ptp_mod,
1, 10, 31, 1, 16, 7,
NULL, NULL, &ptp_reset,
NULL, &tap_attach, NULL };
/* Input instruction */
void op_i_strt (uint32 dev)
{
switch (dev) { /* case on device */
case DEV_PT: /* ptr */
sim_activate (&ptr_unit, ptr_unit.wait); /* activate */
break;
case DEV_TT: /* tti/ttr */
if (Q_MANI) sim_putchar ('`'); /* manual input? */
else sim_activate (&tti_unit[1], tt_wait); /* no, must be ttr */
break; }
return;
}
t_stat op_i (uint32 dev, uint32 ch, uint32 sh4)
{
if (Q_LGP21 && out_strt) return STOP_STALL; /* LGP-21? must be idle */
if (!inp_strt) { /* input started? */
inp_strt = 1; /* no, set start */
inp_done = 0; /* clear done */
A = shift_in (A, ch, sh4);
tti_rdy = ptr_rdy = 0; /* no input */
if (Q_LGP21 || Q_INPT) op_i_strt (dev); } /* LGP-21 or PTR? start */
switch (dev) { /* case on device */
case DEV_PT: /* ptr */
if (ptr_rdy) { /* char ready? */
ptr_rdy = 0; /* reset ready */
if ((ptr_unit.buf != FLEX_DEL) && /* ignore delete and */
(!Q_LGP21 || ((ptr_unit.buf & 3) == 2))) /* LGP-21 4b? zone != 2 */
A = shift_in (A, ptr_unit.buf, sh4); } /* shift data in */
break;
case DEV_TT: /* tti/ttr */
if (tti_rdy) { /* char ready? */
tti_rdy = 0; /* reset ready */
if ((tti_buf != FLEX_DEL) && /* ignore delete and */
(!Q_LGP21 || ((tti_buf & 3) != 0))) /* LGP-21 4b? zone == 0 */
A = shift_in (A, tti_buf, sh4); } /* shift data in */
break;
default: /* nx device */
return STOP_NXDEV; } /* return error */
if (inp_done) { /* done? */
inp_strt = inp_done = 0; /* clear start, done */
return SCPE_OK; } /* no stall */
return STOP_STALL; /* stall */
}
t_stat tti_svc (UNIT *uptr)
{
int32 c, flex;
sim_activate (uptr, tt_wait); /* continue poll */
if ((c = sim_poll_kbd ()) < SCPE_KFLAG) return c; /* no char or error? */
flex = ascii_to_flex[c & 0x1FF]; /* cvt to flex */
if (flex > 0) { /* it's a typewriter... */
write_tto (flex); /* always echos */
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
write_punch (&tto_unit[1], tto_buf); } /* punch to ttp */
else write_tto ('\a'); /* don't echo bad */
if (Q_MANI && (flex > 0) && flex_inp_valid[flex]) { /* wanted, valid? */
if (flex == FLEX_CSTOP) inp_done = 1; /* conditional stop? */
else tti_rdy = 1; /* no, set ready */
tti_buf = flex; /* save char */
uptr->pos = uptr->pos + 1; }
return SCPE_OK;
}
t_stat ttr_svc (UNIT *uptr)
{
t_stat r;
if (r = read_reader (uptr, ttr_stopioe, (int32 *) &tti_buf)) return r;
if (!(uptr->flags & UNIT_NOCS) && /* cstop enable? */
(tti_buf == FLEX_CSTOP)) inp_done = 1; /* cond stop? */
else { tti_rdy = 1; /* no, set ready */
sim_activate (uptr, tt_wait); } /* cont reading */
write_tto (tti_buf); /* echo to tto */
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
return write_punch (&tto_unit[1], tti_buf); /* punch to ttp */
return SCPE_OK;
}
t_stat ptr_svc (UNIT *uptr)
{
t_stat r;
if (r = read_reader (uptr, ptr_stopioe, &uptr->buf)) return r;
if (uptr->buf == FLEX_CSTOP) inp_done = 1; /* cond stop? */
else { ptr_rdy = 1; /* no, set ready */
sim_activate (uptr, uptr->wait); } /* cont reading */
return SCPE_OK;
}
/* Output instruction */
t_stat op_p (uint32 dev, uint32 ch)
{
switch (dev) { /* case on device */
case DEV_PT: /* paper tape punch */
if (sim_is_active (&ptp_unit)) /* busy? */
return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */
ptp_unit.buf = ch; /* save char */
sim_activate (&ptp_unit, ptp_unit.wait); /* activate ptp */
break;
case DEV_TT: /* typewriter */
if (ch == 0) { /* start input? */
if (!Q_LGP21 && !Q_INPT) /* ignore if LGP-21, ptr */
op_i_strt (DEV_TT); /* start tti */
return SCPE_OK; } /* no stall */
if (sim_is_active (&tto_unit[0])) /* busy? */
return (Q_LGP21? STOP_STALL: SCPE_OK); /* LGP-21: stall */
tto_buf = ch; /* save char */
sim_activate (&tto_unit[0], tt_wait); /* activate tto */
break;
default: /* unknown */
return STOP_NXDEV; } /* return error */
if (out_strt == 0) { /* output started? */
out_strt = 1; /* flag start */
out_done = 0; } /* clear done */
return SCPE_OK; /* no stall */
}
/* TTO unit service */
t_stat tto_svc (UNIT *uptr)
{
t_stat r;
if ((r = write_tto (tto_buf)) != SCPE_OK) { /* output; error? */
sim_activate (uptr, tt_wait); /* try again */
return ((r == SCPE_STALL)? SCPE_OK: r); } /* !stall? report */
out_strt = 0;
out_done = 1;
if (tto_unit[1].flags & UNIT_ATT) /* ttp attached? */
return write_punch (&tto_unit[1], tto_buf); /* punch to ttp */
return SCPE_OK;
}
/* PTP unit service */
t_stat ptp_svc (UNIT *uptr)
{
out_strt = 0;
out_done = 1;
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
return IORETURN (ptp_stopioe, SCPE_UNATT); /* error */
return write_punch (uptr, uptr->buf); /* write to ptp */
}
/* Utility routines */
t_stat read_reader (UNIT *uptr, int32 stop, int32 *fl)
{
int32 ch, flex;
if ((uptr->flags & UNIT_ATT) == 0) /* attached? */
return IORETURN (stop, SCPE_UNATT);
do { if ((ch = getc (uptr->fileref)) == EOF) { /* read char */
if (feof (uptr->fileref)) { /* err or eof? */
if (stop) printf ("Reader end of file\n");
else return SCPE_OK; }
else perror ("Reader I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
if (uptr->flags & UNIT_FLEX) /* transposed flex? */
flex = ((ch << 1) | (ch >> 5)) & 0x3F; /* undo 612345 */
else if (ch == '#') { /* encoded? */
int32 d1 = getc (uptr->fileref); /* get 2 digits */
int32 d2 = getc (uptr->fileref);
if ((d1 == EOF) || (d2 == EOF)) { /* error? */
if (feof (uptr->fileref)) { /* eof? */
if (stop) printf ("Reader end of file\n");
else return SCPE_OK; }
else perror ("Reader I/O error");
clearerr (uptr->fileref);
return SCPE_IOERR; }
flex = (((d1 - '0') * 10) + (d2 - '0')) & 0x3F;
uptr->pos = uptr->pos + 2; }
else flex = ascii_to_flex[ch & 0x7F]; /* convert */
uptr->pos = uptr->pos + 1; }
while (flex < 0); /* until valid */
*fl = flex; /* return char */
return SCPE_OK;
}
t_stat write_tto (int32 flex)
{
int32 ch;
t_stat r;
if (flex == FLEX_UC) tto_uc = 1; /* UC? set state */
else if (flex == FLEX_LC) tto_uc = 0; /* LC? set state */
else { if (flex == FLEX_BS) ch = '\b'; /* backspace? */
else ch = flex_to_ascii[flex | (tto_uc << 6)]; /* cvt flex to ascii */
if (ch > 0) { /* legit? */
if (r = sim_putchar_s (ch)) return r; /* write char */
tto_unit[0].pos = tto_unit[0].pos + 1;
if (flex == FLEX_CR) { /* cr? */
sim_putchar ('\n'); /* add lf */
tto_unit[0].pos = tto_unit[0].pos + 1; } } }
return SCPE_OK;
}
t_stat write_punch (UNIT *uptr, int32 flex)
{
int32 c, sta;
if (uptr->flags & UNIT_FLEX) /* transposed flex? */
c = ((flex >> 1) | (flex << 5)) & 0x3F; /* reorder to 612345 */
else c = flex_to_ascii[flex]; /* convert to ASCII */
if (c >= 0) sta = fputc (c, uptr->fileref); /* valid? */
else sta = fprintf (uptr->fileref, "#%02d", flex); /* no, encode */
if (sta == EOF) { /* error? */
perror ("Punch I/O error"); /* error? */
clearerr (uptr->fileref);
return SCPE_IOERR; }
uptr->pos = uptr->pos + ((c >= 0)? 1: 3); /* incr position */
return SCPE_OK;
}
/* Reset routines */
t_stat tti_reset (DEVICE *dptr)
{
sim_activate (&tti_unit[0], tt_wait);
sim_cancel (&tti_unit[1]);
tti_buf = 0;
tti_rdy = 0;
return SCPE_OK;
}
t_stat tto_reset (DEVICE *dptr)
{
sim_cancel (&tto_unit[0]);
tto_buf = 0;
tto_uc = 0;
return SCPE_OK;
}
t_stat ptr_reset (DEVICE *dptr)
{
sim_cancel (&ptr_unit);
ptr_unit.buf = 0;
ptr_rdy = 0;
return SCPE_OK;
}
t_stat ptp_reset (DEVICE *dptr)
{
sim_cancel (&ptp_unit);
ptp_unit.buf = 0;
return SCPE_OK;
}
/* Attach paper tape unit */
t_stat tap_attach (UNIT *uptr, char *cptr)
{
t_stat r;
if ((r = attach_unit (uptr,cptr)) != SCPE_OK) return r;
if ((sim_switches & SWMASK ('F')) ||
((uptr->flags & UNIT_FLEX_D) && !(sim_switches & SWMASK ('A'))))
uptr->flags = uptr->flags | UNIT_FLEX;
else uptr->flags = uptr->flags & ~UNIT_FLEX;
return SCPE_OK;
}
/* Validate unit is attachable */
t_stat tap_attable (UNIT *uptr, int32 val, char *cptr, void *desc)
{
if (uptr->flags & UNIT_ATTABLE) return SCPE_OK;
return SCPE_NOFNC;
}
/* Typewriter reader start/stop */
t_stat tti_rdrss (UNIT *uptr, int32 val, char *cptr, void *desc)
{
if (val) {
if ((tti_unit[1].flags & UNIT_ATT) == 0) return SCPE_UNATT;
sim_activate (&tti_unit[1], tt_wait); }
else sim_cancel (&tti_unit[1]);
return SCPE_OK;
}
/* Punch feed routine */
t_stat punch_feed (UNIT *uptr, int32 val, char *cptr, void *desc)
{
int32 cnt;
t_stat r;
if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT;
if (cptr) {
cnt = (int32) get_uint (cptr, 10, 512, &r);
if ((r != SCPE_OK) || (cnt == 0)) return SCPE_ARG; }
else cnt = 10;
while (cnt-- > 0) {
r = write_punch (uptr, 0);
if (r != SCPE_OK) return r; }
return SCPE_OK;
}
/* Send start signal */
t_stat send_start (UNIT *uptr, int32 val, char *cptr, void *desc)
{
if (inp_strt) inp_done = 1;
else if (out_strt) out_done = 1;
return SCPE_OK;
}