/* ibm1130_ptrp.c: IBM 1130 paper tape reader/punch emulation Based on the SIMH simulator package written by Robert M Supnik Brian Knittel Revision History 2004.10.22 - Written. * (C) Copyright 2004, Brian Knittel. * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN * RISK basis, there is no warranty of fitness for any purpose, and the rest of the * usual yada-yada. Please keep this notice and the copyright in any distributions * or modifications. * * This is not a supported product, but I welcome bug reports and fixes. * Mail to simh@ibm1130.org */ #include "ibm1130_defs.h" /*************************************************************************************** * 1134 Paper Tape Reader device PTR * 1055 Paper Tape Punch device PTP (shares DSW with PTR) ***************************************************************************************/ #define PTR1134_DSW_READER_RESPONSE 0x4000 #define PTR1134_DSW_PUNCH_RESPONSE 0x1000 #define PTR1134_DSW_READER_BUSY 0x0800 #define PTR1134_DSW_READER_NOT_READY 0x0400 #define PTR1134_DSW_PUNCH_BUSY 0x0200 #define PTR1134_DSW_PUNCH_NOT_READY 0x0100 #define IS_ONLINE(u) (((u)->flags & (UNIT_ATT|UNIT_DIS)) == UNIT_ATT) static t_stat ptr_svc (UNIT *uptr); static t_stat ptr_reset (DEVICE *dptr); static t_stat ptr_attach (UNIT *uptr, CONST char *cptr); static t_stat ptr_detach (UNIT *uptr); static t_stat ptr_boot (int32 unitno, DEVICE *dptr); static t_stat ptp_svc (UNIT *uptr); static t_stat ptp_reset (DEVICE *dptr); static t_stat ptp_attach (UNIT *uptr, CONST char *cptr); static t_stat ptp_detach (UNIT *uptr); static int16 ptr_dsw = 0; /* device status word */ static int32 ptr_wait = 1000; /* character read wait */ static uint8 ptr_char = 0; /* last character read */ static int32 ptp_wait = 1000; /* character punch wait */ UNIT ptr_unit[1] = { { UDATA (&ptr_svc, UNIT_ATTABLE, 0) }, }; REG ptr_reg[] = { { HRDATA (DSW, ptr_dsw, 16) }, /* device status word */ { DRDATA (WTIME, ptr_wait, 24), PV_LEFT }, /* character read wait */ { DRDATA (LASTCHAR, ptr_char, 8), PV_LEFT }, /* last character read */ { NULL } }; DEVICE ptr_dev = { "PTR", ptr_unit, ptr_reg, NULL, 1, 16, 16, 1, 16, 16, NULL, NULL, ptr_reset, ptr_boot, ptr_attach, ptr_detach}; UNIT ptp_unit[1] = { { UDATA (&ptp_svc, UNIT_ATTABLE, 0) }, }; REG ptp_reg[] = { { HRDATA (DSW, ptr_dsw, 16) }, /* device status word (this is the same as the reader's!) */ { DRDATA (WTIME, ptp_wait, 24), PV_LEFT }, /* character punch wait */ { NULL } }; DEVICE ptp_dev = { "PTP", ptp_unit, ptp_reg, NULL, 1, 16, 16, 1, 16, 16, NULL, NULL, ptp_reset, NULL, ptp_attach, ptp_detach}; /* xio_1134_papertape - XIO command interpreter for the 1134 paper tape reader and 1055 paper tape punch */ void xio_1134_papertape (int32 iocc_addr, int32 iocc_func, int32 iocc_mod) { char msg[80]; switch (iocc_func) { case XIO_READ: /* read: return last character read */ M[iocc_addr & mem_mask] = (uint16) (ptr_char << 8); break; case XIO_WRITE: /* write: initiate punch operation */ if ((ptr_dsw & PTR1134_DSW_PUNCH_NOT_READY) == 0 && IS_ONLINE(ptp_unit)) { putc((M[iocc_addr & mem_mask] >> 8) & 0xFF, ptp_unit->fileref); ptp_unit->pos++; } sim_activate(ptp_unit, ptp_wait); /* schedule interrupt */ SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY | PTR1134_DSW_PUNCH_BUSY); break; case XIO_SENSE_DEV: /* sense device status */ ACC = ptr_dsw; if (iocc_mod & 0x01) { /* reset interrupts */ CLRBIT(ptr_dsw, PTR1134_DSW_READER_RESPONSE | PTR1134_DSW_PUNCH_RESPONSE); CLRBIT(ILSW[4], ILSW_4_1134_TAPE); } break; case XIO_CONTROL: /* control: initiate character read */ sim_activate(ptr_unit, ptr_wait); /* schedule interrupt */ SETBIT(ptr_dsw, PTR1134_DSW_READER_BUSY | PTR1134_DSW_READER_NOT_READY); break; default: sprintf(msg, "Invalid 1134 reader/1055 punch XIO function %x", iocc_func); xio_error(msg); } } /* ptr_svc - emulated timeout - 1134 read operation complete */ static t_stat ptr_svc (UNIT *uptr) { CLRBIT(ptr_dsw, PTR1134_DSW_READER_BUSY); /* clear reader busy flag */ SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* assume at end of file */ if (IS_ONLINE(uptr)) { /* fetch character from file */ ptr_char = getc(uptr->fileref); if (! feof(uptr->fileref)) { /* there's more left */ CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); uptr->pos++; } } SETBIT(ptr_dsw, PTR1134_DSW_READER_RESPONSE); /* indicate read complete */ SETBIT(ILSW[4], ILSW_4_1134_TAPE); /* initiate interrupt */ calc_ints(); return SCPE_OK; } /* ptp_svc - emulated timeout -- 1055 punch operation complete */ static t_stat ptp_svc (UNIT *uptr) { CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_BUSY); /* clear punch busy flag */ if (IS_ONLINE(uptr)) /* update punch ready status */ CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); else SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_RESPONSE); /* indicate punch complete */ SETBIT(ILSW[4], ILSW_4_1134_TAPE); /* initiate interrupt */ calc_ints(); return SCPE_OK; } /* ptr_reset - reset emulated paper tape reader */ static t_stat ptr_reset (DEVICE *dptr) { sim_cancel(ptr_unit); CLRBIT(ptr_dsw, PTR1134_DSW_READER_BUSY | PTR1134_DSW_READER_RESPONSE); SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); if (IS_ONLINE(ptr_unit) && ! feof(ptr_unit->fileref)) CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); if ((ptr_dsw & PTR1134_DSW_PUNCH_RESPONSE) == 0) { /* punch isn't interrupting either */ CLRBIT(ILSW[4], ILSW_4_1134_TAPE); calc_ints(); } return SCPE_OK; } /* ptp_reset - reset emulated paper tape punch */ static t_stat ptp_reset (DEVICE *dptr) { sim_cancel(ptp_unit); CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_BUSY | PTR1134_DSW_PUNCH_RESPONSE); SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); if (IS_ONLINE(ptp_unit)) CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); if ((ptr_dsw & PTR1134_DSW_READER_RESPONSE) == 0) { /* reader isn't interrupting either */ CLRBIT(ILSW[4], ILSW_4_1134_TAPE); calc_ints(); } return SCPE_OK; } /* ptr_attach - attach file to simulated paper tape reader */ static t_stat ptr_attach (UNIT *uptr, CONST char *cptr) { t_stat rval; SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* assume failure */ if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) /* use standard attach */ return rval; if ((ptr_dsw & PTR1134_DSW_READER_BUSY) == 0 && ! feof(uptr->fileref)) CLRBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); /* we're in business */ return SCPE_OK; } /* ptr_attach - detach file from simulated paper tape reader */ static t_stat ptr_detach (UNIT *uptr) { SETBIT(ptr_dsw, PTR1134_DSW_READER_NOT_READY); return detach_unit(uptr); } /* ptr_attach - perform paper tape initial program load */ static t_stat ptr_boot (int32 unitno, DEVICE *dptr) { int ch, nch, val, addr; t_bool leader = TRUE, start = FALSE; t_stat rval; addr = 0; nch = 0; val = 0; for (;;) { if ((ch = getc(ptr_unit->fileref)) == EOF) { printf("EOF on paper tape without finding Channel 5 end-of-load mark\n"); break; } if (leader) { if ((ch & 0x7F) == 0x7F) /* ignore leading rubouts or "delete" characters */ continue; leader = FALSE; /* after first nonrubout, any punch in channel 5 terminates load */ } /* this is untested -- not sure of actual byte ordering */ val = (val << 4) | (ch & 0x0F); /* get next nybble */ if (++nch == 4) { /* if we now have four nybbles, store the word */ M[addr & mem_mask] = (uint16) val; addr++; /* prepare for next word */ nch = 0; val = 0; } if (ch & 0x10) { /* channel 5 punch terminates load */ start = TRUE; break; } } if (! start) /* if we didn't get a valid load, report EOF error */ return SCPE_EOF; if ((rval = reset_all(0)) != SCPE_OK) /* force a reset */ return rval; IAR = 0; /* start running at address 0 */ return SCPE_OK; } /* ptp_attach - attach file to simulated paper tape punch */ static t_stat ptp_attach (UNIT *uptr, CONST char *cptr) { t_stat rval; SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); /* assume failure */ if ((rval = attach_unit(uptr, cptr)) != SCPE_OK) /* use standard attach */ return rval; fseek(uptr->fileref, 0, SEEK_END); /* if we opened an existing file, append to it */ uptr->pos = ftell(uptr->fileref); if ((ptr_dsw & PTR1134_DSW_PUNCH_BUSY) == 0) CLRBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); /* we're in business */ return SCPE_OK; } /* ptp_detach - detach file from simulated paper tape punch */ static t_stat ptp_detach (UNIT *uptr) { SETBIT(ptr_dsw, PTR1134_DSW_PUNCH_NOT_READY); return detach_unit(uptr); }