~ubuntu-branches/ubuntu/utopic/simh/utopic

« back to all changes in this revision

Viewing changes to I1620/i1620_pt.c

  • Committer: Bazaar Package Importer
  • Author(s): Vince Mulhollon
  • Date: 2004-04-20 20:01:26 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040420200126-ehsuleda8xcgi51h
Tags: 3.2.0-1
New upstream 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* i1620_pt.c: IBM 1621/1624 paper tape reader/punch simulator
 
2
 
 
3
   Copyright (c) 2002-2004, Robert M Supnik
 
4
 
 
5
   Permission is hereby granted, free of charge, to any person obtaining a
 
6
   copy of this software and associated documentation files (the "Software"),
 
7
   to deal in the Software without restriction, including without limitation
 
8
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
9
   and/or sell copies of the Software, and to permit persons to whom the
 
10
   Software is furnished to do so, subject to the following conditions:
 
11
 
 
12
   The above copyright notice and this permission notice shall be included in
 
13
   all copies or substantial portions of the Software.
 
14
 
 
15
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
18
   ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 
19
   IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
   Except as contained in this notice, the name of Robert M Supnik shall not
 
23
   be used in advertising or otherwise to promote the sale, use or other dealings
 
24
   in this Software without prior written authorization from Robert M Supnik.
 
25
 
 
26
   ptr          1621 paper tape reader
 
27
   ptp          1624 paper tape punch
 
28
 
 
29
   25-Apr-03    RMS     Revised for extended file support
 
30
*/
 
31
 
 
32
#include "i1620_defs.h"
 
33
 
 
34
#define PT_EL   0x80                                    /* end record */
 
35
#define PT_X    0x40                                    /* X */
 
36
#define PT_O    0x20                                    /* O */
 
37
#define PT_C    0x10                                    /* C */
 
38
#define PT_FD   0x7F                                    /* deleted */
 
39
 
 
40
extern uint8 M[MAXMEMSIZE];
 
41
extern uint8 ind[NUM_IND];
 
42
extern UNIT cpu_unit;
 
43
extern uint32 io_stop;
 
44
 
 
45
t_stat ptr_reset (DEVICE *dptr);
 
46
t_stat ptr_boot (int32 unitno, DEVICE *dptr);
 
47
t_stat ptr_read (uint8 *c, t_bool ignfeed);
 
48
t_stat ptp_reset (DEVICE *dptr);
 
49
t_stat ptp_write (uint32 c);
 
50
t_stat ptp_num (uint32 pa, uint32 len);
 
51
 
 
52
/* PTR data structures
 
53
 
 
54
   ptr_dev      PTR device descriptor
 
55
   ptr_unit     PTR unit descriptor
 
56
   ptr_reg      PTR register list
 
57
*/
 
58
 
 
59
UNIT ptr_unit = {
 
60
        UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE+UNIT_ROABLE, 0) };
 
61
 
 
62
REG ptr_reg[] = {
 
63
        { DRDATA (POS, ptr_unit.pos, T_ADDR_W), PV_LEFT },
 
64
        { NULL }  };
 
65
 
 
66
DEVICE ptr_dev = {
 
67
        "PTR", &ptr_unit, ptr_reg, NULL,
 
68
        1, 10, 31, 1, 8, 8,
 
69
        NULL, NULL, &ptr_reset,
 
70
        &ptr_boot, NULL, NULL };
 
71
 
 
72
/* PTP data structures
 
73
 
 
74
   ptp_dev      PTP device descriptor
 
75
   ptp_unit     PTP unit descriptor
 
76
   ptp_reg      PTP register list
 
77
*/
 
78
 
 
79
UNIT ptp_unit = {
 
80
        UDATA (NULL, UNIT_SEQ+UNIT_ATTABLE, 0) };
 
81
 
 
82
REG ptp_reg[] = {
 
83
        { DRDATA (POS, ptp_unit.pos, T_ADDR_W), PV_LEFT },
 
84
        { NULL }  };
 
85
 
 
86
DEVICE ptp_dev = {
 
87
        "PTP", &ptp_unit, ptp_reg, NULL,
 
88
        1, 10, 31, 1, 8, 8,
 
89
        NULL, NULL, &ptp_reset,
 
90
        NULL, NULL, NULL };
 
91
 
 
92
/* Data tables */
 
93
 
 
94
/* Paper tape reader odd parity chart: 1 = bad, 0 = ok */
 
