I1620: Add deferred IO mode for slow devices
The major change is the implementation of deferred IO - a more accurate implementation of the 1620's "stop in its tracks" IO model. When a device uses deferred IO, instruction execution is suspended until the IO completes successfully. Operator interruptions, errors, and so on do not return to instruction execution; this only occurs if the IO completes successfully or the command SET CPU RELEASE is given (equivalent of pressing the RELEASE button). Otherwise, the current IO operation continues to execute. Only the console typewriter and paper tape reader/punch currently implement deferred IO; there are operational issues with those devices that require more accurate modeling. The card reader/punch, line printer, and disk still execute IO "instantaneously". It's not all that hard to convert an instantaneous device to deferred operation, but there's no point in doing so (and possibly introducing new bugs) unless there's an actual operational issue. The 1620 doesn't have overlapped IO, so programs can't tell the difference, by and large. A number of other issues have been addressed as well, including the bizarre "treat RM as 0 in the Q field" required by MI-015; the treatment of non-existent indicators as always off; and various other tweaks. I've run CU01 (again), which at least gives typewriter and paper-tape IO a basic workout; and it works. I leave more detailed testing to people who know the machine better than I do. The documentation has been updated to include Tom's detailed breakdown of IO handling for all IO operations on the typewriter, paper-tape reader/punch, card reader/punch, and line printer.
This commit is contained in:
parent
df627b0cb1
commit
a750171c30
7 changed files with 428 additions and 353 deletions
|
@ -433,7 +433,7 @@ switch (op) { /* decode op */
|
||||||
case OP_DN:
|
case OP_DN:
|
||||||
|
|
||||||
/* DN punches all characters the same as WN except that a flagged
|
/* DN punches all characters the same as WN except that a flagged
|
||||||
zero is punched as a hypehen (-) instead of a flagged
|
zero is punched as a hyphen (-) instead of a flagged
|
||||||
zero ([). Punching begins at the P address and continues until
|
zero ([). Punching begins at the P address and continues until
|
||||||
the last digit of the storage module containing the P address
|
the last digit of the storage module containing the P address
|
||||||
has been punched. If the amount of data to be punched is an
|
has been punched. If the amount of data to be punched is an
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
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.
|
||||||
|
|
||||||
|
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
|
||||||
Undefined indicators don't throw an error (Dave Wise)
|
Undefined indicators don't throw an error (Dave Wise)
|
||||||
|
@ -82,6 +83,20 @@
|
||||||
it was nicknamed CADET (Can't Add, Doesn't Even Try). The Model 2 does
|
it was nicknamed CADET (Can't Add, Doesn't Even Try). The Model 2 does
|
||||||
adds in hardware and uses the add table memory for index registers.
|
adds in hardware and uses the add table memory for index registers.
|
||||||
|
|
||||||
|
The 1620 has no concept of overlapped IO. When an IO instruction is
|
||||||
|
issued, instruction execution is suspended until the IO is complete.
|
||||||
|
For "fast" devices, like the disk, IO is done in an instantaneous burst.
|
||||||
|
"Slow" devices have the option of going character-by-character, with
|
||||||
|
delays in between. This allows for operator intervention, such as
|
||||||
|
^E or changing paper tapes.
|
||||||
|
|
||||||
|
The simulated IO state for character-by-character IO is:
|
||||||
|
|
||||||
|
cpuio_mode set if IO in progress
|
||||||
|
cpuio_opc saved IO opcode
|
||||||
|
cpuio_cnt character counter; increments
|
||||||
|
PAR P address; increments
|
||||||
|
|
||||||
This routine is the instruction decode routine for the IBM 1620.
|
This routine is the instruction decode routine for the IBM 1620.
|
||||||
It is called from the simulator control program to execute
|
It is called from the simulator control program to execute
|
||||||
instructions in simulated memory, starting at the simulated PC.
|
instructions in simulated memory, starting at the simulated PC.
|
||||||
|
@ -135,6 +150,9 @@ uint32 idxe = 0; /* index enable */
|
||||||
uint32 idxb = 0; /* index band */
|
uint32 idxb = 0; /* index band */
|
||||||
uint32 io_stop = 1; /* I/O stop */
|
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_opc = 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 */
|
||||||
int32 pcq_p = 0; /* PC queue ptr */
|
int32 pcq_p = 0; /* PC queue ptr */
|
||||||
|
@ -227,6 +245,9 @@ REG cpu_reg[] = {
|
||||||
{ FLDATA (WRCHK, ind[IN_WRCHK], 0) },
|
{ FLDATA (WRCHK, ind[IN_WRCHK], 0) },
|
||||||
{ FLDATA (ARSTOP, ar_stop, 0) },
|
{ FLDATA (ARSTOP, ar_stop, 0) },
|
||||||
{ FLDATA (IOSTOP, io_stop, 0) },
|
{ FLDATA (IOSTOP, io_stop, 0) },
|
||||||
|
{ FLDATA (IOINP, cpuio_inp, 0), REG_RO },
|
||||||
|
{ DRDATA (IOOPC, cpuio_opc, 6), REG_RO },
|
||||||
|
{ DRDATA (IOCNT, cpuio_cnt, 16), REG_RO },
|
||||||
{ BRDATA (IND, ind, 10, 1, NUM_IND) },
|
{ BRDATA (IND, ind, 10, 1, NUM_IND) },
|
||||||
{ FLDATA (IAE, iae, 0) },
|
{ FLDATA (IAE, iae, 0) },
|
||||||
{ FLDATA (IDXE, idxe, 0) },
|
{ FLDATA (IDXE, idxe, 0) },
|
||||||
|
@ -349,7 +370,7 @@ const int32 op_table[100] = {
|
||||||
0,
|
0,
|
||||||
IF_IDX + IF_VPA + IF_VQA, /* 70: MA */
|
IF_IDX + IF_VPA + IF_VQA, /* 70: MA */
|
||||||
IF_EDT + IF_VPA + IF_VQA, /* MF */
|
IF_EDT + IF_VPA + IF_VQA, /* MF */
|
||||||
IF_EDT + IF_VPA + IF_VQA, /* MF */
|
IF_EDT + IF_VPA + IF_VQA, /* TNS */
|
||||||
IF_EDT + IF_VPA + IF_VQA, /* TNF */
|
IF_EDT + IF_VPA + IF_VQA, /* TNF */
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -517,6 +538,10 @@ while (reason == SCPE_OK) { /* loop until halted */
|
||||||
if ((reason = sim_process_event ()))
|
if ((reason = sim_process_event ()))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (cpuio_inp != 0) { /* IO in progress? */
|
||||||
|
sim_interval = sim_interval - 1; /* tick & continue */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
if (sim_brk_summ && sim_brk_test (PC, SWMASK ('E'))) { /* breakpoint? */
|
||||||
reason = STOP_IBKPT; /* stop simulation */
|
reason = STOP_IBKPT; /* stop simulation */
|
||||||
|
@ -1082,6 +1107,8 @@ 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 */
|
||||||
|
sim_printf ("\r\nIO in progress");
|
||||||
return reason;
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2131,6 +2158,28 @@ M[d] = M[d] | sign; /* set result sign */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set and clear IO in progress */
|
||||||
|
|
||||||
|
t_stat cpuio_set_inp (uint32 op, UNIT *uptr)
|
||||||
|
{
|
||||||
|
cpuio_inp = 1;
|
||||||
|
cpuio_opc = op;
|
||||||
|
cpuio_cnt = 0;
|
||||||
|
if (uptr != NULL)
|
||||||
|
sim_activate_abs (uptr, uptr->wait);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_stat cpuio_clr_inp (UNIT *uptr)
|
||||||
|
{
|
||||||
|
cpuio_inp = 0;
|
||||||
|
cpuio_opc = 0;
|
||||||
|
cpuio_cnt = 0;
|
||||||
|
if (uptr != NULL)
|
||||||
|
sim_cancel (uptr);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
t_stat cpu_reset (DEVICE *dptr)
|
t_stat cpu_reset (DEVICE *dptr)
|
||||||
|
@ -2142,6 +2191,8 @@ PR1 = IR2 = 1; /* invalidate PR1,IR2 */
|
||||||
ind[0] = 0;
|
ind[0] = 0;
|
||||||
for (i = IN_SW4 + 1; i < NUM_IND; i++) /* init indicators */
|
for (i = IN_SW4 + 1; i < NUM_IND; i++) /* init indicators */
|
||||||
ind[i] = 0;
|
ind[i] = 0;
|
||||||
|
if (cpuio_inp != 0) /* IO in progress? */
|
||||||
|
cpu_set_release (NULL, 0, NULL, NULL); /* clear IO */
|
||||||
if (cpu_unit.flags & IF_IA) /* indirect enabled? */
|
if (cpu_unit.flags & IF_IA) /* indirect enabled? */
|
||||||
iae = 1;
|
iae = 1;
|
||||||
else iae = 0;
|
else iae = 0;
|
||||||
|
@ -2164,8 +2215,21 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat cpu_set_release (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
t_stat cpu_set_release (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
{
|
{
|
||||||
if (actual_PC == ADDR_A (saved_PC, INST_LEN)) { /* one instr ahead? */
|
uint32 i;
|
||||||
saved_PC = actual_PC; /* return */
|
DEVICE *dptr;
|
||||||
|
|
||||||
|
if (cpuio_inp != 0) { /* IO in progress? */
|
||||||
|
cpuio_inp = 0;
|
||||||
|
cpuio_opc = 0;
|
||||||
|
cpuio_cnt = 0;
|
||||||
|
for (i = 0; (dptr = sim_devices[i]) != NULL; i++) {
|
||||||
|
if (((dptr->flags & DEV_DEFIO) != 0) && (dptr->reset != NULL))
|
||||||
|
dptr->reset (dptr);
|
||||||
|
}
|
||||||
|
sim_printf ("IO operation canceled\n");
|
||||||
|
}
|
||||||
|
else if (actual_PC == ADDR_A (saved_PC, INST_LEN)) { /* one instr ahead? */
|
||||||
|
saved_PC = actual_PC;
|
||||||
sim_printf ("New PC = %05d\n", saved_PC);
|
sim_printf ("New PC = %05d\n", saved_PC);
|
||||||
}
|
}
|
||||||
else sim_printf ("PC unchanged\n");
|
else sim_printf ("PC unchanged\n");
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
I am grateful to Al Kossow, the Computer History Museum, and the IBM Corporate
|
I am grateful to Al Kossow, the Computer History Museum, and the IBM Corporate
|
||||||
Archives for their help in gathering documentation about the IBM 1620.
|
Archives for their help in gathering documentation about the IBM 1620.
|
||||||
|
|
||||||
|
23-May-17 RMS MARCHK is indicator 8, not 18 (Dave Wise)
|
||||||
19-May-17 RMS Added option for Model I diagnostic mode (Dave Wise)
|
19-May-17 RMS Added option for Model I diagnostic mode (Dave Wise)
|
||||||
05-Feb-15 TFM Added definitions for flagged RM, GM, NB
|
05-Feb-15 TFM Added definitions for flagged RM, GM, NB
|
||||||
22-May-10 RMS Added check for 64b definitions
|
22-May-10 RMS Added check for 64b definitions
|
||||||
|
@ -113,6 +114,7 @@
|
||||||
#define IN_SW4 4 /* sense switch 4 */
|
#define IN_SW4 4 /* sense switch 4 */
|
||||||
#define IN_RDCHK 6 /* read check (I/O error) */
|
#define IN_RDCHK 6 /* read check (I/O error) */
|
||||||
#define IN_WRCHK 7 /* write check (I/O error) */
|
#define IN_WRCHK 7 /* write check (I/O error) */
|
||||||
|
#define IN_MARCHK 8 /* MAR check - diag only */
|
||||||
#define IN_LAST 9 /* last card was just read */
|
#define IN_LAST 9 /* last card was just read */
|
||||||
#define IN_HP 11 /* high or positive result */
|
#define IN_HP 11 /* high or positive result */
|
||||||
#define IN_EZ 12 /* equal or zero result */
|
#define IN_EZ 12 /* equal or zero result */
|
||||||
|
@ -121,7 +123,6 @@
|
||||||
#define IN_EXPCHK 15 /* floating exponent check */
|
#define IN_EXPCHK 15 /* floating exponent check */
|
||||||
#define IN_MBREVEN 16 /* even parity check */
|
#define IN_MBREVEN 16 /* even parity check */
|
||||||
#define IN_MBRODD 17 /* odd parity check */
|
#define IN_MBRODD 17 /* odd parity check */
|
||||||
#define IN_MARCHK 18 /* MAR check - diag only */
|
|
||||||
#define IN_ANYCHK 19 /* any of read, write, even/odd */
|
#define IN_ANYCHK 19 /* any of read, write, even/odd */
|
||||||
#define IN_PRCHK 25 /* printer check */
|
#define IN_PRCHK 25 /* printer check */
|
||||||
#define IN_IXN 30 /* IX neither */
|
#define IN_IXN 30 /* IX neither */
|
||||||
|
@ -235,6 +236,15 @@ enum opcodes {
|
||||||
OP_BBT = 90, OP_BMK, OP_ORF, OP_ANDF, OP_CPLF, /* 90 - 99 */
|
OP_BBT = 90, OP_BMK, OP_ORF, OP_ANDF, OP_CPLF, /* 90 - 99 */
|
||||||
OP_EORF, OP_OTD, OP_DTO };
|
OP_EORF, OP_OTD, OP_DTO };
|
||||||
|
|
||||||
|
/* Device flags */
|
||||||
|
|
||||||
|
#define DEV_DEFIO (1 << (DEV_V_UF + 0))
|
||||||
|
|
||||||
|
/* Function declarations */
|
||||||
|
|
||||||
|
t_stat cpuio_set_inp (uint32 op, UNIT *uptr);
|
||||||
|
t_stat cpuio_clr_inp (UNIT *uptr);
|
||||||
|
|
||||||
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];
|
||||||
|
|
||||||
|
|
347
I1620/i1620_pt.c
347
I1620/i1620_pt.c
|
@ -26,6 +26,8 @@
|
||||||
ptr 1621 paper tape reader
|
ptr 1621 paper tape reader
|
||||||
ptp 1624 paper tape punch
|
ptp 1624 paper tape punch
|
||||||
|
|
||||||
|
26-May-17 RMS Added deferred IO
|
||||||
|
25-May-17 RMS Fixed treatment of X0C82 on RN (Tom McBride)
|
||||||
18-May-17 RMS Separated EOF error from other IO errors (Dave Wise)
|
18-May-17 RMS Separated EOF error from other IO errors (Dave Wise)
|
||||||
23-Feb-15 TFM Fixed RA, RBPT to preserve flags on RM at end (Tom McBride)
|
23-Feb-15 TFM Fixed RA, RBPT to preserve flags on RM at end (Tom McBride)
|
||||||
09-Feb-15 TFM Fixed numerous translation problems (Tom McBride)
|
09-Feb-15 TFM Fixed numerous translation problems (Tom McBride)
|
||||||
|
@ -45,17 +47,23 @@
|
||||||
#define PT_C 0x10 /* C */
|
#define PT_C 0x10 /* C */
|
||||||
#define PT_FD 0x7F /* deleted */
|
#define PT_FD 0x7F /* deleted */
|
||||||
|
|
||||||
|
static uint32 ptr_mode = 0; /* normal/binary */
|
||||||
|
static uint32 ptp_mode = 0;
|
||||||
|
|
||||||
extern uint8 M[MAXMEMSIZE];
|
extern uint8 M[MAXMEMSIZE];
|
||||||
extern uint8 ind[NUM_IND];
|
extern uint8 ind[NUM_IND];
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern uint32 io_stop;
|
extern uint32 io_stop;
|
||||||
|
extern uint32 PAR, cpuio_opc, cpuio_cnt;
|
||||||
|
|
||||||
|
t_stat ptr_svc (UNIT *uptr);
|
||||||
t_stat ptr_reset (DEVICE *dptr);
|
t_stat ptr_reset (DEVICE *dptr);
|
||||||
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
|
||||||
t_stat ptr_read (uint8 *c, t_bool ignfeed);
|
t_stat ptr_read (uint8 *c, t_bool ignfeed);
|
||||||
|
t_stat ptp_svc (UNIT *uptr);
|
||||||
t_stat ptp_reset (DEVICE *dptr);
|
t_stat ptp_reset (DEVICE *dptr);
|
||||||
t_stat ptp_write (uint32 c);
|
t_stat ptp_write (uint32 c);
|
||||||
t_stat ptp_num (uint32 pa, uint32 len, t_bool dump);
|
t_stat ptp_num (void);
|
||||||
|
|
||||||
/* PTR data structures
|
/* PTR data structures
|
||||||
|
|
||||||
|
@ -65,11 +73,13 @@ t_stat ptp_num (uint32 pa, uint32 len, t_bool dump);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UNIT ptr_unit = {
|
UNIT ptr_unit = {
|
||||||
UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0)
|
UDATA (&ptr_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0), SERIAL_IN_WAIT
|
||||||
};
|
};
|
||||||
|
|
||||||
REG ptr_reg[] = {
|
REG ptr_reg[] = {
|
||||||
|
{ FLDATA (BIN, ptr_mode, 0) },
|
||||||
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
|
{ DRDATA (TIME, ptr_unit.wait, 24), PV_LEFT },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,7 +87,8 @@ DEVICE ptr_dev = {
|
||||||
"PTR", &ptr_unit, ptr_reg, NULL,
|
"PTR", &ptr_unit, ptr_reg, NULL,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &ptr_reset,
|
NULL, NULL, &ptr_reset,
|
||||||
&ptr_boot, NULL, NULL
|
&ptr_boot, NULL, NULL,
|
||||||
|
NULL, DEV_DEFIO
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PTP data structures
|
/* PTP data structures
|
||||||
|
@ -88,11 +99,13 @@ DEVICE ptr_dev = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UNIT ptp_unit = {
|
UNIT ptp_unit = {
|
||||||
UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0)
|
UDATA (&ptp_svc, UNIT_SEQ+UNIT_ATTABLE, SERIAL_OUT_WAIT)
|
||||||
};
|
};
|
||||||
|
|
||||||
REG ptp_reg[] = {
|
REG ptp_reg[] = {
|
||||||
|
{ FLDATA (BIN, ptp_mode, 0) },
|
||||||
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
|
{ DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
|
||||||
|
{ DRDATA (TIME, ptp_unit.wait, 24), PV_LEFT },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,7 +113,8 @@ DEVICE ptp_dev = {
|
||||||
"PTP", &ptp_unit, ptp_reg, NULL,
|
"PTP", &ptp_unit, ptp_reg, NULL,
|
||||||
1, 10, 31, 1, 8, 8,
|
1, 10, 31, 1, 8, 8,
|
||||||
NULL, NULL, &ptp_reset,
|
NULL, NULL, &ptp_reset,
|
||||||
NULL, NULL, NULL
|
NULL, NULL, NULL,
|
||||||
|
NULL, DEV_DEFIO
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Data tables */
|
/* Data tables */
|
||||||
|
@ -136,7 +150,7 @@ const int8 ptr_to_num[128] = {
|
||||||
-1, 0x01, 0x02, -1, 0x04, -1, -1, 0x07, /* XO */
|
-1, 0x01, 0x02, -1, 0x04, -1, -1, 0x07, /* XO */
|
||||||
0x08, -1, -1, 0x0B, -1, -1, -1, -1,
|
0x08, -1, -1, 0x0B, -1, -1, -1, -1,
|
||||||
0x10, -1, -1, 0x03, -1, 0x05, 0x06, -1, /* XOC */
|
0x10, -1, -1, 0x03, -1, 0x05, 0x06, -1, /* XOC */
|
||||||
-1, 0x09, 0x0A, -1, 0x0C, -1, -1, -1 /* X0C82 is not defined but will treat as RM (tfm) */
|
-1, 0x09, 0x1A, -1, 0x0C, -1, -1, -1 /* X0C82 treated as flagged RM, RN only (tfm) */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Paper tape read (7b) to alphameric (two digits) */
|
/* Paper tape read (7b) to alphameric (two digits) */
|
||||||
|
@ -206,116 +220,116 @@ const int8 alp_to_ptp[256] = {
|
||||||
-1, -1, -1, -1, -1, -1, -1, -1
|
-1, -1, -1, -1, -1, -1, -1, -1
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Paper tape reader IO routine
|
/* Paper tape reader IO init routine */
|
||||||
|
|
||||||
|
t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
||||||
|
{
|
||||||
|
if ((op != OP_RN) && (op != OP_RA)) /* RN & RA only */
|
||||||
|
return STOP_INVFNC;
|
||||||
|
if ((ptr_unit.flags & UNIT_ATT) == 0) /* catch unattached */
|
||||||
|
return SCPE_UNATT;
|
||||||
|
ptr_mode = 0;
|
||||||
|
cpuio_set_inp (op, &ptr_unit);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Binary paper tape reader IO init routine */
|
||||||
|
|
||||||
|
t_stat btr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
||||||
|
{
|
||||||
|
if (op != OP_RA) /* RA only */
|
||||||
|
return STOP_INVFNC;
|
||||||
|
if ((ptr_unit.flags & UNIT_ATT) == 0) /* catch unattached */
|
||||||
|
return SCPE_UNATT;
|
||||||
|
ptr_mode = 1;
|
||||||
|
cpuio_set_inp (op, &ptr_unit);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Paper tape unit service
|
||||||
|
|
||||||
|
- If over the limit, cancel IO and return error.
|
||||||
|
- If unattached, reschedule and return error.
|
||||||
|
- Transfer a digit/character.
|
||||||
- Hard errors halt the operation and the system.
|
- Hard errors halt the operation and the system.
|
||||||
- Parity errors place an invalid character in memory and set
|
- Parity errors place an invalid character in memory and set
|
||||||
RDCHK, but the read continues until end of record. If IO
|
RDCHK, but the read continues until end of record. If IO
|
||||||
stop is set, the system then halts.
|
stop is set, the system then halts.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
t_stat ptr_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
uint32 i = 0;
|
t_stat r;
|
||||||
int8 mc;
|
|
||||||
uint8 ptc;
|
uint8 ptc;
|
||||||
t_stat r, sta;
|
int8 mc;
|
||||||
|
|
||||||
sta = SCPE_OK;
|
if (cpuio_cnt >= MEMSIZE) { /* over the limit? */
|
||||||
switch (op) { /* case on op */
|
cpuio_clr_inp (uptr); /* done */
|
||||||
|
return STOP_RWRAP;
|
||||||
|
}
|
||||||
|
sim_activate (uptr, uptr->wait); /* sched another xfer */
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||||
|
return SCPE_UNATT;
|
||||||
|
|
||||||
|
switch (cpuio_opc) {
|
||||||
|
|
||||||
case OP_RN: /* read numeric */
|
case OP_RN: /* read numeric */
|
||||||
for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */
|
r = ptr_read (&ptc, TRUE); /* read frame */
|
||||||
r = ptr_read (&ptc, TRUE); /* read frame */
|
if (r != SCPE_OK) /* error? */
|
||||||
if (r != SCPE_OK) /* error? */
|
return r;
|
||||||
return r;
|
if (ptc & PT_EL) { /* end record? */
|
||||||
if (ptc & PT_EL) { /* end record? */
|
M[PAR] = REC_MARK; /* store rec mark */
|
||||||
M[pa] = REC_MARK; /* store rec mark */
|
break;
|
||||||
return sta; /* done */
|
|
||||||
}
|
|
||||||
mc = ptr_to_num[ptc]; /* translate char */
|
|
||||||
if ((bad_par[ptc]) || (mc < 0)) { /* bad par. or char? */
|
|
||||||
ind[IN_RDCHK] = 1; /* set read check */
|
|
||||||
if (io_stop) /* set return status */
|
|
||||||
sta = STOP_INVCHR;
|
|
||||||
M[pa] = 0; /* store zero */
|
|
||||||
}
|
|
||||||
else M[pa] = mc; /* stor translated char */
|
|
||||||
PP (pa); /* incr mem addr */
|
|
||||||
}
|
}
|
||||||
break;
|
mc = ptr_to_num[ptc]; /* translate char */
|
||||||
|
if ((bad_par[ptc]) || (mc < 0)) { /* bad par. or char? */
|
||||||
|
ind[IN_RDCHK] = 1; /* set read check */
|
||||||
|
mc = 0; /* store zero */
|
||||||
|
}
|
||||||
|
M[PAR] = mc; /* store translated char */
|
||||||
|
PP (PAR); /* incr mem addr */
|
||||||
|
cpuio_cnt++;
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
case OP_RA: /* read alphameric */
|
case OP_RA: /* read alphameric */
|
||||||
for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */
|
r = ptr_read (&ptc, TRUE); /* read frame */
|
||||||
r = ptr_read (&ptc, TRUE); /* read frame */
|
if (r != SCPE_OK) /* error? */
|
||||||
if (r != SCPE_OK) /* error? */
|
return r;
|
||||||
return r;
|
if (ptc & PT_EL) { /* end record? */
|
||||||
if (ptc & PT_EL) { /* end record? */
|
M[PAR] = (M[PAR] & FLAG) | REC_MARK; /* store alpha RM */
|
||||||
M[pa] = (M[pa] & FLAG) | REC_MARK; /* store alpha RM .. */
|
M[PAR - 1] = M[PAR - 1] & FLAG; /* and preserve flags */
|
||||||
M[pa - 1] = M[pa - 1] & FLAG; /* ..and preserve flags */
|
break;
|
||||||
return sta; /* done */
|
}
|
||||||
}
|
if (ptr_mode == 0) { /* normal mode? */
|
||||||
mc = ptr_to_alp[ptc]; /* translate */
|
mc = ptr_to_alp[ptc]; /* translate */
|
||||||
if (bad_par[ptc] || (mc < 0)) { /* bad par or char? */
|
if (bad_par[ptc] || (mc < 0)) { /* bad par or char? */
|
||||||
ind[IN_RDCHK] = 1; /* set read check */
|
ind[IN_RDCHK] = 1; /* set read check */
|
||||||
if (io_stop) /* set return status */
|
|
||||||
sta = STOP_INVCHR;
|
|
||||||
mc = 0; /* store blank */
|
mc = 0; /* store blank */
|
||||||
}
|
}
|
||||||
M[pa] = (M[pa] & FLAG) | (mc & DIGIT); /* store 2 digits */
|
M[PAR] = (M[PAR] & FLAG) | (mc & DIGIT); /* store 2 digits */
|
||||||
M[pa - 1] = (M[pa - 1] & FLAG) | ((mc >> 4) & DIGIT);
|
M[PAR - 1] = (M[PAR - 1] & FLAG) | ((mc >> 4) & DIGIT);
|
||||||
pa = ADDR_A (pa, 2); /* incr mem addr */
|
|
||||||
}
|
}
|
||||||
break;
|
else { /* binary mode */
|
||||||
|
if (bad_par[ptc]) /* bad parity? */
|
||||||
default: /* invalid function */
|
|
||||||
return STOP_INVFNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STOP_RWRAP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Binary paper tape reader IO routine - see above for error handling */
|
|
||||||
|
|
||||||
t_stat btr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
|
||||||
{
|
|
||||||
uint32 i;
|
|
||||||
uint8 ptc;
|
|
||||||
t_stat r, sta;
|
|
||||||
|
|
||||||
if ((cpu_unit.flags & IF_BIN) == 0)
|
|
||||||
return STOP_INVIO;
|
|
||||||
|
|
||||||
sta = SCPE_OK;
|
|
||||||
switch (op) { /* case on op */
|
|
||||||
|
|
||||||
case OP_RA: /* read alphameric */
|
|
||||||
for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */
|
|
||||||
r = ptr_read (&ptc, FALSE); /* read frame */
|
|
||||||
if (r != SCPE_OK) /* error? */
|
|
||||||
return r;
|
|
||||||
if (ptc & PT_EL) { /* end record? */
|
|
||||||
M[pa] = (M[pa] & FLAG) | REC_MARK; /* store alpha RM .. */
|
|
||||||
M[pa - 1] = M[pa - 1] & FLAG; /* ..and preserve flags */
|
|
||||||
return sta; /* done */
|
|
||||||
}
|
|
||||||
if (bad_par[ptc]) { /* bad parity? */
|
|
||||||
ind[IN_RDCHK] = 1; /* set read check */
|
ind[IN_RDCHK] = 1; /* set read check */
|
||||||
if (io_stop) /* set return status */
|
M[PAR] = (M[PAR] & FLAG) | (ptc & 07); /* store 2 digits */
|
||||||
sta = STOP_INVCHR;
|
M[PAR - 1] = (M[PAR - 1] & FLAG) |
|
||||||
}
|
(((ptc >> 4) & 06) | ((ptc >> 3) & 1));
|
||||||
M[pa] = (M[pa] & FLAG) | (ptc & 07); /* store 2 digits */
|
|
||||||
M[pa - 1] = (M[pa - 1] & FLAG) |
|
|
||||||
(((ptc >> 4) & 06) | ((ptc >> 3) & 1));
|
|
||||||
pa = ADDR_A (pa, 2); /* incr mem addr */
|
|
||||||
}
|
}
|
||||||
break;
|
PAR = ADDR_A (PAR, 2); /* incr mem addr */
|
||||||
|
cpuio_cnt = cpuio_cnt + 2;
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
default: /* invalid function */
|
default: /* invalid function */
|
||||||
return STOP_INVFNC;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return STOP_RWRAP;
|
/* IO is complete */
|
||||||
|
|
||||||
|
cpuio_clr_inp (uptr); /* clear IO in progress */
|
||||||
|
if ((ind[IN_RDCHK] != 0) && (io_stop != 0)) /* parity error? */
|
||||||
|
return STOP_INVCHR;
|
||||||
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read ptr frame - all errors are 'hard' errors and halt the system */
|
/* Read ptr frame - all errors are 'hard' errors and halt the system */
|
||||||
|
@ -324,11 +338,6 @@ t_stat ptr_read (uint8 *c, t_bool ignfeed)
|
||||||
{
|
{
|
||||||
int32 temp;
|
int32 temp;
|
||||||
|
|
||||||
if ((ptr_unit.flags & UNIT_ATT) == 0) { /* attached? */
|
|
||||||
ind[IN_RDCHK] = 1; /* no, error */
|
|
||||||
return SCPE_UNATT;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
ind[IN_RDCHK] = 1; /* err, rd chk */
|
||||||
|
@ -352,6 +361,8 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat ptr_reset (DEVICE *dptr)
|
t_stat ptr_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
|
sim_cancel (&ptr_unit);
|
||||||
|
ptr_mode = 0;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,123 +386,121 @@ saved_PC = BOOT_START;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Paper tape punch IO routine
|
/* Paper tape punch IO init routine */
|
||||||
|
|
||||||
- Hard errors halt the operation and the system.
|
|
||||||
- Parity errors stop the operation and set WRCHK.
|
|
||||||
If IO stop is set, the system then halts.
|
|
||||||
*/
|
|
||||||
|
|
||||||
t_stat ptp (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
t_stat ptp (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
||||||
{
|
{
|
||||||
uint32 i;
|
if ((op != OP_WN) && (op != OP_WA) && (op != OP_DN))
|
||||||
|
return STOP_INVFNC;
|
||||||
|
if ((ptp_unit.flags & UNIT_ATT) == 0) /* catch unattached */
|
||||||
|
return SCPE_UNATT;
|
||||||
|
ptp_mode = 0;
|
||||||
|
cpuio_set_inp (op, &ptp_unit);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Binary paper tape punch IO init routine */
|
||||||
|
|
||||||
|
t_stat btp (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
||||||
|
{
|
||||||
|
if (op != OP_WA) /* WA only */
|
||||||
|
return STOP_INVFNC;
|
||||||
|
if ((ptp_unit.flags & UNIT_ATT) == 0) /* catch unattached */
|
||||||
|
return SCPE_UNATT;
|
||||||
|
ptp_mode = 1;
|
||||||
|
cpuio_set_inp (op, &ptp_unit);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Paper tape punch unit service routine */
|
||||||
|
|
||||||
|
t_stat ptp_svc (UNIT *uptr)
|
||||||
|
{
|
||||||
int8 ptc;
|
int8 ptc;
|
||||||
uint8 z, d;
|
uint8 z, d;
|
||||||
t_stat r;
|
t_stat r;
|
||||||
|
|
||||||
switch (op) { /* decode op */
|
if ((cpuio_opc != OP_DN) && (cpuio_cnt >= MEMSIZE)) { /* wrap, ~dump? */
|
||||||
|
cpuio_clr_inp (uptr); /* done */
|
||||||
|
return STOP_RWRAP;
|
||||||
|
}
|
||||||
|
sim_activate (uptr, uptr->wait); /* sched another xfer */
|
||||||
|
if ((uptr->flags & UNIT_ATT) == 0) /* not attached? */
|
||||||
|
return SCPE_UNATT;
|
||||||
|
|
||||||
|
switch (cpuio_opc) { /* decode op */
|
||||||
|
|
||||||
case OP_DN:
|
case OP_DN:
|
||||||
return ptp_num (pa, 20000 - (pa % 20000), TRUE);/* dump numeric */
|
if ((cpuio_cnt != 0) && ((PAR % 20000) == 0)) /* done? */
|
||||||
|
break;
|
||||||
|
return ptp_num (); /* write numeric */
|
||||||
|
|
||||||
case OP_WN:
|
case OP_WN:
|
||||||
return ptp_num (pa, 0, FALSE); /* punch numeric */
|
if ((M[PAR] & REC_MARK) == REC_MARK) /* end record? */
|
||||||
|
break;
|
||||||
|
return ptp_num (); /* write numeric */
|
||||||
|
|
||||||
case OP_WA:
|
case OP_WA:
|
||||||
for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */
|
d = M[PAR] & DIGIT; /* get digit */
|
||||||
d = M[pa] & DIGIT; /* get digit */
|
z = M[PAR - 1] & DIGIT; /* get zone */
|
||||||
z = M[pa - 1] & DIGIT; /* get zone */
|
if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */
|
||||||
if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */
|
break; /* end record */
|
||||||
return ptp_write (PT_EL); /* end record */
|
if (ptp_mode == 0) { /* normal mode */
|
||||||
ptc = alp_to_ptp[(z << 4) | d]; /* translate pair */
|
ptc = alp_to_ptp[(z << 4) | d]; /* translate pair */
|
||||||
if (ptc < 0) { /* bad char? */
|
if (ptc < 0) { /* bad char? */
|
||||||
ind[IN_WRCHK] = 1; /* write check */
|
ind[IN_WRCHK] = 1; /* write check */
|
||||||
CRETIOE (io_stop, STOP_INVCHR);
|
CRETIOE (io_stop, STOP_INVCHR);
|
||||||
}
|
}
|
||||||
r = ptp_write (ptc); /* write char */
|
|
||||||
if (r != SCPE_OK) /* error? */
|
|
||||||
return r;
|
|
||||||
pa = ADDR_A (pa, 2); /* incr mem addr */
|
|
||||||
}
|
}
|
||||||
break;
|
else { /* binary mode */
|
||||||
|
|
||||||
default: /* invalid function */
|
|
||||||
return STOP_INVFNC;
|
|
||||||
}
|
|
||||||
|
|
||||||
return STOP_RWRAP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Binary paper tape punch IO routine - see above for error handling */
|
|
||||||
|
|
||||||
t_stat btp (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
|
||||||
{
|
|
||||||
uint32 i;
|
|
||||||
uint8 ptc, z, d;
|
|
||||||
t_stat r;
|
|
||||||
|
|
||||||
if ((cpu_unit.flags & IF_BIN) == 0) return STOP_INVIO;
|
|
||||||
|
|
||||||
switch (op) { /* decode op */
|
|
||||||
|
|
||||||
case OP_WA:
|
|
||||||
for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */
|
|
||||||
d = M[pa] & DIGIT; /* get digit */
|
|
||||||
z = M[pa - 1] & DIGIT; /* get zone */
|
|
||||||
if ((d & REC_MARK) == REC_MARK) /* 8-2 char? */
|
|
||||||
return ptp_write (PT_EL); /* end record */
|
|
||||||
ptc = ((z & 06) << 4) | ((z & 01) << 3) | (d & 07);
|
ptc = ((z & 06) << 4) | ((z & 01) << 3) | (d & 07);
|
||||||
if (bad_par[ptc]) /* set parity */
|
if (bad_par[ptc]) /* set parity */
|
||||||
ptc = ptc | PT_C;
|
ptc = ptc | PT_C;
|
||||||
r = ptp_write (ptc); /* write char */
|
|
||||||
if (r != SCPE_OK) /* error? */
|
|
||||||
return r;
|
|
||||||
pa = ADDR_A (pa, 2); /* incr mem addr */
|
|
||||||
}
|
}
|
||||||
break;
|
r = ptp_write (ptc); /* write char */
|
||||||
|
if (r != SCPE_OK) /* error? */
|
||||||
|
return r;
|
||||||
|
PAR = ADDR_A (PAR, 2); /* incr mem addr */
|
||||||
|
cpuio_cnt = cpuio_cnt + 2;
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
default: /* invalid function */
|
default: /* invalid function */
|
||||||
return STOP_INVFNC;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return STOP_RWRAP;
|
/* IO is complete */
|
||||||
|
|
||||||
|
ptp_write (PT_EL); /* write record mark */
|
||||||
|
cpuio_clr_inp (uptr); /* IO complete */
|
||||||
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Punch tape numeric - cannot generate parity errors */
|
/* Punch tape numeric - cannot generate parity errors */
|
||||||
|
|
||||||
t_stat ptp_num (uint32 pa, uint32 len, t_bool dump)
|
t_stat ptp_num (void)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
uint8 d;
|
uint8 d;
|
||||||
uint32 i;
|
|
||||||
int8 ptc;
|
int8 ptc;
|
||||||
|
|
||||||
for (i = 0; i < MEMSIZE; i++) { /* stop runaway */
|
d = M[PAR] & (FLAG | DIGIT); /* get char */
|
||||||
d = M[pa] & (FLAG | DIGIT); /* get char */
|
ptc = num_to_ptp[d]; /* translate digit */
|
||||||
if (dump? (len-- == 0): /* dump: end reached? */
|
if (ptc < 0) { /* bad char? */
|
||||||
((d & REC_MARK) == REC_MARK)) /* write: rec mark? */
|
ind[IN_WRCHK] = 1; /* write check */
|
||||||
return ptp_write (PT_EL); /* end record */
|
CRETIOE(io_stop, STOP_INVCHR);
|
||||||
ptc = num_to_ptp[d]; /* translate digit */
|
|
||||||
if (ptc < 0) { /* bad char? */
|
|
||||||
ind[IN_WRCHK] = 1; /* write check */
|
|
||||||
CRETIOE(io_stop, STOP_INVCHR);
|
|
||||||
}
|
|
||||||
r = ptp_write(ptc); /* write char */
|
|
||||||
if (r != SCPE_OK) /* error? */
|
|
||||||
return r;
|
|
||||||
PP (pa); /* incr mem addr */
|
|
||||||
}
|
}
|
||||||
return STOP_RWRAP;
|
r = ptp_write (ptc); /* write char */
|
||||||
|
if (r != SCPE_OK) /* error? */
|
||||||
|
return r;
|
||||||
|
PP (PAR); /* incr mem addr */
|
||||||
|
cpuio_cnt++;
|
||||||
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write ptp frame - all errors are hard errors */
|
/* Write ptp frame - all errors are hard errors */
|
||||||
|
|
||||||
t_stat ptp_write (uint32 c)
|
t_stat ptp_write (uint32 c)
|
||||||
{
|
{
|
||||||
if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */
|
|
||||||
ind[IN_WRCHK] = 1; /* no, error */
|
|
||||||
return SCPE_UNATT;
|
|
||||||
}
|
|
||||||
if (putc (c, ptp_unit.fileref) == EOF) { /* write char */
|
if (putc (c, ptp_unit.fileref) == EOF) { /* write char */
|
||||||
ind[IN_WRCHK] = 1; /* error? */
|
ind[IN_WRCHK] = 1; /* error? */
|
||||||
sim_perror ("PTP I/O error");
|
sim_perror ("PTP I/O error");
|
||||||
|
@ -506,5 +515,7 @@ return SCPE_OK;
|
||||||
|
|
||||||
t_stat ptp_reset (DEVICE *dptr)
|
t_stat ptp_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
|
sim_cancel (&ptp_unit);
|
||||||
|
ptp_mode = 0;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
25-May-17 RMS Tweaks and corrections from Tom McBride
|
||||||
18-May-17 RMS Changed fprint_val to handle undefined opcodes on stops
|
18-May-17 RMS Changed fprint_val to handle undefined opcodes on stops
|
||||||
19-Mar-12 RMS Fixed declaration of CCT (Mark Pizzolato)
|
19-Mar-12 RMS Fixed declaration of CCT (Mark Pizzolato)
|
||||||
*/
|
*/
|
||||||
|
@ -272,7 +273,7 @@ struct opc opcode[] = {
|
||||||
{ "TNS", 72+I_2, 0 }, { "TNF", 73+I_2, 0 },
|
{ "TNS", 72+I_2, 0 }, { "TNF", 73+I_2, 0 },
|
||||||
{ "BBT", 90+I_2, 0 }, { "BMK", 91+I_2, 0 },
|
{ "BBT", 90+I_2, 0 }, { "BMK", 91+I_2, 0 },
|
||||||
{ "ORF", 92+I_2, 0 }, { "ANDF", 93+I_2, 0 },
|
{ "ORF", 92+I_2, 0 }, { "ANDF", 93+I_2, 0 },
|
||||||
{ "CPFL", 94+I_2, 0 }, { "EORF", 95+I_2, 0 },
|
{ "CPLF", 94+I_2, 0 }, { "EORF", 95+I_2, 0 },
|
||||||
{ "OTD", 96+I_2, 0 }, { "DTO", 97+I_2, 0 },
|
{ "OTD", 96+I_2, 0 }, { "DTO", 97+I_2, 0 },
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
@ -399,7 +400,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, "%s", opcode[i].str); /* print opcode */
|
fprintf (of, "%-4s", opcode[i].str); /* 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? */
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
tty console typewriter
|
tty console typewriter
|
||||||
|
|
||||||
|
26-May-17 RMS Added deferred IO
|
||||||
18-May-17 RMS Fixed keyboard interrupt problem for Linux
|
18-May-17 RMS Fixed keyboard interrupt problem for Linux
|
||||||
Added input backspace for Model II
|
Added input backspace for Model II
|
||||||
04-May-17 DW Revised tab calculation algorithm
|
04-May-17 DW Revised tab calculation algorithm
|
||||||
|
@ -46,8 +47,13 @@
|
||||||
#define TTO_COLMAX 80
|
#define TTO_COLMAX 80
|
||||||
#define UF_V_1DIG (UNIT_V_UF)
|
#define UF_V_1DIG (UNIT_V_UF)
|
||||||
#define UF_1DIG (1 << UF_V_1DIG)
|
#define UF_1DIG (1 << UF_V_1DIG)
|
||||||
|
#define UTTI 0
|
||||||
|
#define UTTO 1
|
||||||
|
|
||||||
|
uint32 tti_unlock = 0; /* expecting input */
|
||||||
|
uint32 tti_flag = 0; /* flag typed */
|
||||||
|
int32 tto_col = 1; /* one-based, char loc to print next */
|
||||||
|
|
||||||
int32 tto_col = 1; /* One-based, char cell we will print to next */
|
|
||||||
uint8 tto_tabs[TTO_COLMAX + 1] = { /* Zero-based access, one-based UI */
|
uint8 tto_tabs[TTO_COLMAX + 1] = { /* Zero-based access, one-based UI */
|
||||||
0,0,0,0,0,0,0,0,
|
0,0,0,0,0,0,0,0,
|
||||||
1,0,0,0,0,0,0,0,
|
1,0,0,0,0,0,0,0,
|
||||||
|
@ -66,15 +72,12 @@ extern uint8 M[MAXMEMSIZE];
|
||||||
extern uint8 ind[NUM_IND];
|
extern uint8 ind[NUM_IND];
|
||||||
extern UNIT cpu_unit;
|
extern UNIT cpu_unit;
|
||||||
extern uint32 io_stop;
|
extern uint32 io_stop;
|
||||||
extern volatile int32 stop_cpu;
|
extern uint32 cpuio_inp, cpuio_opc, cpuio_cnt, PAR;
|
||||||
|
|
||||||
void tti_unlock (void);
|
t_stat tto_num (void);
|
||||||
t_stat tti_rnum (int8 *c);
|
|
||||||
t_stat tti_ralp (int8 *c);
|
|
||||||
t_stat tti_read (int8 *c);
|
|
||||||
t_stat tto_num (uint32 pa, uint32 len, t_bool dump);
|
|
||||||
t_stat tto_write (uint32 c);
|
t_stat tto_write (uint32 c);
|
||||||
t_stat tty_svc (UNIT *uptr);
|
t_stat tti_svc (UNIT *uptr);
|
||||||
|
t_stat tto_svc (UNIT *uptr);
|
||||||
t_stat tty_reset (DEVICE *dptr);
|
t_stat tty_reset (DEVICE *dptr);
|
||||||
t_stat tty_set_fixtabs (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
t_stat tty_set_fixtabs (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
|
|
||||||
|
@ -85,11 +88,17 @@ t_stat tty_set_fixtabs (UNIT *uptr, int32 val, CONST char *cptr, void *desc);
|
||||||
tty_reg TTY register list
|
tty_reg TTY register list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UNIT tty_unit = { UDATA (&tty_svc, 0, 0), KBD_POLL_WAIT };
|
UNIT tty_unit[] = {
|
||||||
|
{ UDATA (&tti_svc, 0, 0), KBD_POLL_WAIT },
|
||||||
|
{ UDATA (&tto_svc, 0, 0), SERIAL_OUT_WAIT }
|
||||||
|
};
|
||||||
|
|
||||||
REG tty_reg[] = {
|
REG tty_reg[] = {
|
||||||
|
{ FLDATA (UNLOCK, tti_unlock, 0) },
|
||||||
|
{ FLDATA (FLAG, tti_flag, 0), REG_HRO },
|
||||||
{ DRDATA (COL, tto_col, 7) },
|
{ DRDATA (COL, tto_col, 7) },
|
||||||
{ DRDATA (TIME, tty_unit.wait, 24), REG_NZ + PV_LEFT },
|
{ DRDATA (KTIME, tty_unit[UTTI].wait, 24), REG_NZ + PV_LEFT },
|
||||||
|
{ DRDATA (TTIME, tty_unit[UTTO].wait, 24), REG_NZ + PV_LEFT },
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,10 +117,11 @@ MTAB tty_mod[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
DEVICE tty_dev = {
|
DEVICE tty_dev = {
|
||||||
"TTY", &tty_unit, tty_reg, tty_mod,
|
"TTY", tty_unit, tty_reg, tty_mod,
|
||||||
1, 10, 31, 1, 8, 7,
|
2, 10, 31, 1, 8, 7,
|
||||||
NULL, NULL, &tty_reset,
|
NULL, NULL, &tty_reset,
|
||||||
NULL, NULL, NULL
|
NULL, NULL, NULL,
|
||||||
|
NULL, DEV_DEFIO
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Data tables */
|
/* Data tables */
|
||||||
|
@ -239,12 +249,6 @@ const char alp_to_tto[256] = {
|
||||||
|
|
||||||
t_stat tty (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
t_stat tty (uint32 op, uint32 pa, uint32 f0, uint32 f1)
|
||||||
{
|
{
|
||||||
t_addr i;
|
|
||||||
uint8 d;
|
|
||||||
int8 ttc;
|
|
||||||
t_stat r, sta;
|
|
||||||
|
|
||||||
sta = SCPE_OK;
|
|
||||||
switch (op) { /* case on op */
|
switch (op) { /* case on op */
|
||||||
|
|
||||||
case OP_K: /* control */
|
case OP_K: /* control */
|
||||||
|
@ -271,174 +275,177 @@ switch (op) { /* case on op */
|
||||||
default:
|
default:
|
||||||
return STOP_INVFNC;
|
return STOP_INVFNC;
|
||||||
}
|
}
|
||||||
return SCPE_OK;
|
|
||||||
|
|
||||||
case OP_RN: /* read numeric */
|
|
||||||
tti_unlock (); /* unlock keyboard */
|
|
||||||
for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */
|
|
||||||
r = tti_rnum (&ttc); /* read char */
|
|
||||||
if (r != SCPE_OK) /* error? */
|
|
||||||
return r;
|
|
||||||
if (ttc == 0x7F) /* end record? */
|
|
||||||
return SCPE_OK;
|
|
||||||
if (ttc == 0x7E) { /* backspace? */
|
|
||||||
MM (pa); /* decr mem addr */
|
|
||||||
}
|
|
||||||
else { /* normal char */
|
|
||||||
M[pa] = ttc & (FLAG | DIGIT); /* store char */
|
|
||||||
PP (pa); /* incr mem addr */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OP_RA: /* read alphameric */
|
|
||||||
tti_unlock ();
|
|
||||||
for (i = 0; i < MEMSIZE; i = i + 2) { /* (stop runaway) */
|
|
||||||
r = tti_ralp (&ttc); /* read char */
|
|
||||||
if (r != SCPE_OK) /* error? */
|
|
||||||
return r;
|
|
||||||
if (ttc == 0x7F) /* end record? */
|
|
||||||
return SCPE_OK;
|
|
||||||
if (ttc == 0x7E) { /* backspace? */
|
|
||||||
pa = ADDR_A (pa, -2); /* decr mem addr*/
|
|
||||||
}
|
|
||||||
else { /* normal char */
|
|
||||||
M[pa] = (M[pa] & FLAG) | (ttc & DIGIT); /* store 2 digits */
|
|
||||||
M[pa - 1] = (M[pa - 1] & FLAG) | ((ttc >> 4) & DIGIT);
|
|
||||||
pa = ADDR_A (pa, 2); /* incr mem addr */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OP_DN:
|
|
||||||
return tto_num (pa, 20000 - (pa % 20000), TRUE);/* dump numeric */
|
|
||||||
|
|
||||||
case OP_WN:
|
case OP_WN:
|
||||||
return tto_num (pa, 0, FALSE); /* type numeric */
|
case OP_DN:
|
||||||
|
|
||||||
case OP_WA:
|
case OP_WA:
|
||||||
for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */
|
cpuio_set_inp (op, &tty_unit[UTTO]); /* set IO in progress */
|
||||||
d = M[pa] & DIGIT; /* get digit */
|
break;
|
||||||
if ((d & REC_MARK) == REC_MARK) /* 8-2 char? done */
|
|
||||||
return sta;
|
case OP_RN:
|
||||||
d = ((M[pa - 1] & DIGIT) << 4) | d; /* get digit pair */
|
case OP_RA:
|
||||||
ttc = alp_to_tto[d]; /* translate */
|
tti_unlock = 1; /* unlock keyboard */
|
||||||
if (ttc < 0) { /* bad char? */
|
tti_flag = 0; /* init flag */
|
||||||
ind[IN_WRCHK] = 1; /* set write check */
|
tto_write ('>'); /* prompt user */
|
||||||
if (io_stop) /* set return status */
|
cpuio_set_inp (op, NULL); /* set IO in progress */
|
||||||
sta = STOP_INVCHR;
|
break;
|
||||||
}
|
|
||||||
tto_write (ttc & 0x7F); /* write */
|
|
||||||
pa = ADDR_A (pa, 2); /* incr mem addr */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: /* invalid function */
|
default: /* invalid function */
|
||||||
return STOP_INVFNC;
|
return STOP_INVFNC;
|
||||||
}
|
}
|
||||||
|
|
||||||
return STOP_RWRAP;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read numerically - cannot generate parity errors */
|
/* Input unit service - OP can be RA or RN */
|
||||||
|
|
||||||
t_stat tti_rnum (int8 *c)
|
t_stat tti_svc (UNIT *uptr)
|
||||||
{
|
{
|
||||||
int8 raw, flg = 0;
|
int32 temp;
|
||||||
|
int8 raw, c;
|
||||||
const char *cp;
|
const char *cp;
|
||||||
t_stat r;
|
|
||||||
|
|
||||||
*c = -1; /* no char yet */
|
sim_activate (uptr, uptr->wait); /* continue poll */
|
||||||
do {
|
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */
|
||||||
r = tti_read (&raw); /* get char */
|
return temp;
|
||||||
if (r != SCPE_OK) /* error? */
|
if (tti_unlock == 0) /* expecting input? */
|
||||||
return r;
|
return SCPE_OK; /* no, ignore */
|
||||||
if (raw == '\r') /* return? mark */
|
raw = (int8) temp;
|
||||||
*c = 0x7F;
|
|
||||||
else if (((raw == '\b') || (raw == 0x7F)) && /* backspace or del? */
|
if (raw == '\r') { /* return? */
|
||||||
((cpu_unit.flags & IF_MII) != 0)) { /* on model 2? */
|
|
||||||
*c = 0x7E; /* mark */
|
|
||||||
raw = '-'; /* print minus */
|
|
||||||
}
|
|
||||||
else if ((raw == '~') || (raw == '`')) /* flag? mark */
|
|
||||||
flg = FLAG;
|
|
||||||
else if ((cp = strchr (tti_to_num, raw)) != 0) /* legal? */
|
|
||||||
*c = tti_position_to_internal[(cp - tti_to_num)] | flg; /* assemble char */
|
|
||||||
else raw = 007; /* beep! */
|
|
||||||
tto_write (raw); /* echo */
|
tto_write (raw); /* echo */
|
||||||
} while (*c == -1);
|
tti_unlock = 0; /* no more input */
|
||||||
|
cpuio_clr_inp (NULL);
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
if (cpuio_opc == OP_RN) { /* RN? */
|
||||||
|
if (((raw == '\b') || (raw == 0x7F)) && /* backspace or del? */
|
||||||
|
((cpu_unit.flags & IF_MII) != 0)) { /* on model 2? */
|
||||||
|
tto_write ('-'); /* print minus */
|
||||||
|
MM (PAR); /* decr mem addr */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
else if ((raw == '~') || (raw == '`')) { /* flag? mark */
|
||||||
|
tto_write (raw);
|
||||||
|
tti_flag = FLAG;
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
else if ((cp = strchr (tti_to_num, raw)) == 0) { /* invalid? */
|
||||||
|
tto_write ('\a'); /* beep! */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
tto_write (raw); /* echo */
|
||||||
|
if (cpuio_cnt >= MEMSIZE) { /* wrap around? */
|
||||||
|
tti_unlock = 0; /* no more input */
|
||||||
|
cpuio_clr_inp (NULL);
|
||||||
|
return STOP_RWRAP;
|
||||||
|
}
|
||||||
|
c = tti_position_to_internal[(cp - tti_to_num)] | tti_flag; /* assemble char */
|
||||||
|
M[PAR] = c & (FLAG | DIGIT); /* store char */
|
||||||
|
tti_flag = 0; /* re-init flag */
|
||||||
|
PP (PAR); /* incr mem addr */
|
||||||
|
cpuio_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
else { /* RA */
|
||||||
|
if (((raw == '\b') || (raw == 0x7F)) && /* backspace or del? */
|
||||||
|
((cpu_unit.flags & IF_MII) != 0)) { /* on model 2? */
|
||||||
|
tto_write ('-'); /* print minus */
|
||||||
|
PAR = ADDR_A (PAR, -2); /* decr mem addr*/
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
else if (tti_to_alp[raw] < 0) { /* illegal char? */
|
||||||
|
tto_write ('\a'); /* beep! */
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
tto_write (raw); /* echo */
|
||||||
|
if (cpuio_cnt >= MEMSIZE) { /* wrap around? */
|
||||||
|
tti_unlock = 0; /* no more input */
|
||||||
|
cpuio_clr_inp (NULL);
|
||||||
|
return STOP_RWRAP;
|
||||||
|
}
|
||||||
|
c = tti_to_alp[raw]; /* xlate */
|
||||||
|
M[PAR] = (M[PAR] & FLAG) | (c & DIGIT); /* store 2 digits */
|
||||||
|
M[PAR - 1] = (M[PAR - 1] & FLAG) | ((c >> 4) & DIGIT);
|
||||||
|
PAR = ADDR_A (PAR, 2); /* incr mem addr */
|
||||||
|
cpuio_cnt = cpuio_cnt + 2;
|
||||||
|
}
|
||||||
|
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read alphamerically - cannot generate parity errors */
|
/* Output unit service */
|
||||||
|
|
||||||
t_stat tti_ralp (int8 *c)
|
t_stat tto_svc (UNIT *uptr) {
|
||||||
{
|
|
||||||
int8 raw;
|
|
||||||
t_stat r;
|
|
||||||
|
|
||||||
*c = -1; /* no char yet */
|
uint8 d;
|
||||||
do {
|
int8 ttc;
|
||||||
r = tti_read (&raw); /* get char */
|
t_stat sta = SCPE_OK;
|
||||||
if (r != SCPE_OK) /* error? */
|
|
||||||
return r;
|
|
||||||
if (raw == '\r') /* return? mark */
|
|
||||||
*c = 0x7F;
|
|
||||||
else if (((raw == '\b') || (raw == 0x7F)) && /* backspace or del? */
|
|
||||||
((cpu_unit.flags & IF_MII) != 0)) { /* on model 2? */
|
|
||||||
*c = 0x7E; /* mark */
|
|
||||||
raw = '-'; /* print minus */
|
|
||||||
}
|
|
||||||
else if (tti_to_alp[raw] >= 0) /* legal char? */
|
|
||||||
*c = tti_to_alp[raw]; /* xlate */
|
|
||||||
else raw = 007; /* beep! */
|
|
||||||
tto_write (raw); /* echo */
|
|
||||||
} while (*c == -1);
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read from keyboard */
|
if ((cpuio_opc != OP_DN) && (cpuio_cnt >= MEMSIZE)) { /* wrap, ~dump? */
|
||||||
|
cpuio_clr_inp (uptr); /* done */
|
||||||
|
return STOP_RWRAP;
|
||||||
|
}
|
||||||
|
sim_activate (uptr, uptr->wait); /* sched another xfer */
|
||||||
|
|
||||||
t_stat tti_read (int8 *c)
|
switch (cpuio_opc) { /* decode op */
|
||||||
{
|
|
||||||
int32 t;
|
|
||||||
|
|
||||||
do {
|
case OP_DN:
|
||||||
if (stop_cpu != 0) /* stop? */
|
if ((cpuio_cnt != 0) && ((PAR % 20000) == 0)) /* done? */
|
||||||
return SCPE_STOP;
|
break;
|
||||||
t = sim_poll_kbd (); /* get character */
|
return tto_num (); /* write numeric */
|
||||||
} while ((t == SCPE_OK) || (t & SCPE_BREAK)); /* ignore break */
|
|
||||||
if (t < SCPE_KFLAG) /* error? */
|
case OP_WN:
|
||||||
return t;
|
if ((M[PAR] & REC_MARK) == REC_MARK) /* end record? */
|
||||||
*c = t & 0177; /* store character */
|
break;
|
||||||
return SCPE_OK;
|
return tto_num (); /* write numeric */
|
||||||
|
|
||||||
|
case OP_WA:
|
||||||
|
d = M[PAR] & DIGIT; /* get digit */
|
||||||
|
if ((d & REC_MARK) == REC_MARK) /* 8-2 char? done */
|
||||||
|
break;
|
||||||
|
d = ((M[PAR - 1] & DIGIT) << 4) | d; /* get digit pair */
|
||||||
|
ttc = alp_to_tto[d]; /* translate */
|
||||||
|
if (ttc < 0) { /* bad char? */
|
||||||
|
ind[IN_WRCHK] = 1; /* set write check */
|
||||||
|
if (io_stop) /* set return status */
|
||||||
|
sta = STOP_INVCHR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tto_write (ttc & 0x7F); /* write */
|
||||||
|
PAR = ADDR_A (PAR, 2); /* incr mem addr */
|
||||||
|
cpuio_cnt = cpuio_cnt + 2;
|
||||||
|
return SCPE_OK;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return SCPE_IERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpuio_clr_inp (uptr); /* clear IO in progress */
|
||||||
|
return sta;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write numerically - cannot generate parity errors */
|
/* Write numerically - cannot generate parity errors */
|
||||||
|
|
||||||
t_stat tto_num (uint32 pa, uint32 len, t_bool dump)
|
t_stat tto_num (void)
|
||||||
{
|
{
|
||||||
t_stat r;
|
t_stat r;
|
||||||
uint8 d;
|
uint8 d;
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */
|
d = M[PAR]; /* get char */
|
||||||
d = M[pa]; /* get char */
|
if (tty_unit[UTTO].flags & UF_1DIG) /* how display flagged digits? */
|
||||||
if (dump? (len-- == 0): /* dump: end reached? */
|
r = tto_write (num_to_tto[d & (DIGIT|FLAG)]); /* single digit display */
|
||||||
((d & REC_MARK) == REC_MARK)) /* write: rec mark? */
|
else {
|
||||||
return SCPE_OK; /* end operation */
|
if (d & FLAG) /* flag? */
|
||||||
if (tty_unit.flags & UF_1DIG) /* how display flagged digits? */
|
tto_write ('`'); /* write flag indicator */
|
||||||
r = tto_write (num_to_tto[d]); /* single digit display */
|
r = tto_write (num_to_tto[d & DIGIT]); /* write the digit */
|
||||||
else {
|
}
|
||||||
if (d & FLAG) /* flag? */
|
if (r != SCPE_OK) /* write error? */
|
||||||
tto_write ('`'); /* write flag indicator */
|
return r;
|
||||||
r = tto_write (num_to_tto[d & DIGIT]); /* write the digit */
|
PP (PAR); /* incr mem addr */
|
||||||
}
|
cpuio_cnt++;
|
||||||
if (r != SCPE_OK) /* write error? */
|
return SCPE_OK;
|
||||||
return r;
|
|
||||||
PP (pa); /* incr mem addr */
|
|
||||||
}
|
|
||||||
return STOP_RWRAP;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrap line, if needed, prior to character output */
|
/* Wrap line, if needed, prior to character output */
|
||||||
|
@ -459,7 +466,7 @@ t_stat tto_write (uint32 c)
|
||||||
if (c == '\t') { /* tab? */
|
if (c == '\t') { /* tab? */
|
||||||
tto_wrap();
|
tto_wrap();
|
||||||
do {
|
do {
|
||||||
sim_putchar(' '); /* use spaces */
|
sim_putchar(' '); /* use spaces */
|
||||||
tto_col++;
|
tto_col++;
|
||||||
} while (!(tto_col > TTO_COLMAX || tto_tabs[tto_col-1] == 1));
|
} while (!(tto_col > TTO_COLMAX || tto_tabs[tto_col-1] == 1));
|
||||||
}
|
}
|
||||||
|
@ -468,7 +475,7 @@ else if (c == '\r') { /* return? */
|
||||||
sim_putchar ('\n');
|
sim_putchar ('\n');
|
||||||
tto_col = 1; /* back to LMargin */
|
tto_col = 1; /* back to LMargin */
|
||||||
}
|
}
|
||||||
else if ((c == '\n') || (c == 007)) { /* non-spacing? */
|
else if ((c == '\n') || (c == '\a')) { /* non-spacing? */
|
||||||
sim_putchar (c);
|
sim_putchar (c);
|
||||||
}
|
}
|
||||||
else if (c == '\b') { /* backspace? */
|
else if (c == '\b') { /* backspace? */
|
||||||
|
@ -485,35 +492,17 @@ else { /* normal */
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unit service - polls for WRU */
|
|
||||||
|
|
||||||
t_stat tty_svc (UNIT *uptr)
|
|
||||||
{
|
|
||||||
int32 temp;
|
|
||||||
|
|
||||||
sim_activate (&tty_unit, tty_unit.wait); /* continue poll */
|
|
||||||
if ((temp = sim_poll_kbd ()) < SCPE_KFLAG) /* no char or error? */
|
|
||||||
return temp;
|
|
||||||
return SCPE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset routine */
|
/* Reset routine */
|
||||||
|
|
||||||
t_stat tty_reset (DEVICE *dptr)
|
t_stat tty_reset (DEVICE *dptr)
|
||||||
{
|
{
|
||||||
sim_activate (&tty_unit, tty_unit.wait); /* activate poll */
|
sim_activate (&tty_unit[UTTI], tty_unit[UTTI].wait); /* activate poll */
|
||||||
|
sim_cancel (&tty_unit[UTTO]); /* cancel output */
|
||||||
|
tti_unlock = tti_flag = 0; /* tty locked */
|
||||||
tto_col = 1;
|
tto_col = 1;
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TTI unlock - signals that we are ready for keyboard input */
|
|
||||||
|
|
||||||
void tti_unlock (void)
|
|
||||||
{
|
|
||||||
tto_write ('>');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set tab stops at fixed modulus */
|
/* Set tab stops at fixed modulus */
|
||||||
|
|
||||||
t_stat tty_set_fixtabs (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
t_stat tty_set_fixtabs (UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||||||
|
|
Binary file not shown.
Loading…
Add table
Reference in a new issue