1
0
mirror of https://github.com/rcornwell/sims.git synced 2026-01-22 18:41:11 +00:00

KA10: Added line buffering, and forms control support to LP.

This commit is contained in:
Richard Cornwell 2019-03-15 18:37:38 -04:00
parent 0d4cc8cc77
commit 7029542b08

View File

@ -36,11 +36,15 @@
#define LP_DEVNUM 0124
#define STATUS u3
#define CHL u4
#define CHR u5
#define COL u4
#define POS u5
#define LINE u6
#define UNIT_V_CT (UNIT_V_UF + 0)
#define UNIT_UC (1 << UNIT_V_CT)
#define UNIT_UTF8 (2 << UNIT_V_CT)
#define UNIT_CT (3 << UNIT_V_CT)
#define UNIT_V_UC (UNIT_V_UF + 0)
#define UNIT_UC (1 << UNIT_V_UC)
#define PI_DONE 000007
#define PI_ERROR 000070
#define DONE_FLG 000100
@ -49,6 +53,7 @@
#define CLR_LPT 002000
#define C96 002000
#define C128 004000
#define DEL_FLG 0100000
@ -62,6 +67,9 @@ t_stat lpt_help (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag,
const char *lpt_description (DEVICE *dptr);
int32 lpt_stopioe;
char lpt_buffer[134 * 3];
uint8 lpt_chbuf[5]; /* Read in Character buffers */
/* LPT data structures
lpt_dev LPT device descriptor
@ -72,19 +80,22 @@ int32 lpt_stopioe;
DIB lpt_dib = { LP_DEVNUM, 1, &lpt_devio, NULL };
UNIT lpt_unit = {
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 0), SERIAL_OUT_WAIT
UDATA (&lpt_svc, UNIT_SEQ+UNIT_ATTABLE+UNIT_TEXT, 0), 100
};
REG lpt_reg[] = {
{ DRDATA (STATUS, lpt_unit.STATUS, 18), PV_LEFT },
{ DRDATA (TIME, lpt_unit.wait, 24), PV_LEFT },
{ FLDATA (STOP_IOE, lpt_stopioe, 0) },
{ BRDATA(BUFF, lpt_buffer, 16, 8, sizeof(lpt_buffer)), REG_HRO},
{ BRDATA(CBUFF, lpt_chbuf, 16, 8, sizeof(lpt_chbuf)), REG_HRO},
{ NULL }
};
MTAB lpt_mod[] = {
{UNIT_UC, 0, "Lower case", "LC", NULL},
{UNIT_UC, UNIT_UC, "Upper case", "UC", NULL},
{UNIT_CT, 0, "Lower case", "LC", NULL},
{UNIT_CT, UNIT_UC, "Upper case", "UC", NULL},
{UNIT_CT, UNIT_UTF8, "UTF8 ouput", "UTF8", NULL},
{ 0 }
};
@ -103,9 +114,11 @@ t_stat lpt_devio(uint32 dev, uint64 *data) {
UNIT *uptr = &lpt_unit;
switch(dev & 3) {
case CONI:
*data = uptr->STATUS;
*data = uptr->STATUS & (PI_DONE|PI_ERROR|DONE_FLG|BUSY_FLG|ERR_FLG);
if ((uptr->flags & UNIT_UC) == 0)
*data |= C96;
if ((uptr->flags & UNIT_UTF8) == 0)
*data |= C128;
if ((uptr->flags & UNIT_ATT) == 0)
*data |= ERR_FLG;
sim_debug(DEBUG_CONI, &lpt_dev, "LP CONI %012llo PC=%06o\n", *data, PC);
@ -114,31 +127,32 @@ t_stat lpt_devio(uint32 dev, uint64 *data) {
case CONO:
clr_interrupt(dev);
sim_debug(DEBUG_CONO, &lpt_dev, "LP CONO %012llo PC=%06o\n", *data, PC);
uptr->STATUS = ((PI_DONE|PI_ERROR|DONE_FLG|BUSY_FLG) & *data);
uptr->STATUS &= ~0777;
uptr->STATUS |= ((PI_DONE|PI_ERROR|DONE_FLG|BUSY_FLG|CLR_LPT) & *data);
if (*data & CLR_LPT) {
uptr->CHR = 0;
uptr->CHL = 0;
uptr->STATUS &= ~DONE_FLG;
uptr->STATUS |= BUSY_FLG;
sim_activate (&lpt_unit, lpt_unit.wait);
}
if ((uptr->flags & UNIT_ATT) == 0) {
uptr->STATUS |= ERR_FLG;
set_interrupt(dev, (uptr->STATUS >> 3));
}
if (uptr->STATUS & DONE_FLG)
if ((uptr->STATUS & DONE_FLG) != 0)
set_interrupt(dev, uptr->STATUS);
break;
case DATAO:
if ((uptr->STATUS & BUSY_FLG) == 0) {
uptr->CHL = (int32)(*data >> 15);
uptr->CHR = (*data >> 1) & 0037777;
uptr->STATUS |= BUSY_FLG;
if ((uptr->STATUS & DONE_FLG) != 0) {
int i, j;
for (j = 0, i = 29; i > 0; i-=7)
lpt_chbuf[j++] = ((uint8)(*data >> i)) & 0x7f;
uptr->STATUS &= ~DONE_FLG;
uptr->STATUS |= BUSY_FLG;
clr_interrupt(dev);
sim_activate (&lpt_unit, lpt_unit.wait);
}
sim_debug(DEBUG_DATAIO, &lpt_dev, "LP DATO %012llo, %06o %06o PC=%06o\n",
*data, uptr->CHL, uptr->CHR, PC);
sim_debug(DEBUG_DATAIO, &lpt_dev, "LP DATO %012llo PC=%06o\n", *data, PC);
}
break;
case DATAI:
*data = 0;
@ -147,53 +161,198 @@ t_stat lpt_devio(uint32 dev, uint64 *data) {
return SCPE_OK;
}
/* Unit service */
t_stat lpt_output(UNIT *uptr, char c) {
if (c == 0)
return SCPE_OK;
if (uptr->flags & UNIT_UC)
c = toupper(c);
fputc (c, uptr->fileref); /* print char */
uptr->pos = ftell (uptr->fileref);
void
lpt_printline(UNIT *uptr, int nl) {
int trim = 0;
/* Trim off trailing blanks */
while (uptr->COL >= 0 && lpt_buffer[uptr->POS - 1] == ' ') {
uptr->COL--;
uptr->POS--;
trim = 1;
}
lpt_buffer[uptr->POS] = '\0';
sim_debug(DEBUG_DETAIL, &lpt_dev, "LP output %d %d [%s]\n", uptr->COL, nl, lpt_buffer);
/* Stick a carraige return and linefeed as needed */
if (uptr->COL != 0 || trim)
lpt_buffer[uptr->POS++] = '\r';
if (nl) {
lpt_buffer[uptr->POS++] = '\n';
uptr->LINE++;
}
sim_fwrite(&lpt_buffer, 1, uptr->POS, uptr->fileref);
uptr->COL = 0;
uptr->POS = 0;
if (ferror (uptr->fileref)) { /* error? */
perror ("LPT I/O error");
clearerr (uptr->fileref);
uptr->STATUS |= ERR_FLG;
set_interrupt(LP_DEVNUM, (uptr->STATUS >> 3));
return SCPE_IOERR;
return;
}
return SCPE_OK;
return;
}
uint16 utf_code[32] = {
0x0000, /* Dot */
0x2193, /* Down arrow */
0x237a, /* APL Alpha */
0x03b2, /* Beta */
0x039b, /* Lambda */
0x2510, /* Box light down and left */
0x03b5, /* Epsilon */
0x03d6, /* Pi */
0x03bb, /* Lambda */
0x221d, /* proportional */
0x222b, /* Integral */
0x00b1, /* Plus minus */
0x2295, /* Circle plus */
0x221e, /* Infinity */
0x2202, /* Partial derivitive */
0x2282, /* Subset of */
0x2283, /* Superset of */
0x2229, /* Intersection */
0x222a, /* union */
0x2200, /* For all */
0x2203, /* Exists */
0x2295, /* Circle plus */
0x2194, /* Left right arrow */
0x2227, /* Logical and */
0x2192, /* Rightwards arror */
0x2014, /* Em dash */
0x2260, /* Not equal */
0x2264, /* Less than or equal */
0x2265, /* Greater than or equal */
0x2261, /* Identical too */
0x2228 /* Logical or */
};
/* Unit service */
void
lpt_output(UNIT *uptr, char c) {
if (c == 0)
return;
if ((uptr->flags & UNIT_UC) && (c & 0140) == 0140)
c &= 0137;
if ((uptr->flags & UNIT_UTF8) && c < 040) {
uint16 u = utf_code[c & 0x1f];
if (u > 0x7ff) {
lpt_buffer[uptr->POS++] = 0xe0 + ((u >> 12) & 0xf);
lpt_buffer[uptr->POS++] = 0x80 + ((u >> 6) & 0x3f);
lpt_buffer[uptr->POS++] = 0x80 + (u & 0x3f);
} else if (u > 0x7f) {
lpt_buffer[uptr->POS++] = 0xc0 + ((u >> 6) & 0x3f);
lpt_buffer[uptr->POS++] = 0x80 + (u & 0x3f);
} else {
lpt_buffer[uptr->POS++] = u & 0x7f;
}
uptr->COL++;
} else if (c >= 040) {
lpt_buffer[uptr->POS++] = c;
uptr->COL++;
}
if (uptr->COL == 132)
lpt_printline(uptr, 1);
return;
}
t_stat lpt_svc (UNIT *uptr)
{
t_stat r;
char c;
int pos;
int cpos;
if ((uptr->flags & DONE_FLG) != 0) {
set_interrupt(LP_DEVNUM, uptr->STATUS);
return SCPE_OK;
}
if ((uptr->flags & UNIT_ATT) == 0) {
uptr->STATUS |= ERR_FLG;
set_interrupt(LP_DEVNUM, (uptr->STATUS >> 3));
return SCPE_OK;
}
c = (uptr->CHL >> 14) & 0177;
if ((r = lpt_output(uptr, c)) != SCPE_OK)
return r;
c = (uptr->CHL >> 7) & 0177;
if ((r = lpt_output(uptr, c)) != SCPE_OK)
return r;
c = uptr->CHL & 0177;
if ((r = lpt_output(uptr, c)) != SCPE_OK)
return r;
c = (uptr->CHR >> 7) & 0177;
if ((r = lpt_output(uptr, c)) != SCPE_OK)
return r;
c = uptr->CHR & 0177;
if ((r = lpt_output(uptr, c)) != SCPE_OK)
return r;
if (uptr->STATUS & CLR_LPT) {
for (pos = 0; pos < uptr->COL; lpt_buffer[pos++] = ' ');
uptr->POS = uptr->COL;
lpt_printline(uptr, 0);
uptr->STATUS &= ~(DEL_FLG|ERR_FLG|BUSY_FLG|CLR_LPT);
uptr->STATUS |= DONE_FLG;
set_interrupt(LP_DEVNUM, uptr->STATUS);
return SCPE_OK;
}
for (cpos = 0; cpos < 5; cpos++) {
c = lpt_chbuf[cpos];
if (uptr->STATUS & DEL_FLG) {
lpt_output(uptr, c);
uptr->STATUS &= ~DEL_FLG;
} else if (c == 0177) { /* Check for DEL Character */
uptr->STATUS |= DEL_FLG;
} else if (c < 040) { /* Control character */
switch(c) {
case 011: /* Horizontal tab, space to 8'th column */
lpt_output(uptr, ' ');
while ((uptr->COL & 07) != 0)
lpt_output(uptr, ' ');
break;
case 015: /* Carriage return, print line */
lpt_printline(uptr, 0);
break;
case 012: /* Line feed, print line, space one line */
lpt_printline(uptr, 1);
uptr->LINE++;
break;
case 014: /* Form feed, skip to top of page */
lpt_printline(uptr, 0);
sim_fwrite("\014", 1, 1, uptr->fileref);
uptr->LINE = 0;
break;
case 013: /* Vertical tab, Skip mod 20 */
lpt_printline(uptr, 1);
while((uptr->LINE % 20) != 0) {
sim_fwrite("\r\n", 1, 2, uptr->fileref);
uptr->LINE++;
}
break;
case 020: /* Skip even lines */
lpt_printline(uptr, 1);
while((uptr->LINE % 2) != 0) {
sim_fwrite("\r\n", 1, 2, uptr->fileref);
uptr->LINE++;
}
break;
case 021: /* Skip third lines */
lpt_printline(uptr, 1);
while((uptr->LINE % 3) != 0) {
sim_fwrite("\r\n", 1, 2, uptr->fileref);
uptr->LINE++;
}
break;
case 022: /* Skip one line */
lpt_printline(uptr, 1);
sim_fwrite("\r\n", 1, 2, uptr->fileref);
uptr->LINE+=2;
break;
case 023: /* Skip every 10 lines */
lpt_printline(uptr, 1);
while((uptr->LINE % 10) != 0) {
sim_fwrite("\r\n", 1, 2, uptr->fileref);
uptr->LINE++;
}
break;
default: /* Ignore */
break;
}
} else {
lpt_output(uptr, c);
}
}
uptr->STATUS &= ~BUSY_FLG;
uptr->STATUS |= DONE_FLG;
set_interrupt(LP_DEVNUM, uptr->STATUS);
//fprintf(stderr, "LP IRQ\n\r");
return SCPE_OK;
}
@ -202,9 +361,10 @@ t_stat lpt_svc (UNIT *uptr)
t_stat lpt_reset (DEVICE *dptr)
{
UNIT *uptr = &lpt_unit;
uptr->CHR = 0;
uptr->CHL = 0;
uptr->STATUS = 0;
uptr->POS = 0;
uptr->COL = 0;
uptr->LINE = 1;
uptr->STATUS = DONE_FLG;
clr_interrupt(LP_DEVNUM);
sim_cancel (&lpt_unit); /* deactivate unit */
return SCPE_OK;