95
 
 
96
const int8 bad_par[128] = {
 
97
 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,        /* 00 */
 
98
 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,        /* 10 */
 
99
 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,        /* 20 */
 
100
 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,        /* 30 */
 
101
 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,        /* 40 */
 
102
 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,        /* 50 */
 
103
 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,        /* 60 */
 
104
 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };      /* 70 */
 
105
 
 
106
/* Paper tape read (7b) to numeric (one digit) */
 
107
 
 
108
const int8 ptr_to_num[128] = {
 
109
 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,        /* - */
 
110
 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F,
 
111
 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,        /* C */
 
112
 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F,
 
113
 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,        /* O */
 
114
 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F,
 
115
 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,        /* OC */
 
116
 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F,
 
117
 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,        /* X */
 
118
 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F,
 
119
 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,        /* XC */
 
120
 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x10, 0x1E, 0x1F,
 
121
 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,        /* XO */
 
122
 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F,
 
123
 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,        /* XOC */
 
124
 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00, 0x0E, 0x0F };
 
125
 
 
126
/* Paper tape read (7b) to alphameric (two digits)
 
127
   Codes XO82, 82, XO842, 842 do not have consistent translations
 
128
*/
 
129
 
 
130
const int8 ptr_to_alp[128] = {
 
131
 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,        /* - */
 
132
 0x78, 0x79,   -1, 0x33, 0x34, 0x70,   -1, 0x0F,
 
133
 0x00, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,        /* C */
 
134
 0x78, 0x79,   -1, 0x33, 0x34, 0x70,   -1, 0x0F,
 
135
 0x70, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,        /* O */
 
136
 0x68, 0x69, 0x0A, 0x23, 0x24, 0x60, 0x0E, 0x0F,
 
137
 0x70, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,        /* OC */
 
138
 0x68, 0x69, 0x0A, 0x23, 0x24, 0x60, 0x0E, 0x0F,
 
139
 0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,        /* X */
 
140
 0x58, 0x59, 0x5A, 0x13, 0x14, 0x50, 0x5E, 0x5F,
 
141
 0x20, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,        /* XC */
 
142
 0x58, 0x59, 0x5A, 0x13, 0x14, 0x50, 0x5E, 0x5F,
 
143
 0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,        /* XO */
 
144
 0x48, 0x49,   -1, 0x03, 0x04, 0x40,   -1, 0x7F,
 
145
 0x10, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,        /* XOC */
 
146
 0x48, 0x49,   -1, 0x03, 0x04, 0x40,   -1, 0x7F };
 
147
 
 
148
/* Numeric (flag + digit) to paper tape punch */
 
149
 
 
150
const int8 num_to_ptp[32] = {
 
151
 0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07,        /* 0 */
 
152
 0x08, 0x19, 0x2A, 0x3B, 0x1C, 0x0D, 0x3E, 0x3F,
 
153
 0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57,        /* F + 0 */
 
154
 0x58, 0x49, 0x4A, 0x5B, 0x4C, 0x5D, 0x5E, 0x4F };
 
155
 
 
156
/* Alphameric (two digits) to paper tape punch */
 
157
 
 
158
const int8 alp_to_ptp[256] = {
 
159
 0x10,   -1, 0x7A, 0x6B, 0x7C,   -1,   -1, 0x7F,        /* 00 */
 
160
   -1,   -1, 0x2A,   -1,   -1,   -1,   -1, 0x1F,
 
161
 0x70,   -1, 0x4A, 0x5B, 0x4C,   -1,   -1,   -1,        /* 10 */
 
162
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
163
 0x40, 0x31, 0x2A, 0x3B, 0x2C,   -1,   -1,   -1,        /* 20 */ 
 
164
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
165
   -1,   -1, 0x1A, 0x0B, 0x1C, 0x0D, 0x0E,   -1,        /* 30 */
 
166
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
167
   -1, 0x61, 0x62, 0x73, 0x64, 0x75, 0x76, 0x67,        /* 40 */
 
168
 0x68, 0x79,   -1,   -1,   -1,   -1,   -1,   -1,
 
169
 0x40, 0x51, 0x52, 0x43, 0x54, 0x45, 0x46, 0x57,        /* 50 */
 
170
 0x58, 0x49, 0x4A,   -1,   -1,   -1,   -1, 0x4F,
 
171
   -1, 0x31, 0x32, 0x23, 0x34, 0x25, 0x26, 0x37,        /* 60 */
 
172
 0x38, 0x29,   -1,   -1,   -1,   -1,   -1,   -1,
 
173
 0x20, 0x01, 0x02, 0x13, 0x04, 0x15, 0x16, 0x07,        /* 70 */
 
174
 0x08, 0x19, 0x7A,   -1,   -1,   -1,   -1, 0x7F,
 
175
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,        /* 80 */
 
176
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
177
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,        /* 90 */
 
178
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
179
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,        /* A0 */
 
180
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
181
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,        /* B0 */
 
182
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
183
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,        /* C0 */
 
184
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
185
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,        /* D0 */
 
186
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
187
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,        /* E0 */
 
188
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,
 
189
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1,        /* F0 */
 
190
   -1,   -1,   -1,   -1,   -1,   -1,   -1,   -1 }; 
 
