711 lines
22 KiB
C
711 lines
22 KiB
C
/* i7090_lpr.c: IBM 7090 Standard line printer.
|
||
|
||
Copyright (c) 2005-2016, Richard Cornwell
|
||
|
||
Permission is hereby granted, free of charge, to any person obtaining a
|
||
copy of this software and associated documentation files (the "Software"),
|
||
to deal in the Software without restriction, including without limitation
|
||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
and/or sell copies of the Software, and to permit persons to whom the
|
||
Software is furnished to do so, subject to the following conditions:
|
||
|
||
The above copyright notice and this permission notice shall be included in
|
||
all copies or substantial portions of the Software.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||
RICHARD CORNWELL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
This is the standard line printer that all 70xx systems have.
|
||
|
||
For WRS read next 24 words and fill print buffer.
|
||
Row 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 11, 12
|
||
For RDS read rows 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
||
Echo 8|4
|
||
read row 10
|
||
Echo 8|3
|
||
read row 11
|
||
Echo 9
|
||
read row 12
|
||
Echo 8, 7, 6, 5, 4, 3, 2, 1
|
||
|
||
*/
|
||
|
||
#include "i7090_defs.h"
|
||
#include "sim_console.h"
|
||
#include "sim_card.h"
|
||
|
||
#ifdef NUM_DEVS_LPR
|
||
|
||
#define UNIT_LPR UNIT_ATTABLE | UNIT_DISABLE
|
||
#define ECHO (1 << UNIT_V_LOCAL)
|
||
|
||
|
||
/* std devices. data structures
|
||
|
||
chan_dev Channel device descriptor
|
||
chan_unit Channel unit descriptor
|
||
chan_reg Channel register list
|
||
chan_mod Channel modifiers list
|
||
*/
|
||
|
||
/* Output selection is stored in u3 */
|
||
/* Line count is stored in u4 */
|
||
/* Device status information stored in u5 */
|
||
/* Position is stored in u6 */
|
||
#define LPRSTA_RCMD 002000 /* Read command */
|
||
#define LPRSTA_WCMD 004000 /* Write command */
|
||
|
||
#define LPRSTA_EOR 010000 /* Hit end of record */
|
||
#define LPRSTA_BINMODE 020000 /* Line printer started in bin mode */
|
||
#define LPRSTA_CHANGE 040000 /* Turn DEV_WRITE on */
|
||
#define LPRSTA_COL72 0100000 /* Mask to last column printed */
|
||
#define LPRSTA_IMAGE 0200000 /* Image to print */
|
||
|
||
|
||
struct _lpr_data
|
||
{
|
||
t_uint64 wbuff[24]; /* Line buffer */
|
||
char lbuff[74]; /* Output line buffer */
|
||
}
|
||
lpr_data[NUM_DEVS_LPR];
|
||
|
||
uint32 lpr_cmd(UNIT *, uint16, uint16);
|
||
t_stat lpr_srv(UNIT *);
|
||
void lpr_ini(UNIT *, t_bool);
|
||
t_stat lpr_reset(DEVICE *);
|
||
t_stat lpr_attach(UNIT *, CONST char *);
|
||
t_stat lpr_detach(UNIT *);
|
||
t_stat lpr_setlpp(UNIT *, int32, CONST char *, void *);
|
||
t_stat lpr_getlpp(FILE *, UNIT *, int32, CONST void *);
|
||
t_stat lpr_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
|
||
const char *cptr);
|
||
const char *lpr_description (DEVICE *dptr);
|
||
|
||
extern char six_to_ascii[64];
|
||
|
||
UNIT lpr_unit[] = {
|
||
#if NUM_DEVS_LPR > 1
|
||
{UDATA(&lpr_srv, UNIT_S_CHAN(CHAN_A) | UNIT_LPR | ECHO, 55)}, /* A */
|
||
#endif
|
||
#if NUM_DEVS_LPR > 2
|
||
{UDATA(&lpr_srv, UNIT_S_CHAN(CHAN_C) | UNIT_LPR, 55)}, /* B */
|
||
#endif
|
||
#if NUM_DEVS_LPR > 3
|
||
{UDATA(&lpr_srv, UNIT_S_CHAN(CHAN_E) | UNIT_LPR | UNIT_DIS, 55)}, /* C */
|
||
#endif
|
||
{UDATA(&lpr_srv, UNIT_S_CHAN(CHAN_CHPIO) | UNIT_LPR, 55)}, /* 704 */
|
||
};
|
||
|
||
MTAB lpr_mod[] = {
|
||
{ECHO, 0, NULL, "NOECHO", NULL, NULL, NULL, "Done echo to console"},
|
||
{ECHO, ECHO, "ECHO", "ECHO", NULL, NULL, NULL, "Echo output to console"},
|
||
{MTAB_XTD|MTAB_VUN|MTAB_VALR, 0, "LINESPERPAGE", "LINESPERPAGE",
|
||
&lpr_setlpp, &lpr_getlpp, NULL, "Number of lines per page"},
|
||
#if NUM_CHAN != 1
|
||
{MTAB_XTD | MTAB_VUN | MTAB_VALR, 0, "CHAN", "CHAN", &set_chan,
|
||
&get_chan, NULL},
|
||
#endif
|
||
{0}
|
||
};
|
||
|
||
DEVICE lpr_dev = {
|
||
"LP", lpr_unit, NULL, lpr_mod,
|
||
NUM_DEVS_LPR, 8, 15, 1, 8, 36,
|
||
NULL, NULL, &lpr_reset, NULL, &lpr_attach, &lpr_detach,
|
||
&lpr_dib, DEV_DISABLE | DEV_DEBUG, 0, dev_debug,
|
||
NULL, NULL, &lpr_help, NULL, NULL, &lpr_description
|
||
};
|
||
|
||
/* Line printer routines
|
||
*/
|
||
|
||
/*
|
||
* Line printer routines
|
||
*/
|
||
|
||
t_stat
|
||
lpr_setlpp(UNIT *uptr, int32 val, CONST char *cptr, void *desc)
|
||
{
|
||
int i;
|
||
if (cptr == NULL)
|
||
return SCPE_ARG;
|
||
if (uptr == NULL)
|
||
return SCPE_IERR;
|
||
i = 0;
|
||
while(*cptr != '\0') {
|
||
if (*cptr < '0' || *cptr > '9')
|
||
return SCPE_ARG;
|
||
i = (i * 10) + (*cptr++) - '0';
|
||
}
|
||
if (i < 20 || i > 100)
|
||
return SCPE_ARG;
|
||
uptr->capac = i;
|
||
uptr->u4 = 0;
|
||
return SCPE_OK;
|
||
}
|
||
|
||
t_stat
|
||
lpr_getlpp(FILE *st, UNIT *uptr, int32 v, CONST void *desc)
|
||
{
|
||
if (uptr == NULL)
|
||
return SCPE_IERR;
|
||
fprintf(st, "linesperpage=%d", uptr->capac);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
t_stat
|
||
print_line(UNIT * uptr, int chan, int unit)
|
||
{
|
||
/* Convert word record into column image */
|
||
/* Check output type, if auto or text, try and convert record to bcd first */
|
||
/* If failed and text report error and dump what we have */
|
||
/* Else if binary or not convertable, dump as image */
|
||
|
||
uint16 buff[80]; /* Temp conversion buffer */
|
||
int i, j;
|
||
int outsel = uptr->u3;
|
||
int prt_flg = 1;
|
||
|
||
if ((uptr->flags & (UNIT_ATT | ECHO)) == 0)
|
||
return SCPE_UNATT; /* attached? */
|
||
|
||
if (outsel & PRINT_3) {
|
||
if (uptr->flags & UNIT_ATT) {
|
||
sim_fwrite("\r\n", 1, 2, uptr->fileref);
|
||
uptr->pos += 2;
|
||
}
|
||
if (uptr->flags & ECHO) {
|
||
sim_putchar('\r');
|
||
sim_putchar('\n');
|
||
}
|
||
uptr->u5 &= ~LPRSTA_COL72;
|
||
uptr->u4++;
|
||
}
|
||
|
||
if (outsel & PRINT_4) {
|
||
if (uptr->flags & UNIT_ATT) {
|
||
sim_fwrite("\r\n\r\n", 1, 4, uptr->fileref);
|
||
uptr->pos += 4;
|
||
}
|
||
if (uptr->flags & ECHO) {
|
||
sim_putchar('\r');
|
||
sim_putchar('\n');
|
||
sim_putchar('\r');
|
||
sim_putchar('\n');
|
||
}
|
||
uptr->u5 &= ~LPRSTA_COL72;
|
||
uptr->u4++;
|
||
uptr->u4++;
|
||
}
|
||
|
||
|
||
/* Try to convert to text */
|
||
memset(buff, 0, sizeof(buff));
|
||
/* Bit flip into temp buffer */
|
||
for (i = 0; i < 24; i++) {
|
||
int bit = 1 << (i / 2);
|
||
t_uint64 mask = 1;
|
||
t_uint64 wd = 0;
|
||
int b = 36 * (i & 1);
|
||
int col;
|
||
|
||
wd = lpr_data[unit].wbuff[i];
|
||
for (col = 35; col >= 0; mask <<= 1, col--) {
|
||
if (wd & mask)
|
||
buff[col + b] |= bit;
|
||
}
|
||
lpr_data[unit].wbuff[i] = 0;
|
||
}
|
||
|
||
/* Space out printer based on last output */
|
||
if ((outsel & PRINT_9)) {
|
||
/* Trim trailing spaces */
|
||
for (j = 72; j > 0 && lpr_data[unit].lbuff[j] == ' '; j--) ;
|
||
j++;
|
||
if ((uptr->u5 & LPRSTA_COL72) == 0)
|
||
j = 0;
|
||
|
||
for (i = j; i < 72; i++) {
|
||
if (uptr->flags & UNIT_ATT) {
|
||
sim_fwrite(" ", 1, 1, uptr->fileref);
|
||
uptr->pos += 1;
|
||
}
|
||
if (uptr->flags & ECHO)
|
||
sim_putchar(' ');
|
||
}
|
||
} else {
|
||
if (uptr->flags & UNIT_ATT) {
|
||
sim_fwrite("\n\r", 1, 2, uptr->fileref);
|
||
uptr->pos += 2;
|
||
}
|
||
if (uptr->flags & ECHO) {
|
||
sim_putchar('\n');
|
||
sim_putchar('\r');
|
||
}
|
||
uptr->u4++;
|
||
uptr->u5 &= ~LPRSTA_COL72;
|
||
}
|
||
|
||
/* Scan each column */
|
||
for (i = 0; i < 72; i++) {
|
||
int bcd = sim_hol_to_bcd(buff[i]);
|
||
|
||
if (bcd == 0x7f)
|
||
lpr_data[unit].lbuff[i] = '{';
|
||
else {
|
||
if (bcd == 020)
|
||
bcd = 10;
|
||
if (uptr->u5 & LPRSTA_BINMODE) {
|
||
char ch = (buff[i] != 0) ? '1' : ' ';
|
||
lpr_data[unit].lbuff[i] = ch;
|
||
} else
|
||
lpr_data[unit].lbuff[i] = sim_six_to_ascii[bcd];
|
||
}
|
||
}
|
||
sim_debug(DEBUG_DETAIL, &lpr_dev, "WRS unit=%d %3o [%72s]\n", unit,
|
||
outsel >> 3, &lpr_data[unit].lbuff[0]);
|
||
|
||
/* Trim trailing spaces */
|
||
for (j = 71; j > 0 && lpr_data[unit].lbuff[j] == ' '; j--) ;
|
||
|
||
/* Print out buffer */
|
||
if (uptr->flags & UNIT_ATT) {
|
||
sim_fwrite(lpr_data[unit].lbuff, 1, j+1, uptr->fileref);
|
||
uptr->pos += j+1;
|
||
}
|
||
if (uptr->flags & ECHO) {
|
||
for(i = 0; i <= j; i++)
|
||
sim_putchar(lpr_data[unit].lbuff[i]);
|
||
}
|
||
uptr->u5 |= LPRSTA_COL72;
|
||
|
||
/* Put output to column where we left off */
|
||
if (outsel != 0) {
|
||
uptr->u5 &= ~LPRSTA_COL72;
|
||
}
|
||
|
||
/* Space printer */
|
||
if (outsel & PRINT_2) {
|
||
if (uptr->flags & UNIT_ATT) {
|
||
sim_fwrite("\r\n", 1, 2, uptr->fileref);
|
||
uptr->pos += 2;
|
||
}
|
||
if (uptr->flags & ECHO) {
|
||
sim_putchar('\r');
|
||
sim_putchar('\n');
|
||
}
|
||
uptr->u4++;
|
||
}
|
||
|
||
if (outsel & PRINT_1) {
|
||
while (uptr->u4 < (int32)uptr->capac) {
|
||
if (uptr->flags & UNIT_ATT) {
|
||
sim_fwrite("\r\n", 1, 2, uptr->fileref);
|
||
uptr->pos += 2;
|
||
}
|
||
if (uptr->flags & ECHO) {
|
||
sim_putchar('\r');
|
||
sim_putchar('\n');
|
||
}
|
||
uptr->u4++;
|
||
}
|
||
}
|
||
|
||
if (uptr->u4 >= (int32)uptr->capac) {
|
||
uptr->u4 -= (int32)uptr->capac;
|
||
dev_pulse[chan] |= PRINT_I;
|
||
}
|
||
|
||
return SCPE_OK;
|
||
}
|
||
|
||
uint32 lpr_cmd(UNIT * uptr, uint16 cmd, uint16 dev)
|
||
{
|
||
int chan = UNIT_G_CHAN(uptr->flags);
|
||
int u = (uptr - lpr_unit);
|
||
int i;
|
||
|
||
/* Check if valid */
|
||
if ((dev & 03) == 0 || (dev & 03) == 3)
|
||
return SCPE_NODEV;
|
||
/* Check if attached */
|
||
if ((uptr->flags & (UNIT_ATT | ECHO)) == 0) {
|
||
chan_set_error(chan);
|
||
sim_debug(DEBUG_EXP, &lpr_dev, "unit=%d not ready\n", u);
|
||
return SCPE_IOERR;
|
||
}
|
||
/* Check if still active */
|
||
if (uptr->u5 & URCSTA_CMD) {
|
||
sim_debug(DEBUG_EXP, &lpr_dev, "unit=%d busy\n", u);
|
||
return SCPE_BUSY;
|
||
}
|
||
/* Ok, issue command if correct */
|
||
if (cmd == IO_WRS || cmd == IO_RDS) {
|
||
/* Start device */
|
||
if (((uptr->u5 & (URCSTA_ON | URCSTA_IDLE)) ==
|
||
(URCSTA_ON | URCSTA_IDLE)) && uptr->wait <= 30) {
|
||
uptr->wait += 85; /* Wait for next latch point */
|
||
} else
|
||
uptr->wait = 330; /* Startup delay */
|
||
for (i = 0; i < 24; lpr_data[u].wbuff[i++] = 0) ;
|
||
uptr->u6 = 0;
|
||
uptr->u5 &= ~(LPRSTA_WCMD | LPRSTA_RCMD | URCSTA_WRITE | URCSTA_READ);
|
||
uptr->u3 = 0;
|
||
dev_pulse[chan] = 0;
|
||
if (cmd == IO_WRS) {
|
||
sim_debug(DEBUG_CMD, &lpr_dev, "WRS %o unit=%d %d\n", dev, u, uptr->wait);
|
||
uptr->u5 |= LPRSTA_WCMD | URCSTA_CMD | URCSTA_WRITE;
|
||
} else {
|
||
sim_debug(DEBUG_CMD, &lpr_dev, "RDS %o unit=%d %d\n", dev, u, uptr->wait);
|
||
uptr->u5 |= LPRSTA_RCMD | URCSTA_CMD | URCSTA_READ;
|
||
}
|
||
if ((dev & 03) == 2)
|
||
uptr->u5 |= LPRSTA_BINMODE;
|
||
else
|
||
uptr->u5 &= ~LPRSTA_BINMODE;
|
||
chan_set_sel(chan, 1);
|
||
chan_clear_status(chan);
|
||
sim_activate(uptr, us_to_ticks(1000)); /* activate */
|
||
return SCPE_OK;
|
||
} else {
|
||
chan_set_attn(chan);
|
||
}
|
||
return SCPE_IOERR;
|
||
}
|
||
|
||
t_stat lpr_srv(UNIT * uptr)
|
||
{
|
||
int chan = UNIT_G_CHAN(uptr->flags);
|
||
int u = (uptr - lpr_unit);
|
||
int pos;
|
||
int r;
|
||
int eor = 0;
|
||
|
||
/* Channel has disconnected, abort current line. */
|
||
if (uptr->u5 & URCSTA_CMD && chan_stat(chan, DEV_DISCO)) {
|
||
print_line(uptr, chan, u);
|
||
uptr->u5 &= ~(URCSTA_WRITE | URCSTA_READ | URCSTA_CMD | LPRSTA_EOR | LPRSTA_CHANGE);
|
||
uptr->u6 = 0;
|
||
chan_clear(chan, DEV_WEOR | DEV_SEL);
|
||
sim_debug(DEBUG_CHAN, &lpr_dev, "unit=%d disconnect\n", u);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* If change requested, do that first */
|
||
if (uptr->u5 & LPRSTA_CHANGE) {
|
||
/* Wait until word read by CPU or timeout */
|
||
if (chan_test(chan, DEV_FULL)) {
|
||
uptr->wait -= 50;
|
||
if (uptr->wait == 50)
|
||
uptr->u5 &= ~LPRSTA_CHANGE;
|
||
sim_activate(uptr, us_to_ticks(100));
|
||
return SCPE_OK;
|
||
} else {
|
||
chan_set(chan, DEV_WRITE);
|
||
sim_activate(uptr, uptr->wait);
|
||
uptr->u5 &= ~LPRSTA_CHANGE;
|
||
uptr->wait = 0;
|
||
return SCPE_OK;
|
||
}
|
||
}
|
||
|
||
/* Check to see if we have timed out */
|
||
if (uptr->wait != 0) {
|
||
uptr->wait--;
|
||
/* If at end of record and channel is still active, do another print */
|
||
if (((uptr->u5 & (URCSTA_IDLE|URCSTA_CMD|URCSTA_WRITE|URCSTA_READ|
|
||
URCSTA_ON)) == (URCSTA_IDLE|URCSTA_CMD|URCSTA_ON))
|
||
&& uptr->wait == 1 && chan_test(chan, STA_ACTIVE)) {
|
||
/* Restart same command */
|
||
uptr->u5 |= (URCSTA_WRITE | URCSTA_READ) & (uptr->u5 >> 5);
|
||
uptr->u6 = 0;
|
||
chan_set(chan, DEV_WRITE);
|
||
sim_debug(DEBUG_CHAN, &lpr_dev, "unit=%d restarting\n", u);
|
||
}
|
||
sim_activate(uptr, us_to_ticks(1000)); /* activate */
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* If no request, go to idle mode */
|
||
if ((uptr->u5 & (URCSTA_READ | URCSTA_WRITE)) == 0) {
|
||
if ((uptr->u5 & (URCSTA_IDLE | URCSTA_ON)) == (URCSTA_IDLE | URCSTA_ON)) {
|
||
uptr->wait = 85; /* Delay 85ms */
|
||
uptr->u5 &= ~URCSTA_IDLE; /* Not running */
|
||
sim_activate(uptr, us_to_ticks(1000));
|
||
} else {
|
||
uptr->wait = 330; /* Delay 330ms */
|
||
uptr->u5 &= ~URCSTA_ON; /* Turn motor off */
|
||
}
|
||
return SCPE_OK;
|
||
}
|
||
|
||
/* Motor is on and up to speed */
|
||
uptr->u5 |= URCSTA_ON;
|
||
uptr->u5 &= ~URCSTA_IDLE;
|
||
pos = uptr->u6;
|
||
|
||
uptr->u3 |= dev_pulse[chan] & PRINT_M;
|
||
|
||
/* Check if he write out last data */
|
||
if (uptr->u5 & URCSTA_READ) {
|
||
int wrow = 0;
|
||
t_uint64 wd = 0;
|
||
int action = 0;
|
||
|
||
/* Case 0: Read word from MF memory, DEV_WRITE=1 */
|
||
/* Case 1: Read word from MF memory, write echo back */
|
||
/* Case 2: Write echoback, after gone switch to read */
|
||
/* Case 3: Write echoback */
|
||
/* Case 4: No update, DEV_WRITE=1 */
|
||
eor = (uptr->u5 & LPRSTA_BINMODE) ? 1 : 0;
|
||
switch (pos) {
|
||
case 46:
|
||
print_line(uptr, chan, u);
|
||
pos = 0;
|
||
/* Fall through */
|
||
case 0:
|
||
case 1: /* Row 9 */
|
||
case 2:
|
||
case 3: /* Row 8 */
|
||
case 4:
|
||
case 5: /* Row 7 */
|
||
case 6:
|
||
case 7: /* Row 6 */
|
||
case 8:
|
||
case 9: /* Row 5 */
|
||
case 10:
|
||
case 11: /* Row 4 */
|
||
case 12:
|
||
case 13: /* Row 3 */
|
||
case 14:
|
||
case 15: /* Row 2 */
|
||
case 16: /* Row 1R */
|
||
wrow = pos;
|
||
break;
|
||
case 17: /* Row 1L and start Echo */
|
||
wrow = pos;
|
||
action = 1;
|
||
break;
|
||
case 18: /* Echo 8-4 R */
|
||
wd = lpr_data[u].wbuff[2];
|
||
wd &= lpr_data[u].wbuff[10];
|
||
action = 2;
|
||
wrow = pos;
|
||
break;
|
||
case 19: /* Echo 8-4 L */
|
||
wd = lpr_data[u].wbuff[3];
|
||
wd &= lpr_data[u].wbuff[11];
|
||
action = 3;
|
||
wrow = pos;
|
||
break;
|
||
case 20: /* Row 10 R */
|
||
wrow = 18;
|
||
break;
|
||
case 21: /* Row 10 L */
|
||
wrow = 19;
|
||
action = 1;
|
||
break;
|
||
case 22: /* Echo 8-3 */
|
||
/* Fill for echo back */
|
||
wd = lpr_data[u].wbuff[12];
|
||
wd &= lpr_data[u].wbuff[2];
|
||
action = 2;
|
||
wrow = pos;
|
||
break;
|
||
case 23:
|
||
wd = lpr_data[u].wbuff[13];
|
||
wd &= lpr_data[u].wbuff[3];
|
||
action = 3;
|
||
wrow = pos;
|
||
break;
|
||
case 24: /* Row 11 R */
|
||
wrow = 20;
|
||
break;
|
||
case 25: /* Row 11 L */
|
||
wrow = 21;
|
||
action = 1;
|
||
break;
|
||
case 26: /* Echo 9 */
|
||
wd = lpr_data[u].wbuff[0];
|
||
action = 2;
|
||
wrow = pos;
|
||
break;
|
||
case 27:
|
||
wd = lpr_data[u].wbuff[1];
|
||
action = 3;
|
||
wrow = pos;
|
||
break;
|
||
case 28:
|
||
wrow = 22;
|
||
break;
|
||
case 29: /* Row 12 */
|
||
wrow = 23;
|
||
action = 1;
|
||
break;
|
||
case 45: /* Echo 1 */
|
||
eor = 1;
|
||
/* Fall through */
|
||
|
||
case 30:
|
||
case 31: /* Echo 8 */
|
||
case 32:
|
||
case 33: /* Echo 7 */
|
||
case 34:
|
||
case 35: /* Echo 6 */
|
||
case 36:
|
||
case 37: /* Echo 5 */
|
||
case 38:
|
||
case 39: /* Echo 4 */
|
||
case 40:
|
||
case 41: /* Echo 3 */
|
||
case 42:
|
||
case 43: /* Echo 2 */
|
||
case 44: /* Echo 1 */
|
||
wrow = pos - 28;
|
||
wd = lpr_data[u].wbuff[wrow];
|
||
action = 2;
|
||
break;
|
||
}
|
||
|
||
if (action == 0 || action == 1) {
|
||
/* If reading grab next word */
|
||
r = chan_read(chan, &lpr_data[u].wbuff[wrow], 0);
|
||
sim_debug(DEBUG_DATA, &lpr_dev, "print read row < %d %d %012llo eor=%d\n",
|
||
pos, wrow, lpr_data[u].wbuff[wrow], 0);
|
||
if (action == 1)
|
||
chan_clear(chan, DEV_WRITE);
|
||
} else { /* action == 2 || action == 3 */
|
||
/* Place echo data in buffer */
|
||
sim_debug(DEBUG_DATA, &lpr_dev, "print read row > %d %d %012llo eor=%d\n",
|
||
pos, wrow, wd, eor);
|
||
r = chan_write(chan, &wd, 0);
|
||
/* Change back to reading */
|
||
if (action == 3) {
|
||
uptr->wait = 650;
|
||
uptr->u6 = ++pos;
|
||
uptr->u5 &= ~(LPRSTA_EOR);
|
||
uptr->u5 |= LPRSTA_CHANGE;
|
||
sim_activate(uptr, us_to_ticks(100));
|
||
return SCPE_OK;
|
||
}
|
||
}
|
||
} else {
|
||
eor = (pos == 23 || (uptr->u5 & LPRSTA_BINMODE && pos == 1)) ? 1 : 0;
|
||
if (pos == 24 || (uptr->u5 & LPRSTA_BINMODE && pos == 2)) {
|
||
print_line(uptr, chan, u);
|
||
pos = 0;
|
||
}
|
||
r = chan_read(chan, &lpr_data[u].wbuff[pos], 0);
|
||
sim_debug(DEBUG_DATA, &lpr_dev, "print row %d %012llo %d\n", pos,
|
||
lpr_data[u].wbuff[pos], eor);
|
||
}
|
||
|
||
uptr->u6 = pos + 1;
|
||
switch (r) {
|
||
case END_RECORD:
|
||
uptr->wait = 100; /* Print wheel gap */
|
||
uptr->u5 |= LPRSTA_EOR | URCSTA_IDLE;
|
||
uptr->u5 &= ~(URCSTA_WRITE | URCSTA_READ);
|
||
chan_set(chan, DEV_REOR);
|
||
break;
|
||
case DATA_OK:
|
||
if (eor) {
|
||
uptr->wait = 100; /* Print wheel gap */
|
||
uptr->u5 |= LPRSTA_EOR | URCSTA_IDLE;
|
||
uptr->u5 &= ~(URCSTA_WRITE | URCSTA_READ);
|
||
chan_set(chan, DEV_REOR);
|
||
} else {
|
||
uptr->wait = 0;
|
||
uptr->u5 &= ~(LPRSTA_EOR);
|
||
sim_activate(uptr, (pos & 1) ? us_to_ticks(500) : us_to_ticks(16000));
|
||
return SCPE_OK;
|
||
}
|
||
break;
|
||
case TIME_ERROR:
|
||
chan_set_attn(chan);
|
||
chan_set(chan, DEV_REOR);
|
||
uptr->wait = 13 * (12 - (pos / 2)) + 85;
|
||
uptr->u5 &= ~(URCSTA_READ | URCSTA_WRITE);
|
||
uptr->u5 |= URCSTA_IDLE;
|
||
break;
|
||
}
|
||
|
||
sim_activate(uptr, us_to_ticks(1000));
|
||
return SCPE_OK;
|
||
}
|
||
|
||
void
|
||
lpr_ini(UNIT * uptr, t_bool f)
|
||
{
|
||
int u = (uptr - lpr_unit);
|
||
|
||
uptr->u3 = 0;
|
||
uptr->u4 = 0;
|
||
uptr->u5 = 0;
|
||
memset(&lpr_data[u].lbuff, ' ', sizeof(lpr_data[u].lbuff));
|
||
}
|
||
|
||
t_stat
|
||
lpr_reset(DEVICE * dptr)
|
||
{
|
||
return SCPE_OK;
|
||
}
|
||
|
||
t_stat
|
||
lpr_attach(UNIT * uptr, CONST char *file)
|
||
{
|
||
t_stat r;
|
||
|
||
sim_switches |= SWMASK ('A'); /* Position to EOF */
|
||
if ((r = attach_unit(uptr, file)) != SCPE_OK)
|
||
return r;
|
||
uptr->u5 = 0;
|
||
return SCPE_OK;
|
||
}
|
||
|
||
t_stat
|
||
lpr_detach(UNIT * uptr)
|
||
{
|
||
int u = (uptr - lpr_unit);
|
||
|
||
return detach_unit(uptr);
|
||
}
|
||
|
||
t_stat
|
||
lpr_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr)
|
||
{
|
||
const char *cpu = cpu_description(&cpu_dev);
|
||
extern void fprint_attach_help_ex (FILE *st, DEVICE *dptr, t_bool silent);
|
||
|
||
fprintf (st, "%s\n\n", lpr_description(dptr));
|
||
#if NUM_DEVS_LPR > 3
|
||
fprintf (st, "The %s supports up to four line printers", cpu);
|
||
#elif NUM_DEVS_LPR > 2
|
||
fprintf (st, "The %s supports up to three line printers", cpu);
|
||
#elif NUM_DEVS_LPR > 1
|
||
fprintf (st, "The %s supports up to two line printers", cpu);
|
||
#elif NUM_DEVS_LPR > 0
|
||
fprintf (st, "The %s supports one line printer", cpu);
|
||
#endif
|
||
fprintf (st, "by default. The Line printer can\n");
|
||
fprintf (st, "The printer acted as the console printer:\n\n");
|
||
fprintf (st, " sim> SET %s ECHO\n\n", dptr->name);
|
||
fprintf (st, "Causes all output sent to printer to also go to console.\n");
|
||
help_set_chan_type(st, dptr, "Line printers");
|
||
fprint_set_help(st, dptr);
|
||
fprint_show_help(st, dptr);
|
||
return SCPE_OK;
|
||
}
|
||
|
||
const char *
|
||
lpr_description(DEVICE *dptr)
|
||
{
|
||
return "716 Line Printer";
|
||
}
|
||
|
||
|
||
#endif
|