I1620: Updated Simulator

- added deferred IO and RELEASE button simulation
- added SET TTY 1DIGIT
- added SET LPT NOFF
- numerous fixes from Tom McBride, Bob Armstrong, and Dave Wise
This commit is contained in:
Bob Supnik 2018-03-08 03:56:26 -08:00 committed by Mark Pizzolato
parent 72dde6660c
commit e7a0296584
9 changed files with 188 additions and 84 deletions

View file

@ -26,6 +26,7 @@
cdr 1622 card reader cdr 1622 card reader
cdp 1622 card punch cdp 1622 card punch
23-Jun-17 RMS Unattached error does not set RDCHK/WRCHK
09-Mar-17 RMS Guardbanded translation table lookups (COVERITY) 09-Mar-17 RMS Guardbanded translation table lookups (COVERITY)
31-Jan-15 TFM Changes to translation tables (Tom McBride) 31-Jan-15 TFM Changes to translation tables (Tom McBride)
10-Dec-13 RMS Fixed WA card punch translations (Bob Armstrong) 10-Dec-13 RMS Fixed WA card punch translations (Bob Armstrong)
@ -339,10 +340,8 @@ t_stat cdr_read (void)
int32 i; int32 i;
ind[IN_LAST] = 0; /* clear last card */ ind[IN_LAST] = 0; /* clear last card */
if ((cdr_unit.flags & UNIT_ATT) == 0) { /* attached? */ if ((cdr_unit.flags & UNIT_ATT) == 0) /* attached? */
ind[IN_RDCHK] = 1; /* no, error */
return SCPE_UNATT; return SCPE_UNATT;
}
for (i = 0; i < CD_LEN + 2; i++) /* clear buffer */ for (i = 0; i < CD_LEN + 2; i++) /* clear buffer */
cdr_buf[i] = ' '; cdr_buf[i] = ' ';
@ -520,10 +519,8 @@ return SCPE_OK;
t_stat cdp_write (uint32 len) t_stat cdp_write (uint32 len)
{ {
if ((cdp_unit.flags & UNIT_ATT) == 0) { /* attached? */ if ((cdp_unit.flags & UNIT_ATT) == 0) /* attached? */
ind[IN_WRCHK] = 1; /* no, error */
return SCPE_UNATT; return SCPE_UNATT;
}
while ((len > 0) && (cdp_buf[len - 1] == ' ')) /* trim spaces */ while ((len > 0) && (cdp_buf[len - 1] == ' ')) /* trim spaces */
--len; --len;

View file

@ -26,6 +26,8 @@
This CPU module incorporates code and comments from the 1620 simulator by This CPU module incorporates code and comments from the 1620 simulator by
Geoff Kuenning, with his permission. Geoff Kuenning, with his permission.
23-Jun-17 RMS BS should not enable indexing unless configured
15-Jun-17 RMS Added more information to IO in progress message
26-May-17 RMS Added deferred IO mode for slow devices 26-May-17 RMS Added deferred IO mode for slow devices
20-May-17 RMS Changed to commit PC on certain stops 20-May-17 RMS Changed to commit PC on certain stops
Added SET CPU RELEASE command Added SET CPU RELEASE command
@ -94,6 +96,7 @@
cpuio_mode set if IO in progress cpuio_mode set if IO in progress
cpuio_opc saved IO opcode cpuio_opc saved IO opcode
cpuio_dev saved IO device number
cpuio_cnt character counter; increments cpuio_cnt character counter; increments
PAR P address; increments PAR P address; increments
@ -152,6 +155,7 @@ uint32 io_stop = 1; /* I/O stop */
uint32 ar_stop = 1; /* arith stop */ uint32 ar_stop = 1; /* arith stop */
uint32 cpuio_inp = 0; /* IO in progress */ uint32 cpuio_inp = 0; /* IO in progress */
uint32 cpuio_opc = 0; uint32 cpuio_opc = 0;
uint32 cpuio_dev = 0;
uint32 cpuio_cnt = 0; uint32 cpuio_cnt = 0;
int32 ind_max = 16; /* iadr nest limit */ int32 ind_max = 16; /* iadr nest limit */
uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */ uint16 pcq[PCQ_SIZE] = { 0 }; /* PC queue */
@ -249,6 +253,7 @@ REG cpu_reg[] = {
{ FLDATAD (IOSTOP, io_stop, 0, "I/O stop") }, { FLDATAD (IOSTOP, io_stop, 0, "I/O stop") },
{ FLDATAD (IOINP, cpuio_inp, 0, "IO in progress"), REG_RO }, { FLDATAD (IOINP, cpuio_inp, 0, "IO in progress"), REG_RO },
{ DRDATAD (IOOPC, cpuio_opc, 6, "IO opcode"), REG_RO }, { DRDATAD (IOOPC, cpuio_opc, 6, "IO opcode"), REG_RO },
{ DRDATAD (IODEV, cpuio_dev, 7, "IO device"), REG_RO },
{ DRDATA (IOCNT, cpuio_cnt, 16), REG_RO }, { DRDATA (IOCNT, cpuio_cnt, 16), REG_RO },
{ BRDATA (IND, ind, 10, 1, NUM_IND) }, { BRDATA (IND, ind, 10, 1, NUM_IND) },
{ FLDATAD (IAE, iae, 0, "indirect address enable (Model 2 only)") }, { FLDATAD (IAE, iae, 0, "indirect address enable (Model 2 only)") },
@ -960,7 +965,7 @@ while (reason == SCPE_OK) { /* loop until halted */
} }
break; break;
/* Branch and select - P is valid */ /* Branch and select - P is valid - Model 2 only */
case OP_BS: case OP_BS:
t = M[ADDR_A (saved_PC, I_SEL)] & DIGIT; /* get select */ t = M[ADDR_A (saved_PC, I_SEL)] & DIGIT; /* get select */
@ -969,10 +974,12 @@ while (reason == SCPE_OK) { /* loop until halted */
idxe = idxb = 0; /* indexing off */ idxe = idxb = 0; /* indexing off */
break; break;
case 1: case 1:
idxe = 1; idxb = 0; /* index band A */ if ((cpu_unit.flags & IF_IDX) != 0) /* indexing present? */
idxe = 1; idxb = 0; /* index band A */
break; break;
case 2: case 2:
idxe = idxb = 1; /* index band B */ if ((cpu_unit.flags & IF_IDX) != 0) /* indexing present? */
idxe = idxb = 1; /* index band B */
break; break;
case 8: case 8:
iae = 0; /* indirect off */ iae = 0; /* indirect off */
@ -1111,8 +1118,13 @@ for (i = 0; commit_pc[i] != 0; i++) { /* check stop code */
actual_PC = PC; /* save cur PC for RLS */ actual_PC = PC; /* save cur PC for RLS */
pcq_r->qptr = pcq_p; /* update pc q ptr */ pcq_r->qptr = pcq_p; /* update pc q ptr */
upd_ind (); upd_ind ();
if (cpuio_inp != 0) /* flag IO in progress */ if (cpuio_inp != 0) { /* flag IO in progress */
sim_printf ("\r\nIO in progress"); const char *opstr = opc_lookup (cpuio_opc, cpuio_dev * 100, NULL);
if (opstr != NULL)
sim_printf ("\r\nIO in progress (%s %05d)", opstr, PAR);
else sim_printf ("\r\nIO in progress (%02d %05d,%05d)", cpuio_opc, PAR, cpuio_dev * 100);
}
return reason; return reason;
} }
@ -2164,10 +2176,11 @@ return SCPE_OK;
/* Set and clear IO in progress */ /* Set and clear IO in progress */
t_stat cpuio_set_inp (uint32 op, UNIT *uptr) t_stat cpuio_set_inp (uint32 op, uint32 dev, UNIT *uptr)
{ {
cpuio_inp = 1; cpuio_inp = 1;
cpuio_opc = op; cpuio_opc = op;
cpuio_dev = dev;
cpuio_cnt = 0; cpuio_cnt = 0;
if (uptr != NULL) if (uptr != NULL)
DEFIO_ACTIVATE_ABS (uptr); DEFIO_ACTIVATE_ABS (uptr);
@ -2178,6 +2191,7 @@ t_stat cpuio_clr_inp (UNIT *uptr)
{ {
cpuio_inp = 0; cpuio_inp = 0;
cpuio_opc = 0; cpuio_opc = 0;
cpuio_dev = 0;
cpuio_cnt = 0; cpuio_cnt = 0;
if (uptr != NULL) if (uptr != NULL)
sim_cancel (uptr); sim_cancel (uptr);
@ -2225,6 +2239,7 @@ DEVICE *dptr;
if (cpuio_inp != 0) { /* IO in progress? */ if (cpuio_inp != 0) { /* IO in progress? */
cpuio_inp = 0; cpuio_inp = 0;
cpuio_opc = 0; cpuio_opc = 0;
cpuio_dev = 0;
cpuio_cnt = 0; cpuio_cnt = 0;
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) { for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
if (((dptr->flags & DEV_DEFIO) != 0) && (dptr->reset != NULL)) if (((dptr->flags & DEV_DEFIO) != 0) && (dptr->reset != NULL))

View file

@ -250,8 +250,9 @@ enum opcodes {
#endif #endif
/* Function declarations */ /* Function declarations */
t_stat cpuio_set_inp (uint32 op, UNIT *uptr); t_stat cpuio_set_inp (uint32 op, uint32 dev, UNIT *uptr);
t_stat cpuio_clr_inp (UNIT *uptr); t_stat cpuio_clr_inp (UNIT *uptr);
const char *opc_lookup (uint32 op, uint32 qv, uint32 *fl);
extern const int8 cdr_to_alp[128]; extern const int8 cdr_to_alp[128];
extern const int8 alp_to_cdp[256]; extern const int8 alp_to_cdp[256];

View file

@ -0,0 +1,29 @@
Device Error Action
CDR RN, RA invalid char set RDCHK; if IOSTOP set, stop simulator with INVCHR
unattached stop simulator with UNATT (CHANGED - used to set RDCHK too)
end of file stop simulator witn NOCD (CHANGED - used to set RDCHK too)
file read error set RDCHK; stop simulator with IOERR
input line too long set RDCHK; stop simulator with IOERR
CDP WN,DN invalid digit set WRCHK; if IOSTOP set, stop simulator with INVCHR
WA invalid char set WRCHK; if IOSTOP set, stop simulator with INVCHR
unattached stop simulator with UNATT (CHANGED - used to set WRCHK too)
file write error set WRCHK; stop simulator with IOERR
LPT bad K control field set PRCHK; if IOSTOP set, stop simulator with INVFNC
WN,DN invalid digit set PRCHK and WRCHK; if IOSTOP set, stop simulator with INVFNC
WA invalid char set PRCHK and WRCHK; if IOSTOP set, stop simulator with INVFNC
unattached stop simulator with UNATT (CHANGED - used to set WRCHK too)
file write error set PRCHK and WRCHK; stop simulator with IOERR
PTR RN, RA invalid char set RDCHK but complete operation; if IOSTOP set at end, stop simulator with INVCHR
RN, RA parity error set RDCHK but complete operation; if IOSTOP set at end, stop simulator with INVCHR
WN, DN invalid digit set WRCHK; if IOSTOP set, stop simulator with INVCHR
WA invalid char set WRCHK; if IOSTOP set, stop simulator with INVCHR
unattached stop simulator with UNATT (CHANGED - used to set WRCHK too)
file write error set WRCHK; stop simulator with IOERR
TTY RN, RA invalid char ignored, echoed as beep/bell
WN, DN invalid digit ignored, printed as :
WA invalid char set WRCHK; if IOSTOP set, stop simulator with INVCHR

View file

@ -186,7 +186,8 @@ uint8 d, l, z;
z = 1; /* assume zero */ z = 1; /* assume zero */
for (l = 1; l <= FP_LMAX; l++) { /* scan to get length */ for (l = 1; l <= FP_LMAX; l++) { /* scan to get length */
d = M[ad] & DIGIT; /* get mant digit */ d = M[ad] & DIGIT; /* get mant digit */
if (d) z = 0; /* non-zero? */ if (d) /* non-zero? */
z = 0;
if ((l != 1) && (M[ad] & FLAG)) { /* flag past first dig? */ if ((l != 1) && (M[ad] & FLAG)) { /* flag past first dig? */
*lnt = l; /* set returns */ *lnt = l; /* set returns */
if (zro) if (zro)

View file

@ -1,6 +1,6 @@
/* i1620_lp.c: IBM 1443 line printer simulator /* i1620_lp.c: IBM 1443 line printer simulator
Copyright (c) 2002-2015, Robert M. Supnik Copyright (c) 2002-2017, Robert M. Supnik
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),
@ -25,6 +25,8 @@
lpt 1443 line printer lpt 1443 line printer
15-Jun-17 RMS Fixed K constants and print-no-spacing (Tom McBride)
Added option to emulate form feed with newlines
31-Jan-15 TFM Fixed various problems ... see comments in code 31-Jan-15 TFM Fixed various problems ... see comments in code
10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong) 10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong)
Fixed test on VFU 10 (Bob Armstrong) Fixed test on VFU 10 (Bob Armstrong)
@ -37,10 +39,13 @@
#include "i1620_defs.h" #include "i1620_defs.h"
#define LPT_BSIZE 197 /* buffer size */ #define LPT_BSIZE 197 /* buffer size */
#define UNIT_V_FF (UNIT_V_UF + 0)
#define UNIT_FF (1 << UNIT_V_FF)
#define K_IMM 0x10 /* control now */ /* decoded print control */
#define K_IMM 0x10 /* before print */
#define K_LIN 0x20 /* spc lines */ #define K_LIN 0x20 /* spc lines */
#define K_CH10 0x40 /* chan 10 */
#define K_LCNT 0x03 /* line count */ #define K_LCNT 0x03 /* line count */
#define K_CHAN 0x0F /* channel */ #define K_CHAN 0x0F /* channel */
@ -59,8 +64,9 @@ t_stat lpt_svc (UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr); t_stat lpt_reset (DEVICE *dptr);
t_stat lpt_attach (UNIT *uptr, CONST char *cptr); t_stat lpt_attach (UNIT *uptr, CONST char *cptr);
void lpt_buf_init (void); void lpt_buf_init (void);
t_stat lpt_num(uint32 pa, uint32 f1, t_bool dump); /* tfm: length parameter removed, not needed */ t_stat lpt_num(uint32 pa, uint32 f1, t_bool dump);
t_stat lpt_print (void); t_stat lpt_print (uint32 flag);
t_stat lpt_spcop (int32 ctrl);
t_stat lpt_space (int32 lines, int32 lflag); t_stat lpt_space (int32 lines, int32 lflag);
#define CHP(ch,val) ((val) & (1 << (ch))) #define CHP(ch,val) ((val) & (1 << (ch)))
@ -79,7 +85,7 @@ UNIT lpt_unit = {
REG lpt_reg[] = { REG lpt_reg[] = {
{ BRDATAD (LBUF, lpt_buf, 8, 8, LPT_BSIZE + 1, "line buffer") }, { BRDATAD (LBUF, lpt_buf, 8, 8, LPT_BSIZE + 1, "line buffer") },
{ DRDATAD (BPTR, lpt_bptr, 8, "buffer pointer") }, { DRDATAD (BPTR, lpt_bptr, 8, "buffer pointer") },
{ HRDATAD (PCTL, lpt_savctrl, 8, "saved print control directive") }, { HRDATAD (PCTL, lpt_savctrl, 6, "saved print control directive") },
{ FLDATAD (PRCHK, ind[IN_PRCHK], 0, "print check indicator") }, { FLDATAD (PRCHK, ind[IN_PRCHK], 0, "print check indicator") },
{ FLDATAD (PRCH9, ind[IN_PRCH9], 0, "channel 9 indicator") }, { FLDATAD (PRCH9, ind[IN_PRCH9], 0, "channel 9 indicator") },
{ FLDATAD (PRCH12, ind[IN_PRCH12], 0, "channel 12 indicator") }, { FLDATAD (PRCH12, ind[IN_PRCH12], 0, "channel 12 indicator") },
@ -91,8 +97,14 @@ REG lpt_reg[] = {
{ NULL } { NULL }
}; };
MTAB lp_mod[] = {
{ UNIT_FF, 0, "no form feeds", "NOFF", NULL },
{ UNIT_FF, UNIT_FF, "form feeds", "FF", NULL },
{ 0 }
};
DEVICE lpt_dev = { DEVICE lpt_dev = {
"LPT", &lpt_unit, lpt_reg, NULL, "LPT", &lpt_unit, lpt_reg, lp_mod,
1, 10, 31, 1, 8, 7, 1, 10, 31, 1, 8, 7,
NULL, NULL, &lpt_reset, NULL, NULL, &lpt_reset,
NULL, &lpt_attach, NULL NULL, &lpt_attach, NULL
@ -103,10 +115,10 @@ DEVICE lpt_dev = {
/* Numeric (flag plus digit) to lineprinter (ASCII) */ /* Numeric (flag plus digit) to lineprinter (ASCII) */
const int8 num_to_lpt[32] = { const int8 num_to_lpt[32] = {
'0', '1', '2', '3', '4', '5', '6', '7', /* tfm: All invalid char treated as errors */ '0', '1', '2', '3', '4', '5', '6', '7', /* All invalid char treated as errors */
'8', '9', '|', -1, '@', -1, -1, 'G', /* tfm: @, G only print on DN; else NB is blank */ '8', '9', '|', -1, '@', -1, -1, 'G', /* @, G only print on DN; else NB is blank */
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'W', -1, '*', -1, -1, 'X' /* tfm: W, *, X only print on DN */ 'Q', 'R', 'W', -1, '*', -1, -1, 'X' /* W, *, X only print on DN */
}; };
/* Alphameric (digit pair) to lineprinter (ASCII) */ /* Alphameric (digit pair) to lineprinter (ASCII) */
@ -146,6 +158,24 @@ const int8 alp_to_lpt[256] = { /* tfm: invalid codes 02
-1, -1, -1, -1, -1, -1, -1, -1 -1, -1, -1, -1, -1, -1, -1, -1
}; };
/* K validation and translation table - entryies 80:FF always 0 */
static const int8 lpt_ktbl[128] = {
0, 0, 0, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 00 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */
0, K_LIN|1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 */
0, 0, 0, K_IMM|11, K_IMM|12, 0, 0, 0, 0, 0, /* 30 */
0, 0, 0, 0, 0, 0,
10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 40 */
0, K_IMM|K_LIN|1, K_IMM|K_LIN|2, K_IMM|K_LIN|3, 0, /* 50 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, K_LIN|2, K_LIN|3, 0, 0, 0, 0, 0, 0, /* 60 */
0, 0, 0, 0, 0, 0,
K_IMM|10, K_IMM|1, K_IMM|2, K_IMM|3, K_IMM|4, /* 70 */
K_IMM|5, K_IMM|6, K_IMM|7, K_IMM|8, K_IMM|9,
0, 0, 0, 0, 0, 0,
};
/* Line printer IO routine /* Line printer IO routine
- Hard errors halt the system. - Hard errors halt the system.
@ -157,6 +187,7 @@ t_stat lpt (uint32 op, uint32 pa, uint32 f0, uint32 f1)
{ {
int8 lpc; int8 lpc;
uint8 z, d; uint8 z, d;
int32 ctrl;
t_stat r, sta; t_stat r, sta;
sta = SCPE_OK; sta = SCPE_OK;
@ -166,16 +197,24 @@ ind[IN_PRBSY] = 0; /* printer free */
switch (op) { /* decode op */ switch (op) { /* decode op */
case OP_K: /* control */ case OP_K: /* control */
lpt_savctrl = (f0 << 4) | f1; /* form ctrl */ ctrl = lpt_ktbl[((f0 & 0x7) << 4) | (f1 & 0xF)]; /* xlate ctrl */
if (lpt_savctrl & K_IMM) /* immediate? */ if ((f0 > 7) || (ctrl == 0)) { /* invalid? */
return lpt_print (); ind[IN_PRCHK] = 1; /* print chk */
break; if (io_stop) /* set return status */
sta = STOP_INVFNC;
}
else {
if ((ctrl & K_IMM) != 0) /* immediate? */
return lpt_spcop (ctrl); /* execute */
else lpt_savctrl = ctrl; /* otherwise, save */
}
return sta;
case OP_DN: case OP_DN:
return lpt_num (pa, f1, TRUE); /* dump numeric (tfm: removed len parm ) */ return lpt_num (pa, f1, TRUE); /* dump numeric */
case OP_WN: case OP_WN:
return lpt_num (pa, f1, FALSE); /* write numeric (tfm: removed len parm ) */ return lpt_num (pa, f1, FALSE); /* write numeric */
case OP_WA: case OP_WA:
for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */ for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */
@ -192,11 +231,9 @@ switch (op) { /* decode op */
lpt_buf[lpt_bptr] = lpc & 0x7F; /* fill buffer */ lpt_buf[lpt_bptr] = lpc & 0x7F; /* fill buffer */
pa = ADDR_A (pa, 2); /* incr mem addr */ pa = ADDR_A (pa, 2); /* incr mem addr */
} }
if ((f1 & 1) == 0) { ; /* print now? */ r = lpt_print (f1); /* print line */
r = lpt_print (); /* print line */ if (r != SCPE_OK)
if (r != SCPE_OK) return r;
return r;
}
return sta; return sta;
default: /* invalid function */ default: /* invalid function */
@ -208,7 +245,7 @@ return SCPE_OK;
/* Print numeric */ /* Print numeric */
t_stat lpt_num (uint32 pa, uint32 f1, t_bool dump) /* tfm: removed len parm and reorganized code */ t_stat lpt_num (uint32 pa, uint32 f1, t_bool dump)
{ {
uint8 d; uint8 d;
int8 lpc; int8 lpc;
@ -232,57 +269,55 @@ for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */
lpt_buf[lpt_bptr] = lpc & 0x7F; /* put char into buffer (tfm: correct increment)*/ lpt_buf[lpt_bptr] = lpc & 0x7F; /* put char into buffer (tfm: correct increment)*/
PP (pa); /* incr mem addr */ PP (pa); /* incr mem addr */
} }
if ((f1 & 1) == 0) { /* print now? */ r = lpt_print (f1); /* print line */
r = lpt_print (); /* print line */ if (r != SCPE_OK)
if (r != SCPE_OK) return r;
return r;
}
return sta; return sta;
} }
/* Print and space */ /* Print and possibly space - any spacing operation is non-immediate */
t_stat lpt_print (void) t_stat lpt_print (uint32 flag)
{ {
int32 i, chan, ctrl = lpt_savctrl; int32 i;
if ((lpt_unit.flags & UNIT_ATT) == 0) { /* not attached? */ if ((lpt_unit.flags & UNIT_ATT) == 0) { /* not attached? */
ind[IN_PRCHK] = ind[IN_WRCHK] = 1; /* wr, pri check */ ind[IN_PRCHK] = 1; /* pri check */
return SCPE_UNATT; return SCPE_UNATT;
} }
ind[IN_PRBSY] = 1; /* print busy */
sim_activate (&lpt_unit, lpt_unit.wait); /* start timer */
for (i = LPT_WIDTH; i <= LPT_BSIZE; i++) /* clear unprintable */ for (i = LPT_WIDTH; i <= LPT_BSIZE; i++) /* clear unprintable */
lpt_buf[i] = ' '; lpt_buf[i] = ' ';
while ((lpt_bptr > 0) && (lpt_buf[lpt_bptr - 1] == ' ')) while ((lpt_bptr > 0) && (lpt_buf[lpt_bptr - 1] == ' '))
lpt_buf[--lpt_bptr] = 0; /* trim buffer */ lpt_buf[--lpt_bptr] = 0; /* trim buffer */
if (lpt_bptr) { /* any line? */ if (lpt_bptr != 0) { /* any line? */
fputs (lpt_buf, lpt_unit.fileref); /* print */ fputs (lpt_buf, lpt_unit.fileref); /* print */
if ((flag & 1) != 0) /* no space? */
fputc ('\r', lpt_unit.fileref); /* bare return */
lpt_unit.pos = ftell (lpt_unit.fileref); /* update pos */ lpt_unit.pos = ftell (lpt_unit.fileref); /* update pos */
lpt_buf_init (); /* reinit buf */ lpt_buf_init (); /* reinit buf */
if (ferror (lpt_unit.fileref)) { /* error? */ if (ferror (lpt_unit.fileref)) { /* error? */
ind[IN_PRCHK] = ind[IN_WRCHK] = 1; /* wr, pri check */ ind[IN_PRCHK] = 1; /* pri check */
sim_perror ("LPT I/O error"); sim_perror ("LPT I/O error");
clearerr (lpt_unit.fileref); clearerr (lpt_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;
} }
} }
if ((flag & 1) == 0) /* spacing? */
return lpt_spcop (lpt_savctrl); /* execute */
return SCPE_OK; /* done */
}
lpt_savctrl = 0x61; /* reset ctrl */ /* Space operation - direct (K) or deferred (WA, WN, DN) */
if ((ctrl & K_LIN) == ((ctrl & K_IMM)? 0: K_LIN)) /* space lines? */
return lpt_space (ctrl & K_LCNT, FALSE); t_stat lpt_spcop (int32 ctrl)
chan = lpt_savctrl & K_CHAN; /* basic chan */ {
if ((lpt_savctrl & K_CH10) == 0) { /* chan 10-12? */ int32 chan, i;
if (chan == 0)
chan = 10; lpt_savctrl = K_LIN|1; /* reset saved control */
else if (chan == 3) if ((ctrl & K_LIN) != 0) /* space lines? */
chan = 11; return lpt_space (ctrl & K_LCNT, FALSE); /* execute spacing op */
else if (chan == 4) chan = lpt_savctrl & K_CHAN; /* get chan */
chan = 12;
else chan = 0;
}
if ((chan == 0) || (chan > 12)) if ((chan == 0) || (chan > 12))
return STOP_INVFNC; return STOP_INVFNC;
for (i = 1; i < cct_lnt + 1; i++) { /* sweep thru cct */ for (i = 1; i < cct_lnt + 1; i++) { /* sweep thru cct */
@ -304,7 +339,8 @@ t_stat lpt_space (int32 count, int32 sflag)
int32 i; int32 i;
cct_ptr = (cct_ptr + count) % cct_lnt; /* adv cct, mod lnt */ cct_ptr = (cct_ptr + count) % cct_lnt; /* adv cct, mod lnt */
if (sflag && CHP (0, cct[cct_ptr])) /* skip, top of form? */ if (sflag && CHP (0, cct[cct_ptr]) && /* skip, top of form, */
((lpt_unit.flags & UNIT_FF) != 0)) /* and use form feeds? */
fputs ("\n\f", lpt_unit.fileref); /* nl, ff */ fputs ("\n\f", lpt_unit.fileref); /* nl, ff */
else { else {
for (i = 0; i < count; i++) /* count lines */ for (i = 0; i < count; i++) /* count lines */
@ -319,6 +355,8 @@ if (ferror (lpt_unit.fileref)) { /* error? */
clearerr (lpt_unit.fileref); clearerr (lpt_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;
} }
ind[IN_PRBSY] = 1; /* print busy */
sim_activate (&lpt_unit, lpt_unit.wait); /* start timer */
return SCPE_OK; return SCPE_OK;
} }
@ -348,7 +386,7 @@ t_stat lpt_reset (DEVICE *dptr)
{ {
lpt_buf_init (); /* clear buffer */ lpt_buf_init (); /* clear buffer */
cct_ptr = 0; /* clear cct ptr */ cct_ptr = 0; /* clear cct ptr */
lpt_savctrl = 0x61; /* clear cct action */ lpt_savctrl = K_LIN|1; /* reset cct action */
ind[IN_PRCHK] = ind[IN_PRBSY] = 0; /* clear indicators */ ind[IN_PRCHK] = ind[IN_PRBSY] = 0; /* clear indicators */
ind[IN_PRCH9] = ind[IN_PRCH12] = 0; ind[IN_PRCH9] = ind[IN_PRCH12] = 0;
return SCPE_OK; return SCPE_OK;

View file

@ -26,6 +26,7 @@
ptr 1621 paper tape reader ptr 1621 paper tape reader
ptp 1624 paper tape punch ptp 1624 paper tape punch
23-Jun-17 RMS PTR/PTP errors does not set read check
10-Jun-17 RMS Fixed typo in PTP unit (Dave Wise) 10-Jun-17 RMS Fixed typo in PTP unit (Dave Wise)
26-May-17 RMS Added deferred IO 26-May-17 RMS Added deferred IO
25-May-17 RMS Fixed treatment of X0C82 on RN (Tom McBride) 25-May-17 RMS Fixed treatment of X0C82 on RN (Tom McBride)
@ -232,7 +233,7 @@ if ((op != OP_RN) && (op != OP_RA)) /* RN & RA only */
if ((ptr_unit.flags & UNIT_ATT) == 0) /* catch unattached */ if ((ptr_unit.flags & UNIT_ATT) == 0) /* catch unattached */
return SCPE_UNATT; return SCPE_UNATT;
ptr_mode = 0; ptr_mode = 0;
cpuio_set_inp (op, &ptr_unit); cpuio_set_inp (op, IO_PTR, &ptr_unit);
return SCPE_OK; return SCPE_OK;
} }
@ -245,7 +246,7 @@ if (op != OP_RA) /* RA only */
if ((ptr_unit.flags & UNIT_ATT) == 0) /* catch unattached */ if ((ptr_unit.flags & UNIT_ATT) == 0) /* catch unattached */
return SCPE_UNATT; return SCPE_UNATT;
ptr_mode = 1; ptr_mode = 1;
cpuio_set_inp (op, &ptr_unit); cpuio_set_inp (op, IO_BTR, &ptr_unit);
return SCPE_OK; return SCPE_OK;
} }
@ -343,7 +344,6 @@ int32 temp;
do { do {
if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read char */ if ((temp = getc (ptr_unit.fileref)) == EOF) { /* read char */
ind[IN_RDCHK] = 1; /* err, rd chk */
if (feof (ptr_unit.fileref)) { /* EOF? */ if (feof (ptr_unit.fileref)) { /* EOF? */
sim_printf ("PTR end of file\n"); sim_printf ("PTR end of file\n");
clearerr (ptr_unit.fileref); clearerr (ptr_unit.fileref);
@ -398,7 +398,7 @@ if ((op != OP_WN) && (op != OP_WA) && (op != OP_DN))
if ((ptp_unit.flags & UNIT_ATT) == 0) /* catch unattached */ if ((ptp_unit.flags & UNIT_ATT) == 0) /* catch unattached */
return SCPE_UNATT; return SCPE_UNATT;
ptp_mode = 0; ptp_mode = 0;
cpuio_set_inp (op, &ptp_unit); cpuio_set_inp (op, IO_PTP, &ptp_unit);
return SCPE_OK; return SCPE_OK;
} }
@ -411,7 +411,7 @@ if (op != OP_WA) /* WA only */
if ((ptp_unit.flags & UNIT_ATT) == 0) /* catch unattached */ if ((ptp_unit.flags & UNIT_ATT) == 0) /* catch unattached */
return SCPE_UNATT; return SCPE_UNATT;
ptp_mode = 1; ptp_mode = 1;
cpuio_set_inp (op, &ptp_unit); cpuio_set_inp (op, IO_BTP, &ptp_unit);
return SCPE_OK; return SCPE_OK;
} }
@ -505,7 +505,6 @@ return SCPE_OK;
t_stat ptp_write (uint32 c) t_stat ptp_write (uint32 c)
{ {
if (putc (c, ptp_unit.fileref) == EOF) { /* write char */ if (putc (c, ptp_unit.fileref) == EOF) { /* write char */
ind[IN_WRCHK] = 1; /* error? */
sim_perror ("PTP I/O error"); sim_perror ("PTP I/O error");
clearerr (ptp_unit.fileref); clearerr (ptp_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;

View file

@ -303,6 +303,34 @@ if ((cpu_unit.flags & IF_IDX) && flg) { /* indexing? */
return; return;
} }
/* Look up an opcode
Inputs:
op = opcode (decimal)
qv = Q value (full 5 digits)
Outputs:
*opcst = pointer to opcode string
(NULL if not found)
*fl = opcode flags (optional)
*/
const char *opc_lookup (uint32 op, uint32 qv, uint32 *fl)
{
uint32 i, opfl;
for (i = 0; opcode[i].str != NULL; i++) { /* find opcode */
opfl = opcode[i].opv & 0xFF0000; /* get flags */
if ((op == (opcode[i].opv & 0xFF)) && /* op match? */
((qv == opcode[i].qv) || /* q match or */
((opfl != I_1E) && (opfl != I_0E)))) { /* not needed? */
if (fl != NULL)
*fl = opfl;
return opcode[i].str;
}
}
return NULL;
}
/* Symbolic decode /* Symbolic decode
Inputs: Inputs:
@ -323,6 +351,7 @@ t_stat fprint_sym (FILE *of, t_addr addr, t_value *val,
{ {
int32 pmp, qmp, i, c, d, any; int32 pmp, qmp, i, c, d, any;
uint32 op, qv, opfl; uint32 op, qv, opfl;
const char *opstr;
if (uptr == NULL) if (uptr == NULL)
uptr = &cpu_unit; uptr = &cpu_unit;
@ -383,14 +412,9 @@ for (i = qv = pmp = qmp = 0; i < ADDR_LEN; i++) { /* test addr */
} }
if ((val[0] | val[1]) & FLAG) /* flags force */ if ((val[0] | val[1]) & FLAG) /* flags force */
pmp = qmp = 1; pmp = qmp = 1;
for (i = 0; opcode[i].str != NULL; i++) { /* find opcode */ opstr = opc_lookup (op, qv, &opfl); /* find opcode */
opfl = opcode[i].opv & 0xFF0000;
if ((op == (opcode[i].opv & 0xFF)) && if (opstr == NULL) { /* invalid opcode */
((qv == opcode[i].qv) ||
((opfl != I_1E) && (opfl != I_0E))))
break;
}
if (opcode[i].str == NULL) { /* invalid opcode */
if ((sw & SIM_SW_STOP) != 0) { /* stop message? */ if ((sw & SIM_SW_STOP) != 0) { /* stop message? */
fprintf (of, "%02d", op); /* print numeric opcode */ fprintf (of, "%02d", op); /* print numeric opcode */
return -(INST_LEN - 1); /* report success */ return -(INST_LEN - 1); /* report success */
@ -400,7 +424,7 @@ if (opcode[i].str == NULL) { /* invalid opcode */
if (I_GETQP (opfl) == I_M_QNP) /* Q no print? */ if (I_GETQP (opfl) == I_M_QNP) /* Q no print? */
qmp = 0; qmp = 0;
fprintf (of, "%-4s", opcode[i].str); /* print opcode */ fprintf (of, ((sw & SIM_SW_STOP)? "%s": "%-4s"), opstr);/* print opcode */
if (I_GETPP (opfl) == I_M_PP) /* P required? */ if (I_GETPP (opfl) == I_M_PP) /* P required? */
fprint_addr (of, ' ', &val[I_P], I_M_QX); fprint_addr (of, ' ', &val[I_P], I_M_QX);
else if ((I_GETPP (opfl) == I_M_PCP) && (pmp || qmp)) /* P opt & needed? */ else if ((I_GETPP (opfl) == I_M_PCP) && (pmp || qmp)) /* P opt & needed? */

View file

@ -136,7 +136,7 @@ DEVICE tty_dev = {
/* The following constant is a list of valid 1620 numeric characters /* The following constant is a list of valid 1620 numeric characters
that can be entered from the keyboard. They are the digits 0-9, that can be entered from the keyboard. They are the digits 0-9,
record mark(|), numeric blank(@) and group mark(}). All others record mark(|), numeric blank(@) and group mark(}). All others
are cosidered invalid. When entering data, these characters may are considered invalid. When entering data, these characters may
all be preceeded by tilde(~) or accent(`) to indicate that the all be preceeded by tilde(~) or accent(`) to indicate that the
following character should be entered into storage with a flag. following character should be entered into storage with a flag.
@ -285,7 +285,7 @@ switch (op) { /* case on op */
case OP_WN: case OP_WN:
case OP_DN: case OP_DN:
case OP_WA: case OP_WA:
cpuio_set_inp (op, &tty_unit[UTTO]); /* set IO in progress */ cpuio_set_inp (op, IO_TTY, &tty_unit[UTTO]); /* set IO in progress */
break; break;
case OP_RN: case OP_RN:
@ -293,7 +293,7 @@ switch (op) { /* case on op */
tti_unlock = 1; /* unlock keyboard */ tti_unlock = 1; /* unlock keyboard */
tti_flag = 0; /* init flag */ tti_flag = 0; /* init flag */
tto_write ('>'); /* prompt user */ tto_write ('>'); /* prompt user */
cpuio_set_inp (op, NULL); /* set IO in progress */ cpuio_set_inp (op, IO_TTY, NULL); /* set IO in progress */
break; break;
default: /* invalid function */ default: /* invalid function */
@ -316,7 +316,7 @@ if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */
return temp; return temp;
if (tti_unlock == 0) /* expecting input? */ if (tti_unlock == 0) /* expecting input? */
return SCPE_OK; /* no, ignore */ return SCPE_OK; /* no, ignore */
raw = (int8) temp; raw = (int8) (temp & 0x7F);
if (raw == '\r') { /* return? */ if (raw == '\r') { /* return? */
tto_write (raw); /* echo */ tto_write (raw); /* echo */