191
 
 
192
/* Paper tape reader IO routine
 
193
 
 
194
   - Hard errors halt the operation and the system.
 
195
   - Parity errors place an invalid character in memory and set
 
196
     RDCHK, but the read continues until end of record.  If IO
 
197
     stop is set, the system then halts.
 
198
*/
 
199
 
 
200
t_stat ptr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
 
201
{
 
202
uint32 i;
 
203
int8 mc;
 
204
uint8 ptc;
 
205
t_stat r, inv = SCPE_OK;
 
206
 
 
207
switch (op) {                                           /* case on op */
 
208
case OP_RN:                                             /* read numeric */
 
209
        for (i = 0; i < MEMSIZE; i++) {                 /* (stop runaway) */
 
210
            r = ptr_read (&ptc, TRUE);                  /* read frame */
 
211
            if (r != SCPE_OK) return r;                 /* error? */
 
212
            if (ptc & PT_EL) {                          /* end record? */
 
213
                M[pa] = REC_MARK;                       /* store rec mark */
 
214
                CRETIOE (io_stop, inv);  }              /* done */
 
215
            if (bad_par[ptc]) {                         /* bad parity? */
 
216
                ind[IN_RDCHK] = 1;                      /* set read check */
 
217
                inv = STOP_INVCHR;                      /* set return status */
 
218
                M[pa] = 0;  }                           /* store zero */
 
219
            else M[pa] = ptr_to_num[ptc];               /* translate, store */
 
220
            PP (pa);  }                                 /* incr mem addr */
 
221
        break;
 
222
case OP_RA:                                             /* read alphameric */
 
223
        for (i = 0; i < MEMSIZE; i = i + 2) {           /* (stop runaway) */
 
224
            r = ptr_read (&ptc, TRUE);                  /* read frame */
 
225
            if (r != SCPE_OK) return r;                 /* error? */
 
226
            if (ptc & PT_EL) {                          /* end record? */
 
227
                M[pa] = REC_MARK;                       /* store rec mark */
 
228
                M[pa - 1] = 0;
 
229
                CRETIOE (io_stop, inv);  }              /* done */
 
230
            mc = ptr_to_alp[ptc];                       /* translate */
 
231
            if (bad_par[ptc] || (mc < 0)) {             /* bad par or char? */
 
232
                ind[IN_RDCHK] = 1;                      /* set read check */
 
233
                inv = STOP_INVCHR;                      /* set return status */
 
234
                mc = 0;  }                              /* store blank */
 
235
            M[pa] = (M[pa] & FLAG) | (mc & DIGIT);      /* store 2 digits */
 
236
            M[pa - 1] = (M[pa - 1] & FLAG) | ((mc >> 4) & DIGIT);
 
237
            pa = ADDR_A (pa, 2);  }                     /* incr mem addr */
 
238
        break;  
 
239
default:                                                /* invalid function */
 
240
        return STOP_INVFNC;  }
 
241
return STOP_RWRAP;
 
242
}
 
243
 
 
244
/* Binary paper tape reader IO routine - see above for error handling */
 
245
 
 
246
t_stat btr (uint32 op, uint32 pa, uint32 f0, uint32 f1)
 
