I1620: Fixes Tom McBride

- Card Reader/Punch, Line Printer, Paper Tape Reader/Punch, Typewriter Translation Tables
This commit is contained in:
Mark Pizzolato 2015-04-03 18:38:50 -07:00
parent c221e1ff97
commit 2f350955ec
8 changed files with 292 additions and 166 deletions

View file

@ -1,6 +1,6 @@
/* i1620_cd.c: IBM 1622 card reader/punch /* i1620_cd.c: IBM 1622 card reader/punch
Copyright (c) 2002-2013, Robert M. Supnik Copyright (c) 2002-2015, 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"),
@ -26,6 +26,7 @@
cdr 1622 card reader cdr 1622 card reader
cdp 1622 card punch cdp 1622 card punch
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)
Fixed card reader EOL processing (Bob Armstrong) Fixed card reader EOL processing (Bob Armstrong)
19-Mar-12 RMS Fixed declarations of saved_pc, io_stop (Mark Pizzolato) 19-Mar-12 RMS Fixed declarations of saved_pc, io_stop (Mark Pizzolato)
@ -107,10 +108,38 @@ DEVICE cdp_dev = {
}; };
/* Data tables. The card reader presents unusual problems. /* Data tables. The card reader presents unusual problems.
- Unique codes needed for 11-2-8 (uses !) and 12-7-8 (uses ") .
- Can punch both 11 (-) and 11-0 (uses ]). Some of these translations may seem strange. The 1620 could
On input, the nul and nl generated by C are converted to read and punch cards numerically (one 1620 storage location
spaces; tabs and line feeds are also converted to spaces. per card column) or alphabetically (two 1620 storage locations
per card column). Even though a card might have contained any
possible character (digit, letter, special character), it
could still be read numerically. In this case, some characters
behaved the same as numbers or as record marks. The results
are well defined in IBM documentation.
In order to make it possible to prepare card decks for input
using normal text editors, ASCII characters have been assigned
to represent 1620 characters that could appear on cards. In most
cases, this was easy since the letters, digits and punctuation
characters all have equivalent ASCII assignments. Five 1620
characters do not have equivalent ASCII graphics and are
assigned as follows:
] is used to represent a flagged zero
| is used to represent a record mark
! is used to represent a flagged record mark
} is used to represent a group mark
" is used to represent a flagged group mark
As a concession to some editors, ASCII nul, nl, tab, and lf
characters are accepted and converted to blanks. Also, for
the same reason, lower case letters are treated the same as
upper case on input. All other ASCII characters not in the
1620 character set are treated as errors.
(Tom McBride)
*/ */
/* Card reader (ASCII) to numeric (one digit) */ /* Card reader (ASCII) to numeric (one digit) */
@ -119,36 +148,47 @@ const int8 cdr_to_num[128] = {
-1, 0x00, 0x00, -1, -1, 0x00, -1, -1, -1, 0x00, 0x00, -1, -1, 0x00, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0x00, 0x1A, 0x0F, 0x0B, 0x1B, 0x0C, 0x00, 0x0C, /* !"#$%&' */ 0x00, 0x1A, 0x1F, -1, 0x1B, -1, -1, -1, /* !" $ */
0x0C, 0x0C, 0x1C, 0x00, 0x0B, 0x10, 0x1B, 0x01, /* ()*+,-./ */ 0x0C, 0x0C, 0x1C, 0x00, 0x0B, 0x10, 0x0B, 0x01, /* ()*+,-./ */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 01234567 */
0x08, 0x09, 0x00, 0x1E, 0x1E, 0x0B, 0x0E, 0x1A, /* 89:;<=>? */ 0x08, 0x09, -1, -1, -1, 0x0B, -1, -1, /* 89 = */
0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* @ABCDEFG */ 0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* @ABCDEFG */
0x08, 0x09, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* HIJKLMNO */ 0x08, 0x09, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* HIJKLMNO */
0x17, 0x18, 0x19, 0x02, 0x03, 0x04, 0x05, 0x06, /* PQRSTUVW */ 0x17, 0x18, 0x19, 0x02, 0x03, 0x04, 0x05, 0x06, /* PQRSTUVW */
0x07, 0x08, 0x09, 0x00, 0x0E, 0x10, 0x0A, 0x1F, /* XYZ[\]^_ */ 0x07, 0x08, 0x09, -1, -1, 0x10, -1, -1, /* XYZ ] */
-1, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* `abcdefg */ -1, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* `abcdefg */
0x08, 0x09, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* hijklmno */ 0x08, 0x09, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, /* hijklmno */
0x17, 0x18, 0x19, 0x02, 0x03, 0x04, 0x05, 0x06, /* pqrstuvw */ 0x17, 0x18, 0x19, 0x02, 0x03, 0x04, 0x05, 0x06, /* pqrstuvw */
0x07, 0x08, 0x09, 0x0F, 0x0A, 0x1F, 0x00, -1 /* xyz{|}~ */ 0x07, 0x08, 0x09, -1, 0x0A, 0x0F, -1, -1 /* xyz |} */
}; };
/* Numeric (flag + digit) to card punch (ASCII) */ /* Numeric (flag + digit) to card punch (ASCII) */
/* Note that all valid digits produce different
codes except that both numeric blanks and flagged
numeric blanks both produce a blank column. (tfm) */
const int8 num_to_cdp[32] = { const int8 num_to_cdp[32] = {
'0', '1', '2', '3', '4', '5', '6', '7', /* 0 */ '0', '1', '2', '3', '4', '5', '6', '7', /* 0 */
'8', '9', '|', ',', ' ', '"', ' ', '"', '8', '9', '|', -1, ' ', -1, -1, '}',
']', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* F + 0 */ ']', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* F + 0 */
'Q', 'R', '!', '$', -1, -1, -1, '"' 'Q', 'R', '!', -1, ' ', -1, -1, '"'
}; };
/* Card reader (ASCII) to alphameric (two digits) /* Card reader (ASCII) to alphameric (two digits)
11-2-8 (!) reads as 5A ] reads as 50 (flagged zero)
11-7-8 (_) reads as 5F | reads as 0A (record mark)
12-2-8 (?) reads inconsistently (here 02) ! reads as 5A (flagged record mark)
12-6-8 (<) reads inconsistently (here 5E) } reads as 0F (group mark)
12-7-8 (}) reads as 5F " reads as 5F (flagged group mark)
As a concession to some editors, ASCII nul, nl, tab, and lf
characters are accepted and converted to blanks. Also, for
the same reason, lower case letters are treated the same as
upper case on input. All other ASCII characters not in the
1620 character set are treated as errors.
*/ */
const int8 cdr_to_alp[128] = { const int8 cdr_to_alp[128] = {
@ -156,63 +196,58 @@ const int8 cdr_to_alp[128] = {
-1, 0x00, 0x00, -1, -1, 0x00, -1, -1, -1, 0x00, 0x00, -1, -1, 0x00, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0x00, 0x5A, 0x0F, 0x33, 0x13, 0x24, 0x10, 0x34, /* !"#$%&' */ 0x00, 0x5A, 0x5F, -1, 0x13, -1, -1, -1, /* !" $ */
0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */ 0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */
0x78, 0x79, 0x70, 0x5E, 0x5E, 0x33, 0x0E, 0x02, /* 89:;<=>? */ 0x78, 0x79, -1, -1, -1, 0x33, -1, -1, /* 89 = */
0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */ 0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */ 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */
0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */ 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */
0x67, 0x68, 0x69, 0x40, 0x0E, 0x50, 0x0A, 0x5F, /* XYZ[\]^_ */ 0x67, 0x68, 0x69, -1, -1, 0x50, -1, -1, /* XYZ ] */
0x50, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* `abcdefg */ -1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* abcdefg */
0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */ 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */
0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */ 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */
0x67, 0x68, 0x69, 0x0F, 0x0A, 0x5F, 0x60, -1 /* xyz{|}~ */ 0x67, 0x68, 0x69, -1, 0x0A, 0x0F, -1, -1 /* xyz |} */
}; };
/* Alphameric (two digits) to card punch (ASCII). Oddities: /* Alphameric (two digits) to card punch (ASCII).
02 -> 12-2-8 (?), symmetric All 1620 compilers are know to punch numeric data
07 -> 12-7-8 (}), reads as 5F (i.e. data that it knows will be read back using RNCD)
12 -> 11-2-8 (!), reads as 5A in alphameric mode with WACD. Because of that, there are some
15 -> 11,0 (`), reads as 50
22 -> 0-2-8 (|), reads as 0A
32 -> 2-8 (^), reads as 0A
5B -> 11-3-8 (=), reads as 13
6A -> 0-2-8 (|), reads as 0A
6B -> 0-3-8 (,), reads as 23
AA -> 0-2-8 (|), reads as 0A
There is no way to punch 0-5-8 (~), 0-6-8 (\),
11-5-8 (]), 11-6-8 (;), 11-7-8 (_),
12-5-8 ([), or 12-6-8 (<)
According to Bob Armstrong,
the FORTRAN compiler is sneaky and actually punches numeric
data (i.e. data that it knows will be read back using RNCD)
in alphameric mode with WACD. Because of that there are some
alpha to ASCII translations that absolutely MUST work out right alpha to ASCII translations that absolutely MUST work out right
or otherwise we won't be able to load FORTRAN object decks. or otherwise we won't be able to load the object decks.
50 - must "punch" as ] (flagged zero) (used to be "_") 50 - punches as ] (flagged zero)
0A - must "punch" as | (record mark) (used to be "'") 0A - punches as | (record mark)
0F - punches as } (group mark)
If a program punches alphameric data that includes a flagged
record mark or flagged group mark, they will be punched
as below. No known IBM compiler punches any of these but
some application programs do. The mapping of characters for
the card reader and punch is such that a card deck can be
duplicated with a RACD, WACD loop.
5A - punches as ! (flagged record mark)
5F - punches as " (flagged group mark)
*/ */
const int8 alp_to_cdp[256] = { const int8 alp_to_cdp[256] = {
' ', -1, '?', '.', ')', -1, -1, '}', /* 00 */ ' ', -1, -1, '.', ')', -1, -1, -1, /* 00 */
-1, -1, '|', -1, -1, -1, -1, '"', -1, -1, '|', -1, -1, -1, -1, '}',
'+', -1, '!', '$', '*', ']', -1, -1, /* 10 */ '+', -1, -1, '$', '*', -1, -1, -1, /* 10 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
'-', '/', '|', ',', '(', -1, -1, -1, /* 20 */ '-', '/', -1, ',', '(', -1, -1, -1, /* 20 */
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, '=', '@', -1, -1, -1, /* 30 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, '^', '=', '@', ':', ' ', -1, /* 30 */
-1, -1, '|', -1, -1, -1, -1, '"',
-1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */
'H', 'I', -1, -1, -1, -1, -1, -1, 'H', 'I', -1, -1, -1, -1, -1, -1,
']', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ ']', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */
'Q', 'R', '?', '=', -1, -1, -1, '}', 'Q', 'R', '!', -1, -1, -1, -1, '"',
-1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ -1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */
'Y', 'Z', '|', ',', -1, -1, -1, -1, 'Y', 'Z', -1, -1, -1, -1, -1, -1,
'0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */
'8', '9', -1, -1, -1, -1, -1, -1, '8', '9', -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
@ -220,7 +255,7 @@ const int8 alp_to_cdp[256] = {
-1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* A0 */ -1, -1, -1, -1, -1, -1, -1, -1, /* A0 */
-1, -1, '|', -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* B0 */ -1, -1, -1, -1, -1, -1, -1, -1, /* B0 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* C0 */ -1, -1, -1, -1, -1, -1, -1, -1, /* C0 */
@ -315,7 +350,7 @@ if (feof (cdr_unit.fileref)) /* eof? */
return STOP_NOCD; return STOP_NOCD;
if (ferror (cdr_unit.fileref)) { /* error? */ if (ferror (cdr_unit.fileref)) { /* error? */
ind[IN_RDCHK] = 1; /* set read check */ ind[IN_RDCHK] = 1; /* set read check */
perror ("CDR I/O error"); sim_printf ("CDR I/O error: %s", strerror (errno));
clearerr (cdr_unit.fileref); clearerr (cdr_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;
} }
@ -331,7 +366,7 @@ if ((i = strlen (cdr_buf)) > 0) { /* anything at all? */
} }
else { /* line too long */ else { /* line too long */
ind[IN_RDCHK] = 1; ind[IN_RDCHK] = 1;
perror ("CDR line too long"); sim_printf ("CDR line too long");
return SCPE_IOERR; return SCPE_IOERR;
} }
} }
@ -395,12 +430,38 @@ uint8 z, d;
switch (op) { /* decode op */ switch (op) { /* decode op */
case OP_DN: case OP_DN:
return cdp_num (pa, 20000 - (pa % 20000), TRUE);/* dump numeric */
/* DN punches all characters the same as WN except that a flagged
zero is punched as a hypehen (-) instead of a flagged
zero ([). Punching begins at the P address and continues until
the last digit of the storage module containing the P address
has been punched. If the amount of data to be punched is an
exact multiple of 80, the operation ends there. If the last
character of the module does not fill out the card, additional
characters from the next higher addresses (addressing wraps to
back to zero if the operation started in the highest module) are
used to fill out the card. (Tom McBride) */
return cdp_num (pa, /* dump numeric */
((20000 - (pa % 20000) + 79) / 80) * 80,
TRUE);
case OP_WN: case OP_WN:
/* WN always punches exactly 80 characters. If the highest address
in the machine is reached before the card is full, addressing
wraps around to zero and continues. The PP function handles
this correctly. (Tom McBride) */
return cdp_num (pa, CD_LEN, FALSE); /* write numeric */ return cdp_num (pa, CD_LEN, FALSE); /* write numeric */
case OP_WA: case OP_WA: /* write alphanumerically */
/* WA always punches exactly 80 characters. If the highest address
in the machine is reached before the card is full, addressing
wraps around to zero and continues. The ADDR_A function handles
this correctly. (Tom McBride) */
for (i = 0; i < CD_LEN; i++) { /* one card */ for (i = 0; i < CD_LEN; i++) { /* one card */
d = M[pa] & DIGIT; /* get digit pair */ d = M[pa] & DIGIT; /* get digit pair */
z = M[pa - 1] & DIGIT; z = M[pa - 1] & DIGIT;
@ -437,8 +498,8 @@ while (ncd-- >= 0) { /* until done */
break; break;
for (i = 0; i < len; i++) { /* one card */ for (i = 0; i < len; i++) { /* one card */
d = M[pa] & (FLAG | DIGIT); /* get char */ d = M[pa] & (FLAG | DIGIT); /* get char */
if (dump && (d == FLAG)) /* dump? F+0 is diff */ if (dump && (d == FLAG)) /* dump? F+0 is diff .. */
cdc = '-'; cdc = '-'; /* .. punch as hyphen */
else cdc = num_to_cdp[d]; /* translate */ else cdc = num_to_cdp[d]; /* translate */
if (cdc < 0) { /* bad char? */ if (cdc < 0) { /* bad char? */
ind[IN_WRCHK] = 1; /* set write check */ ind[IN_WRCHK] = 1; /* set write check */
@ -472,7 +533,7 @@ fputs (cdp_buf, cdp_unit.fileref); /* write card */
cdp_unit.pos = ftell (cdp_unit.fileref); /* count char */ cdp_unit.pos = ftell (cdp_unit.fileref); /* count char */
if (ferror (cdp_unit.fileref)) { /* error? */ if (ferror (cdp_unit.fileref)) { /* error? */
ind[IN_WRCHK] = 1; ind[IN_WRCHK] = 1;
perror ("CDP I/O error"); sim_printf ("CDR I/O error: %s", strerror (errno));
clearerr (cdp_unit.fileref); clearerr (cdp_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;
} }

View file

@ -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.
28-Mar-15 RMS Revised to use sim_printf
26-Mar-15 RMS Separated compare from add/sub flows (Tom McBride) 26-Mar-15 RMS Separated compare from add/sub flows (Tom McBride)
Removed ADD_SIGNC return from add/sub flows Removed ADD_SIGNC return from add/sub flows
10-Dec-13 RMS Fixed several bugs in add and compare (Bob Armstrong) 10-Dec-13 RMS Fixed several bugs in add and compare (Bob Armstrong)

View file

@ -1,6 +1,6 @@
/* i1620_defs.h: IBM 1620 simulator definitions /* i1620_defs.h: IBM 1620 simulator definitions
Copyright (c) 2002-2010, Robert M. Supnik Copyright (c) 2002-2015, 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"),
@ -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.
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
18-Oct-02 RMS Fixed bug in ADDR_S macro (found by Hans Pufal) 18-Oct-02 RMS Fixed bug in ADDR_S macro (found by Hans Pufal)
*/ */
@ -158,6 +159,9 @@
#define REC_MARK 0xA #define REC_MARK 0xA
#define NUM_BLANK 0xC #define NUM_BLANK 0xC
#define GRP_MARK 0xF #define GRP_MARK 0xF
#define FLG_REC_MARK 0x1A
#define FLG_NUM_BLANK 0x1C
#define FLG_GRP_MARK 0x1F
#define BAD_DIGIT(x) ((x) > 9) #define BAD_DIGIT(x) ((x) > 9)
/* Instruction format */ /* Instruction format */

View file

@ -1,6 +1,6 @@
/* i1620_dp.c: IBM 1311 disk simulator /* i1620_dp.c: IBM 1311 disk simulator
Copyright (c) 2002-2008, Robert M. Supnik Copyright (c) 2002-2015, 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"),

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-2013, Robert M. Supnik Copyright (c) 2002-2015, 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,7 @@
lpt 1443 line printer lpt 1443 line printer
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)
19-Jan-07 RMS Added UNIT_TEXT flag 19-Jan-07 RMS Added UNIT_TEXT flag
@ -58,7 +59,7 @@ t_stat lpt_svc (UNIT *uptr);
t_stat lpt_reset (DEVICE *dptr); t_stat lpt_reset (DEVICE *dptr);
t_stat lpt_attach (UNIT *uptr, char *cptr); t_stat lpt_attach (UNIT *uptr, char *cptr);
void lpt_buf_init (void); void lpt_buf_init (void);
t_stat lpt_num (uint32 pa, uint32 len, uint32 f1, t_bool dump); t_stat lpt_num(uint32 pa, uint32 f1, t_bool dump); /* tfm: length parameter removed, not needed */
t_stat lpt_print (void); t_stat lpt_print (void);
t_stat lpt_space (int32 lines, int32 lflag); t_stat lpt_space (int32 lines, int32 lflag);
@ -101,29 +102,29 @@ DEVICE lpt_dev = {
/* Numeric (flag plus digit) to lineprinter (ASCII) */ /* Numeric (flag plus digit) to lineprinter (ASCII) */
const char num_to_lpt[32] = { const int8 num_to_lpt[32] = {
'0', '1', '2', '3', '4', '5', '6', '7', '0', '1', '2', '3', '4', '5', '6', '7', /* tfm: All invalid char treated as errors */
'8', '9', '|', ' ', '@', ':', ' ', 'G', '8', '9', '|', -1, '@', -1, -1, 'G', /* tfm: @, 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, 'X' 'Q', 'R', 'W', -1, '*', -1, -1, 'X' /* tfm: W, *, X only print on DN */
}; };
/* Alphameric (digit pair) to lineprinter (ASCII) */ /* Alphameric (digit pair) to lineprinter (ASCII) */
const char alp_to_lpt[256] = { const int8 alp_to_lpt[256] = { /* tfm: invalid codes 02, 12, 15, 32, 35, 61 removed */
' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */ ' ', -1, -1, '.', ')', -1, -1, -1, /* 00 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
'+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ '+', -1, -1, '$', '*', -1, -1, -1, /* 10 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
'-', '/', '|', ',', '(', -1, -1, -1, /* 20 */ '-', '/', '|', ',', '(', -1, -1, -1, /* 20 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ -1, -1, -1, '=', '@', -1, -1, -1, /* 30 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */
'H', 'I', -1, -1, -1, -1, -1, -1, 'H', 'I', -1, -1, -1, -1, -1, -1,
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */
'Q', 'R', -1, -1, -1, -1, -1, -1, 'Q', 'R', -1, -1, -1, -1, -1, -1,
-1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ -1, -1, 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */
'Y', 'Z', -1, -1, -1, -1, -1, -1, 'Y', 'Z', -1, -1, -1, -1, -1, -1,
'0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */
'8', '9', -1, -1, -1, -1, -1, -1, '8', '9', -1, -1, -1, -1, -1, -1,
@ -171,10 +172,10 @@ switch (op) { /* decode op */
break; break;
case OP_DN: case OP_DN:
return lpt_num (pa, 20000 - (pa % 20000), f1, TRUE); /* dump numeric */ return lpt_num (pa, f1, TRUE); /* dump numeric (tfm: removed len parm ) */
case OP_WN: case OP_WN:
return lpt_num (pa, 0, f1, FALSE); /* write numeric */ return lpt_num (pa, f1, FALSE); /* write numeric (tfm: removed len parm ) */
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 */
@ -207,7 +208,7 @@ return SCPE_OK;
/* Print numeric */ /* Print numeric */
t_stat lpt_num (uint32 pa, uint32 len, uint32 f1, t_bool dump) t_stat lpt_num (uint32 pa, uint32 f1, t_bool dump) /* tfm: removed len parm and reorganized code */
{ {
uint8 d; uint8 d;
int8 lpc; int8 lpc;
@ -215,17 +216,20 @@ t_stat r, sta;
sta = SCPE_OK; sta = SCPE_OK;
for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */ for ( ; lpt_bptr < LPT_BSIZE; lpt_bptr++) { /* only fill buf */
d = M[pa]; /* get digit */ d = M[pa]; /* get data char */
if (dump? (len-- == 0): /* end reached? */ if (!dump && /* not dumping? */
((d & REC_MARK) == REC_MARK)) ((d & REC_MARK) == REC_MARK)) /* quit on RM or GM */
break; break;
lpc = num_to_lpt[d]; /* translate */ lpc = num_to_lpt[d]; /* translate digit */
if (!dump && /* if not dumping */
((d & DIGIT) == NUM_BLANK)) /* translate numeric blank */
lpc = ' '; /* to normal space */
if (lpc < 0) { /* bad char? */ if (lpc < 0) { /* bad char? */
ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */ ind[IN_WRCHK] = ind[IN_PRCHK] = 1; /* wr chk */
if (io_stop) /* set return status */ if (io_stop) /* set return status */
sta = STOP_INVCHR; sta = STOP_INVCHR;
} }
lpt_buf[lpt_bptr++] = lpc & 0x7F; /* fill buffer */ 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? */ if ((f1 & 1) == 0) { /* print now? */
@ -260,7 +264,7 @@ if (lpt_bptr) { /* any line? */
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] = ind[IN_WRCHK] = 1; /* wr, pri check */
perror ("LPT I/O error"); sim_printf ("LPT I/O error: %s", strerror (errno));
clearerr (lpt_unit.fileref); clearerr (lpt_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;
} }
@ -311,7 +315,7 @@ ind[IN_PRCH9] = CHP (9, cct[cct_ptr]) != 0; /* set indicators */
ind[IN_PRCH12] = CHP (12, cct[cct_ptr]) != 0; ind[IN_PRCH12] = CHP (12, cct[cct_ptr]) != 0;
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] = ind[IN_WRCHK] = 1; /* wr, pri check */
perror ("LPT I/O error"); sim_printf ("LPT I/O error: %s", strerror (errno));
clearerr (lpt_unit.fileref); clearerr (lpt_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;
} }

View file

@ -1,6 +1,6 @@
/* i1620_pt.c: IBM 1621/1624 paper tape reader/punch simulator /* i1620_pt.c: IBM 1621/1624 paper tape reader/punch simulator
Copyright (c) 2002-2013, Robert M Supnik Copyright (c) 2002-2015, 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"),
@ -26,6 +26,9 @@
ptr 1621 paper tape reader ptr 1621 paper tape reader
ptp 1624 paper tape punch ptp 1624 paper tape punch
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 pack/unpack errors in binary r/w (Tom McBride)
21-Dec-13 RMS Fixed translation of paper tape code X0C 21-Dec-13 RMS Fixed translation of paper tape code X0C
10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong) 10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong)
19-Mar-12 RMS Fixed declaration of io_stop (Mark Pizzolato) 19-Mar-12 RMS Fixed declaration of io_stop (Mark Pizzolato)
@ -117,75 +120,73 @@ const int8 bad_par[128] = {
/* Paper tape read (7b) to numeric (one digit) */ /* Paper tape read (7b) to numeric (one digit) */
const int8 ptr_to_num[128] = { const int8 ptr_to_num[128] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* - */ -1, 0x01, 0x02, -1, 0x04, -1, -1, 0x07, /* - */
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, 0x08, -1, -1, 0x0B, -1, -1, -1, -1,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* C */ 0x00, -1, -1, 0x03, -1, 0x05, 0x06, -1, /* C */
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, -1, 0x09, -1, -1, 0x0C, -1, -1, -1,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* O */ 0x00, -1, -1, 0x03, -1, 0x05, 0x06, -1, /* O */
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, -1, 0x09, 0x0A, -1, 0x0C, -1, -1, 0x0F,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* OC */ -1, 0x01, 0x02, -1, 0x04, -1, -1, 0x07, /* OC */
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, 0x08, -1, -1, 0x0B, -1, -1, -1, -1,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* X */ 0x10, -1, -1, 0x13, -1, 0x15, 0x16, -1, /* X */
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F, -1, 0x19, 0x1A, -1, 0x1C, -1, -1, 0x1F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* XC */ -1, 0x11, 0x12, -1, 0x14, -1, -1, 0x17, /* XC */
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F, 0x18, -1, -1, 0x1B, -1, -1, -1, -1,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XO */ -1, 0x01, 0x02, -1, 0x04, -1, -1, 0x07, /* XO */
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F, 0x08, -1, -1, 0x0B, -1, -1, -1, -1,
0x10, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* XOC */ 0x10, -1, -1, 0x03, -1, 0x05, 0x06, -1, /* XOC */
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F -1, 0x09, 0x0A, -1, 0x0C, -1, -1, -1 /* X0C82 is not defined but will treat as RM (tfm) */
}; };
/* Paper tape read (7b) to alphameric (two digits) /* Paper tape read (7b) to alphameric (two digits) */
Codes XO82, 82, XO842, 842 do not have consistent translations
*/
const int8 ptr_to_alp[128] = { const int8 ptr_to_alp[128] = {
0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* - */ 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* - */
0x78, 0x79, -1, 0x33, 0x34, 0x70, -1, 0x0F, 0x78, 0x79, -1, 0x33, 0x34, -1, -1, -1,
0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* C */ 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* C */
0x78, 0x79, -1, 0x33, 0x34, 0x70, -1, 0x0F, 0x78, 0x79, -1, 0x33, 0x34, -1, -1, -1,
0x70, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* O */ 0x70, 0x21, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* O */
0x68, 0x69, 0x0A, 0x23, 0x24, 0x60, 0x0E, 0x0F, 0x68, 0x69, 0x0A, 0x23, 0x24, -1, -1, 0x0F,
0x70, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* OC */ 0x70, 0x21, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* OC */
0x68, 0x69, 0x0A, 0x23, 0x24, 0x60, 0x0E, 0x0F, 0x68, 0x69, 0x0A, 0x23, 0x24, -1, -1, 0x0F,
0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* X */ 0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* X */
0x58, 0x59, 0x5A, 0x13, 0x14, 0x50, 0x5E, 0x5F, 0x58, 0x59, 0x5A, 0x13, 0x14, -1, -1, 0x5F,
0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* XC */ 0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* XC */
0x58, 0x59, 0x5A, 0x13, 0x14, 0x50, 0x5E, 0x5F, 0x58, 0x59, 0x5A, 0x13, 0x14, -1, -1, 0x5F,
0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* XO */ 0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* XO */
0x48, 0x49, -1, 0x03, 0x04, 0x40, -1, 0x7F, 0x48, 0x49, -1, 0x03, 0x04, -1, -1, -1,
0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* XOC */ 0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* XOC */
0x48, 0x49, -1, 0x03, 0x04, 0x40, -1, 0x7F 0x48, 0x49, -1, 0x03, 0x04, -1, -1, -1
}; };
/* Numeric (flag + digit) to paper tape punch */ /* Numeric (flag + digit) to paper tape punch */
const int8 num_to_ptp[32] = { const int8 num_to_ptp[32] = {
0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07, /* 0 */ 0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07, /* 0 */
0x08, 0x19, 0x2A, 0x3B, 0x1C, 0x0D, 0x3E, 0x3F, 0x08, 0x19, 0x2A, -1, 0x1C, -1, -1, 0x2F,
0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57, /* F + 0 */ 0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57, /* F + 0 */
0x58, 0x49, 0x4A, 0x5B, 0x4C, 0x5D, 0x5E, 0x4F 0x58, 0x49, 0x4A, -1, 0x4C, -1, -1, 0x4F
}; };
/* Alphameric (two digits) to paper tape punch */ /* Alphameric (two digits) to paper tape punch */
const int8 alp_to_ptp[256] = { const int8 alp_to_ptp[256] = {
0x10, -1, 0x7A, 0x6B, 0x7C, -1, -1, 0x7F, /* 00 */ 0x10, -1, -1, 0x6B, 0x7C, -1, -1, -1, /* 00 */
-1, -1, 0x2A, -1, -1, -1, -1, 0x1F,
0x70, -1, 0x4A, 0x5B, 0x4C, -1, -1, -1, /* 10 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0x40, 0x31, 0x2A, 0x3B, 0x2C, -1, -1, -1, /* 20 */ 0x70, -1, -1, 0x5B, 0x4C, -1, -1, -1, /* 10 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, 0x1A, 0x0B, 0x1C, 0x0D, 0x0E, -1, /* 30 */ 0x40, 0x31, -1, 0x3B, 0x2C, -1, -1, -1, /* 20 */
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 0x0B, 0x1C, -1, -1, -1, /* 30 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 0x61, 0x62, 0x73, 0x64, 0x75, 0x76, 0x67, /* 40 */ -1, 0x61, 0x62, 0x73, 0x64, 0x75, 0x76, 0x67, /* 40 */
0x68, 0x79, -1, -1, -1, -1, -1, -1, 0x68, 0x79, -1, -1, -1, -1, -1, -1,
0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57, /* 50 */ 0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57, /* 50 */
0x58, 0x49, 0x4A, -1, -1, -1, -1, 0x4F, 0x58, 0x49, -1, -1, -1, -1, -1, -1,
-1, 0x31, 0x32, 0x23, 0x34, 0x25, 0x26, 0x37, /* 60 */ -1, -1, 0x32, 0x23, 0x34, 0x25, 0x26, 0x37, /* 60 */
0x38, 0x29, -1, -1, -1, -1, -1, -1, 0x38, 0x29, -1, -1, -1, -1, -1, -1,
0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07, /* 70 */ 0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07, /* 70 */
0x08, 0x19, 0x7A, -1, -1, -1, -1, 0x7F, 0x08, 0x19, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* 80 */ -1, -1, -1, -1, -1, -1, -1, -1, /* 80 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* 90 */ -1, -1, -1, -1, -1, -1, -1, -1, /* 90 */
@ -214,7 +215,7 @@ const int8 alp_to_ptp[256] = {
t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1) t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
{ {
uint32 i, q = 0; uint32 i = 0;
int8 mc; int8 mc;
uint8 ptc; uint8 ptc;
t_stat r, sta; t_stat r, sta;
@ -231,15 +232,14 @@ switch (op) { /* case on op */
M[pa] = REC_MARK; /* store rec mark */ M[pa] = REC_MARK; /* store rec mark */
return sta; /* done */ return sta; /* done */
} }
if (pa == 18976) mc = ptr_to_num[ptc]; /* translate char */
q++; if ((bad_par[ptc]) || (mc < 0)) { /* bad par. or char? */
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 */ if (io_stop) /* set return status */
sta = STOP_INVCHR; sta = STOP_INVCHR;
M[pa] = 0; /* store zero */ M[pa] = 0; /* store zero */
} }
else M[pa] = ptr_to_num[ptc]; /* translate, store */ else M[pa] = mc; /* stor translated char */
PP (pa); /* incr mem addr */ PP (pa); /* incr mem addr */
} }
break; break;
@ -250,8 +250,8 @@ switch (op) { /* case on op */
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[pa] = REC_MARK; /* store rec mark */ M[pa] = (M[pa] & FLAG) | REC_MARK; /* store alpha RM .. */
M[pa - 1] = 0; M[pa - 1] = M[pa - 1] & FLAG; /* ..and preserve flags */
return sta; /* done */ return sta; /* done */
} }
mc = ptr_to_alp[ptc]; /* translate */ mc = ptr_to_alp[ptc]; /* translate */
@ -294,8 +294,8 @@ switch (op) { /* case on op */
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[pa] = REC_MARK; /* store rec mark */ M[pa] = (M[pa] & FLAG) | REC_MARK; /* store alpha RM .. */
M[pa - 1] = 0; M[pa - 1] = M[pa - 1] & FLAG; /* ..and preserve flags */
return sta; /* done */ return sta; /* done */
} }
if (bad_par[ptc]) { /* bad parity? */ if (bad_par[ptc]) { /* bad parity? */
@ -305,7 +305,7 @@ switch (op) { /* case on op */
} }
M[pa] = (M[pa] & FLAG) | (ptc & 07); /* store 2 digits */ M[pa] = (M[pa] & FLAG) | (ptc & 07); /* store 2 digits */
M[pa - 1] = (M[pa - 1] & FLAG) | M[pa - 1] = (M[pa - 1] & FLAG) |
(((ptc >> 5) & 06) | ((ptc >> 3) & 1)); (((ptc >> 4) & 06) | ((ptc >> 3) & 1));
pa = ADDR_A (pa, 2); /* incr mem addr */ pa = ADDR_A (pa, 2); /* incr mem addr */
} }
break; break;
@ -334,7 +334,7 @@ do {
if (feof (ptr_unit.fileref)) if (feof (ptr_unit.fileref))
sim_printf ("PTR end of file\n"); sim_printf ("PTR end of file\n");
else else
sim_printf ("PTR I/O error: %d\n", errno); sim_printf ("PTR I/O error: %s", strerror (errno));
clearerr (ptr_unit.fileref); clearerr (ptr_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;
} }
@ -354,13 +354,7 @@ return SCPE_OK;
/* Bootstrap routine */ /* Bootstrap routine */
static const uint8 boot_rom[] = { static const uint8 boot_rom[] = {
4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* NOP */ 3, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, /* RNPT 0 */
3, 6, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0, /* RNPT 31 */
2, 5, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0, /* TD 71,loc */
3, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, /* RNPT loc1 */
2, 6, 0, 0, 0, 6, 6, 0, 0, 0, 3, 5, /* TF 66,35 */
1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* TDM loc2,loc3 */
4, 9, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0 /* BR 12 */
}; };
#define BOOT_START 0 #define BOOT_START 0
@ -442,7 +436,7 @@ switch (op) { /* decode op */
z = M[pa - 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? */
return ptp_write (PT_EL); /* end record */ return ptp_write (PT_EL); /* end record */
ptc = ((z & 06) << 5) | ((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 */ r = ptp_write (ptc); /* write char */
@ -466,13 +460,19 @@ t_stat ptp_num (uint32 pa, uint32 len, t_bool dump)
t_stat r; t_stat r;
uint8 d; uint8 d;
uint32 i; uint32 i;
int8 ptc;
for (i = 0; i < MEMSIZE; i++) { /* stop runaway */ for (i = 0; i < MEMSIZE; i++) { /* stop runaway */
d = M[pa] & (FLAG | DIGIT); /* get char */ d = M[pa] & (FLAG | DIGIT); /* get char */
if (dump? (len-- == 0): /* dump: end reached? */ if (dump? (len-- == 0): /* dump: end reached? */
((d & REC_MARK) == REC_MARK)) /* write: rec mark? */ ((d & REC_MARK) == REC_MARK)) /* write: rec mark? */
return ptp_write (PT_EL); /* end record */ return ptp_write (PT_EL); /* end record */
r = ptp_write (num_to_ptp[d]); /* write */ 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? */ if (r != SCPE_OK) /* error? */
return r; return r;
PP (pa); /* incr mem addr */ PP (pa); /* incr mem addr */
@ -490,7 +490,7 @@ if ((ptp_unit.flags & UNIT_ATT) == 0) { /* attached? */
} }
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? */
perror ("PTP I/O error"); sim_printf ("PTP I/O error: %s", strerror (errno));
clearerr (ptp_unit.fileref); clearerr (ptp_unit.fileref);
return SCPE_IOERR; return SCPE_IOERR;
} }

View file

@ -1,6 +1,6 @@
/* i1620_sys.c: IBM 1620 simulator interface /* i1620_sys.c: IBM 1620 simulator interface
Copyright (c) 2002-2008, Robert M. Supnik Copyright (c) 2002-2015, 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"),

View file

@ -1,6 +1,6 @@
/* i1620_tty.c: IBM 1620 typewriter /* i1620_tty.c: IBM 1620 typewriter
Copyright (c) 2002-2014, Robert M. Supnik Copyright (c) 2002-2015, 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 @@
tty console typewriter tty console typewriter
21-Feb-15 TFM Option to provide single digit numeric output
05-Feb-15 TFM Changes to translate tables and valid input char.
02-Jan-14 RMS Added variable tab stops 02-Jan-14 RMS Added variable tab stops
10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong) 10-Dec-13 RMS Fixed DN wraparound (Bob Armstrong)
21-Sep-05 RMS Revised translation tables for 7094/1401 compatibility 21-Sep-05 RMS Revised translation tables for 7094/1401 compatibility
@ -33,7 +35,11 @@
#include "i1620_defs.h" #include "i1620_defs.h"
#define NUM_1_DIGIT TRUE /* Indicate numeric output will use single digit format (tfm) */
#define TTO_COLMAX 80 #define TTO_COLMAX 80
#define UF_V_1DIG (UNIT_V_UF)
#define UF_1DIG (1 << UF_V_1DIG)
int32 tto_col = 0; int32 tto_col = 0;
uint8 tto_tabs[TTO_COLMAX + 1] = { uint8 tto_tabs[TTO_COLMAX + 1] = {
@ -89,6 +95,8 @@ MTAB tty_mod[] = {
&tty_set_fixtabs, NULL, NULL }, &tty_set_fixtabs, NULL, NULL },
{ MTAB_XTD|MTAB_VDV, 8, NULL, "DEFAULTTABS", { MTAB_XTD|MTAB_VDV, 8, NULL, "DEFAULTTABS",
&tty_set_fixtabs, NULL, NULL }, &tty_set_fixtabs, NULL, NULL },
{ UF_1DIG, UF_1DIG, "combined digits and flags", "1DIGIT", NULL },
{ UF_1DIG, 0 , "separate digits and flags", "2DIGIT", NULL },
{ 0 } { 0 }
}; };
@ -103,7 +111,39 @@ DEVICE tty_dev = {
/* Keyboard to numeric */ /* Keyboard to numeric */
const char *tti_to_num = "0123456789|=@:;}"; /* The following constant is a list of valid 1620 numeric characters
that can be entered from the keyboard. They are the digits 0-9,
record mark(|), numeric blank(@) and group mark(}). All others
are cosidered invalid. When entering data, these characters may
all be preceeded by tilde(~) or accent(`) to indicate that the
following character should be entered into storage with a flag.
Alternatively, ] can be entered for flagged 0,
J-R or j-r can be entered for flagged 1-9,
! for flagged RM, * for flagged numeric blank,
" for flagged GM.
These different methods of entering numeric data represent
compromises since there is no practical way to exactly emulate
the 1620 typewriter capability of entering a flag but not
spacing the carriage. Entering a flag symbol in front of a
character is easier and sometimes more readable; using the
letters j-r is useful if column alignment is important on
the screen or when copying data that has printed letters in
place of flagged digits. This also matches the output of WN
or DN to the line printer.
*tti_to_num is the string of valid characters
tti_position_to_internal[] are the matching internal codes
(Tom McBride)*/
const char *tti_to_num = "0123456789|@}]jklmnopqr!*\"JKLMNOPQR";
const char tti_position_to_internal[35] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, REC_MARK, NUM_BLANK, GRP_MARK,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
FLG_REC_MARK, FLG_NUM_BLANK, FLG_GRP_MARK,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19
};
/* Keyboard to alphameric (digit pair) - translates LC to UC */ /* Keyboard to alphameric (digit pair) - translates LC to UC */
@ -112,43 +152,55 @@ const int8 tti_to_alp[128] = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, /* 10 */ -1, -1, -1, -1, -1, -1, -1, -1, /* 10 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
0x00, 0x02, -1, 0x33, 0x13, 0x24, 0x10, 0x34, /* !"#$%&' */ 0x00, 0x5A, 0x5F, -1, 0x13, -1, -1, -1, /* !"#$%&' */
0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */ 0x24, 0x04, 0x14, 0x10, 0x23, 0x20, 0x03, 0x21, /* ()*+,-./ */
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 01234567 */
0x78, 0x79, -1, -1, -1, 0x33, -1, -1, /* 89:;<=>? */ 0x78, 0x79, -1, -1, -1, 0x33, -1, -1, /* 89:;<=>? */
0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */ 0x34, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* @ABCDEFG */
0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */ 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* HIJKLMNO */
0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */ 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* PQRSTUVW */
0x67, 0x68, 0x69, -1, -1, -1, -1, -1, /* XYZ[\]^_ */ 0x67, 0x68, 0x69, -1, -1, 0x50, -1, -1, /* XYZ[\]^_ */
-1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* `abcdefg */ -1, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* `abcdefg */
0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */ 0x48, 0x49, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, /* hijklmno */
0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */ 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66, /* pqrstuvw */
0x67, 0x68, 0x69, -1, -1, 0x0F, -1, -1 /* xyz{|}~ */ 0x67, 0x68, 0x69, -1, 0x0A, 0x0F, -1, -1 /* xyz{|}~ */
}; };
/* Numeric (digit) to typewriter */ /* Numeric (digit) to typewriter */
const char num_to_tto[16] = { /* Digits with values of 11, 13 and 14 should never occur and will be typed as :'s
if they ever do. These are really errors. (Tom McBride) */
/* If flagged digits are being printed with preceeding ` characters only the first
half of this table is actually used. If digits are being printed one char per
digit the whole table is used. (Tom McBride) */
const char num_to_tto[32] = {
'0', '1', '2', '3', '4', '5', '6', '7', '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', '|', '=', '@', ':', ';', '}' '8', '9', '|', ':', '@', ':', ':', '}',
']', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', '!', ':', '*', ':', ':', '"'
}; };
/* Alphameric (digit pair) to typewriter */ /* Alphameric (digit pair) to typewriter */
/* Characters not in 1620 set have been removed from table (tfm) */
const char alp_to_tto[256] = { const char alp_to_tto[256] = {
' ', -1, '?', '.', ')', -1, -1, -1, /* 00 */ ' ', -1, -1, '.', ')', -1, -1, -1, /* 00 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
'+', -1, '!', '$', '*', ' ', -1, -1, /* 10 */ '+', -1, -1, '$', '*', -1, -1, -1, /* 10 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
'-', '/', '|', ',', '(', -1, -1, -1, /* 20 */ '-', '/', -1, ',', '(', -1, -1, -1, /* 20 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, '0', '=', '@', ':', -1, -1, /* 30 */ -1, -1, -1, '=', '@', -1, -1, -1, /* 30 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */ -1, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 40 */
'H', 'I', -1, -1, -1, -1, -1, -1, 'H', 'I', -1, -1, -1, -1, -1, -1,
'-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */ '-', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 50 */
'Q', 'R', -1, -1, -1, -1, -1, -1, 'Q', 'R', -1, -1, -1, -1, -1, -1,
-1, '/', 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */ -1, -1, 'S', 'T', 'U', 'V', 'W', 'X', /* 60 */
'Y', 'Z', -1, -1, -1, -1, -1, -1, 'Y', 'Z', -1, -1, -1, -1, -1, -1,
'0', '1', '2', '3', '4', '5', '6', '7', /* 70 */ '0', '1', '2', '3', '4', '5', '6', '7', /* 70 */
'8', '9', -1, -1, -1, -1, -1, -1, '8', '9', -1, -1, -1, -1, -1, -1,
@ -250,7 +302,7 @@ switch (op) { /* case on op */
case OP_WA: case OP_WA:
for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */ for (i = 0; i < MEMSIZE; i = i + 2) { /* stop runaway */
d = M[pa] & DIGIT; /* get digit */ d = M[pa] & DIGIT; /* get digit */
if ((d & 0xA) == REC_MARK) /* 8-2 char? done */ if ((d & REC_MARK) == REC_MARK) /* 8-2 char? done */
return sta; return sta;
d = ((M[pa - 1] & DIGIT) << 4) | d; /* get digit pair */ d = ((M[pa - 1] & DIGIT) << 4) | d; /* get digit pair */
ttc = alp_to_tto[d]; /* translate */ ttc = alp_to_tto[d]; /* translate */
@ -276,7 +328,7 @@ return STOP_RWRAP;
t_stat tti_rnum (int8 *c) t_stat tti_rnum (int8 *c)
{ {
int8 raw, flg = 0; int8 raw, flg = 0;
char *cp; const char *cp;
t_stat r; t_stat r;
*c = -1; /* no char yet */ *c = -1; /* no char yet */
@ -288,8 +340,8 @@ do {
*c = 0x7F; *c = 0x7F;
else if ((raw == '~') || (raw == '`')) /* flag? mark */ else if ((raw == '~') || (raw == '`')) /* flag? mark */
flg = FLAG; flg = FLAG;
else if ((cp = strchr (tti_to_num, raw))) /* legal? */ else if ((cp = strchr (tti_to_num, raw)) != 0) /* legal? */
*c = ((int8) (cp - tti_to_num)) | flg; /* assemble char */ *c = tti_position_to_internal[(cp - tti_to_num)] | flg; /* assemble char */
else raw = 007; /* beep! */ else raw = 007; /* beep! */
tto_write (raw); /* echo */ tto_write (raw); /* echo */
} while (*c == -1); } while (*c == -1);
@ -346,10 +398,14 @@ for (i = 0; i < MEMSIZE; i++) { /* (stop runaway) */
if (dump? (len-- == 0): /* dump: end reached? */ if (dump? (len-- == 0): /* dump: end reached? */
((d & REC_MARK) == REC_MARK)) /* write: rec mark? */ ((d & REC_MARK) == REC_MARK)) /* write: rec mark? */
return SCPE_OK; /* end operation */ return SCPE_OK; /* end operation */
if (d & FLAG) /* flag? */ if (tty_unit.flags & UF_1DIG) /* how display flagged digits? */
tto_write ('`'); r = tto_write (num_to_tto[d]); /* single digit display */
r = tto_write (num_to_tto[d & DIGIT]); /* write */ else {
if (r != SCPE_OK) /* error? */ if (d & FLAG) /* flag? */
tto_write ('`'); /* write flag indicator */
r = tto_write (num_to_tto[d & DIGIT]); /* write the digit */
}
if (r != SCPE_OK) /* write error? */
return r; return r;
PP (pa); /* incr mem addr */ PP (pa); /* incr mem addr */
} }