247
{
 
248
uint32 i;
 
249
uint8 ptc;
 
250
t_stat r, inv = SCPE_OK;
 
251
 
 
252
if ((cpu_unit.flags & IF_BIN) == 0) return STOP_INVIO;
 
253
switch (op) {                                           /* case on op */
 
254
case OP_RA:                                             /* read alphameric */
 
255
        for (i = 0; i < MEMSIZE; i = i + 2) {           /* (stop runaway) */
 
256
            r = ptr_read (&ptc, FALSE);                 /* read frame */
 
257
            if (r != SCPE_OK) return r;                 /* error? */
 
258
            if (ptc & PT_EL) {                          /* end record? */
 
259
                M[pa] = REC_MARK;                       /* store rec mark */
 
260
                M[pa - 1] = 0;
 
261
                CRETIOE (io_stop, inv);  }              /* done */
 
262
            if (bad_par[ptc]) {                         /* bad parity? */
 
263
                ind[IN_RDCHK] = 1;                      /* set read check */
 
264
                inv = STOP_INVCHR;  }                   /* set return status */
 
265
            M[pa] = (M[pa] & FLAG) | (ptc & 07);        /* store 2 digits */
 
266
            M[pa - 1] = (M[pa - 1] & FLAG) |
 
267
                (((ptc >> 5) & 06) | ((ptc >> 3) & 1));
 
268
            pa = ADDR_A (pa, 2);  }                     /* incr mem addr */
 
269
        break;  
 
270
default:                                                /* invalid function */
 
271
        return STOP_INVFNC;  }
 
272
return STOP_RWRAP;
 
273
}
 
274
 
 
275
/* Read ptr frame - all errors are 'hard' errors and halt the system */
 
276
 
 
277
t_stat ptr_read (uint8 *c, t_bool ignfeed)
 
278
{
 
279
int32 temp;
 
280
 
 
281
if ((ptr_unit.flags & UNIT_ATT) == 0) {                 /* attached? */
 
282
        ind[IN_RDCHK] = 1;                              /* no, error */
 
283
        return SCPE_UNATT;  }
 
284
 
 
285
do {    if ((temp = getc (ptr_unit.fileref)) == EOF) {  /* read char */
 
286
            ind[IN_RDCHK] = 1;                  /* err, rd chk */
 
287
            if (feof (ptr_unit.fileref))
 
288
                printf ("PTR end of file\n");
 
289
            else perror ("PTR I/O error");
 
290
            clearerr (ptr_unit.fileref);
 
291
            return SCPE_IOERR;  }
 
292
        *c = temp & 0377;                               /* save char */
 
293
        ptr_unit.pos = ptr_unit.pos + 1;  }             /* incr file addr */
 
294
while (ignfeed && (*c == PT_FD));                       /* until not feed */
 
295
return SCPE_OK;
 
296
}
 
297
 
 
298
/* Reset routine */
 
299
 
 
300
t_stat ptr_reset (DEVICE *dptr)
 
301
{
 
302
return SCPE_OK;
 
303
}
 
304
 
 
305
/* Bootstrap routine */
 
306
 
 
307
const static uint8 boot_rom[] = {
 
308
 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                    /* NOP */
 
309
 3, 6, 0, 0, 0, 3, 1, 0, 0, 3, 0, 0,                    /* RNPT 31 */
 
310
 2, 5, 0, 0, 0, 7, 1, 0, 0, 0, 0, 0,                    /* TD 71,loc */
 
311
 3, 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,                    /* RNPT loc1 */
 
312
 2, 6, 0, 0, 0, 6, 6, 0, 0, 0, 3, 5,                    /* TF 66,35 */
 
313
 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                    /* TDM loc2,loc3 */
 
314
 4, 9, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0 };                  /* BR 12 */
 
315
 
 
316
#define BOOT_START      0
 
317
#define BOOT_LEN        (sizeof (boot_rom) / sizeof (uint8))
 
318
 
 
319
t_stat ptr_boot (int32 unitno, DEVICE *dptr)
 
320
{
 
321
int32 i;
 
322
extern int32 saved_PC;
 
323
 
 
324
for (i = 0; i < BOOT_LEN; i++) M[BOOT_START + i] = boot_rom[i];
 
325
saved_PC = BOOT_START;
 
326
return SCPE_OK;
 
327
}
 
328
 
 
329
/* Paper tape punch IO routine
 
330
 
 
331
   - Hard errors halt the operation and the system.
 
332
   - Parity errors stop the operation and set WRCHK.
 
333
     If IO stop is set, the system then halts.
 
334
*/
 
335
 
 
336
t_stat ptp (uint32 op, uint32 pa, uint32 f0, uint32 f1)
 
337
{
 
338
uint32 i;
 
339
int8 ptc;
 
340
uint8 z, d;
 
341
t_stat r;
 
342
 
 
343
switch (op) {                                           /* decode op */
 
344
case OP_DN:
 
345
        return ptp_num (pa, 20000 - (pa % 20000));      /* dump numeric */
 
346
case OP_WN:
 
347
        return ptp_num (pa, 0);                         /* punch numeric */
 
348
case OP_WA:
 
349
        for (i = 0; i < MEMSIZE; i = i + 2) {           /* stop runaway */
 
350
            d = M[pa] & DIGIT;                          /* get digit */
 
351
            z = M[pa - 1] & DIGIT;                      /* get zone */
 
352
            if ((d & REC_MARK) == REC_MARK)             /* 8-2 char? */
 
353
                return ptp_write (PT_EL);               /* end record */
 
354
            ptc = alp_to_ptp[(z << 4) | d];             /* translate pair */
 
355
            if (ptc < 0) {                              /* bad char? */
 
356
                ind[IN_WRCHK] = 1;                      /* write check */
 
357
                CRETIOE (io_stop, STOP_INVCHR);  }
 
358
            r = ptp_write (ptc);                        /* write char */
 
359
            if (r != SCPE_OK) return r;                 /* error? */
 
360
            pa = ADDR_A (pa, 2);  }                     /* incr mem addr */
 
361
        break;          
 
362
default:                                                /* invalid function */
 
363
        return STOP_INVFNC;  }
 
364
return STOP_RWRAP;
 
365
}
 
366
 
 
367
/* Binary paper tape punch IO routine - see above for error handling */
 
368
 
 
369
t_stat btp (uint32 op, uint32 pa, uint32 f0, uint32 f1)
 
370
{
 
371
uint32 i;
 
372
uint8 ptc, z, d;
 
373
t_stat r;
 
374
 
 
375
if ((cpu_unit.flags & IF_BIN) == 0) return STOP_INVIO;
 
376
switch (op) {                                           /* decode op */
 
377
case OP_WA:
 
378
        for (i = 0; i < MEMSIZE; i = i + 2) {           /* stop runaway */
 
379
            d = M[pa] & DIGIT;                          /* get digit */
 
380
            z = M[pa - 1] & DIGIT;                      /* get zone */
 
381
            if ((d & REC_MARK) == REC_MARK)             /* 8-2 char? */
 
382
                return ptp_write (PT_EL);               /* end record */
 
383
            ptc = ((z & 06) << 5) | ((z & 01) << 3) | (d & 07);
 
384
            if (bad_par[ptc]) ptc = ptc | PT_C;         /* set parity */
 
385
            r = ptp_write (ptc);                        /* write char */
 
386
            if (r != SCPE_OK) return r;                 /* error? */
 
387
            pa = ADDR_A (pa, 2);  }                     /* incr mem addr */
 
388
        break;          
 
389
default:                                                /* invalid function */
 
390
        return STOP_INVFNC;  }
 
391
return STOP_RWRAP;
 
392
}
 
393
 
 
394
/* Punch tape numeric - cannot generate parity errors */
 
395
 
 
396
t_stat ptp_num (uint32 pa, uint32 len)
 
397
{
 
398
t_stat r;
 
399
uint8 d;
 
400
uint32 i, end;
 
401
 
 
402
end = pa + len;
 
403
for (i = 0; i < MEMSIZE; i++) {                         /* stop runaway */
 
404
        d = M[pa] & (FLAG | DIGIT);                     /* get char */
 
405
        if (len? (pa >= end):                           /* dump: end reached? */
 
406
           ((d & REC_MARK) == REC_MARK))                /* write: rec mark? */
 
407
            return ptp_write (PT_EL);                   /* end record */
 
408
        r = ptp_write (num_to_ptp[d]);                  /* write */
 
409
        if (r != SCPE_OK) return r;                     /* error? */
 
410
        PP (pa);  }                                     /* incr mem addr */
 
411
return STOP_RWRAP;
 
412
}
 
413
 
 
414
/* Write ptp frame - all errors are hard errors */
 
415
 
 
416
t_stat ptp_write (uint32 c)
 
417
{
 
418
if ((ptp_unit.flags & UNIT_ATT) == 0) {                 /* attached? */
 
419
        ind[IN_WRCHK] = 1;                              /* no, error */
 
420
        return SCPE_UNATT;  }
 
421
 
 
422
if (putc (c, ptp_unit.fileref) == EOF) {                /* write char */
 
423
        ind[IN_WRCHK] = 1;                              /* error? */
 
424
        perror ("PTP I/O error");
 
425
        clearerr (ptp_unit.fileref);
 
426
        return SCPE_IOERR;  }
 
427
ptp_unit.pos = ptp_unit.pos + 1;                        /* count char */
 
428
return SCPE_OK;
 
429
}
 
430
 
 
431
/* Reset routine */
 
432
 
 
433
t_stat ptp_reset (DEVICE *dptr)
 
434
{
 
435
return SCPE_OK;
 
436
}