1
0
mirror of https://github.com/simh/simh.git synced 2026-02-14 19:57:19 +00:00

AltairZ80: Adds Cromemco TUART devices

Adds the following devices to AltairZ80:

TUART0: Cromemco FDC controller TUART console port at I/O address 0x00.
TUART1: Cromemco TU-ART port A at I/O address 0x20.
TUART2: Cromemco TU-ART port B at I/I address 0x50.

These devices are fully TMXR capable.
This commit is contained in:
Patrick Linstruth
2024-06-03 06:16:41 -10:00
committed by Mark Pizzolato
parent b2ec2bfd26
commit 0d705c98d5

View File

@@ -215,18 +215,24 @@ static UNIT tuart2_unit[] = {
}; };
static REG tuart0_reg[] = { static REG tuart0_reg[] = {
{ HRDATAD (TXP0, tuart0_ctx.txp, 1, "TU-ART port 0 transmit pending"), },
{ HRDATAD (STB0, tuart0_ctx.stb, 8, "TU-ART port 0 status buffer"), },
{ HRDATAD (INTMASK0, tuart0_ctx.intmask, 8, "TU-ART port 0 interrupt mask"), }, { HRDATAD (INTMASK0, tuart0_ctx.intmask, 8, "TU-ART port 0 interrupt mask"), },
{ DRDATAD (INTVEC0, tuart0_ctx.intvector, 8, "TU-ART port 0 interrupt vector"), }, { DRDATAD (INTVEC0, tuart0_ctx.intvector, 8, "TU-ART port 0 interrupt vector"), },
{ HRDATAD (INTADR0, tuart0_ctx.intadr, 8, "TU-ART port 0 interrupt address"), }, { HRDATAD (INTADR0, tuart0_ctx.intadr, 8, "TU-ART port 0 interrupt address"), },
{ NULL } { NULL }
}; };
static REG tuart1_reg[] = { static REG tuart1_reg[] = {
{ HRDATAD (TXP1, tuart1_ctx.txp, 1, "TU-ART port 1/A transmit pending"), },
{ HRDATAD (STB1, tuart1_ctx.stb, 8, "TU-ART port 1/A status buffer"), },
{ HRDATAD (INTMASK1, tuart1_ctx.intmask, 8, "TU-ART port 1/A interrupt mask"), }, { HRDATAD (INTMASK1, tuart1_ctx.intmask, 8, "TU-ART port 1/A interrupt mask"), },
{ DRDATAD (INTVEC1, tuart1_ctx.intvector, 8, "TU-ART port 1/A interrupt vector"), }, { DRDATAD (INTVEC1, tuart1_ctx.intvector, 8, "TU-ART port 1/A interrupt vector"), },
{ HRDATAD (INTADR1, tuart1_ctx.intadr, 8, "TU-ART port 1/A interrupt address"), }, { HRDATAD (INTADR1, tuart1_ctx.intadr, 8, "TU-ART port 1/A interrupt address"), },
{ NULL } { NULL }
}; };
static REG tuart2_reg[] = { static REG tuart2_reg[] = {
{ HRDATAD (TXP2, tuart2_ctx.txp, 1, "TU-ART port 2/B transmit pending"), },
{ HRDATAD (STB2, tuart2_ctx.stb, 8, "TU-ART port 2/B status buffer"), },
{ HRDATAD (INTMASK2, tuart2_ctx.intmask, 8, "TU-ART port 2/B interrupt mask"), }, { HRDATAD (INTMASK2, tuart2_ctx.intmask, 8, "TU-ART port 2/B interrupt mask"), },
{ DRDATAD (INTVEC2, tuart2_ctx.intvector, 8, "TU-ART port 2/B interrupt vector"), }, { DRDATAD (INTVEC2, tuart2_ctx.intvector, 8, "TU-ART port 2/B interrupt vector"), },
{ HRDATAD (INTADR2, tuart2_ctx.intadr, 8, "TU-ART port 2/B interrupt address"), }, { HRDATAD (INTADR2, tuart2_ctx.intadr, 8, "TU-ART port 2/B interrupt address"), },
@@ -356,7 +362,7 @@ static t_stat tuart_reset(DEVICE *dptr, int32 (*routine)(const int32, const int3
dptr->units[0].dptr = dptr; dptr->units[0].dptr = dptr;
/* Reset registers */ /* Reset registers */
xptr->stb = 0x00; xptr->stb = TUART_TBE;
xptr->txp = FALSE; xptr->txp = FALSE;
xptr->hbd = 1; xptr->hbd = 1;
xptr->baud = 9600; xptr->baud = 9600;
@@ -364,8 +370,8 @@ static t_stat tuart_reset(DEVICE *dptr, int32 (*routine)(const int32, const int3
tuart_config_line(&dptr->units[0]); tuart_config_line(&dptr->units[0]);
if (!(dptr->flags & DEV_DIS) && dptr->units[0].flags & UNIT_TUART_CONSOLE) { if (!(dptr->flags & DEV_DIS)) {
sim_activate_after_abs(&dptr->units[0], dptr->units[0].wait); sim_activate_abs(&dptr->units[0], dptr->units[0].wait);
} else { } else {
sim_cancel(&dptr->units[0]); sim_cancel(&dptr->units[0]);
} }
@@ -381,6 +387,7 @@ static t_stat tuart_svc(UNIT *uptr)
TUART_CTX *xptr; TUART_CTX *xptr;
int32 c; int32 c;
t_stat r; t_stat r;
t_bool dr = TRUE;
xptr = (TUART_CTX *) uptr->dptr->ctxt; xptr = (TUART_CTX *) uptr->dptr->ctxt;
@@ -389,32 +396,27 @@ static t_stat tuart_svc(UNIT *uptr)
if (tmxr_poll_conn(xptr->tmxr) >= 0) { /* poll connection */ if (tmxr_poll_conn(xptr->tmxr) >= 0) { /* poll connection */
xptr->conn = TRUE; /* set connected */ xptr->conn = TRUE; /* set connected */
xptr->tmln->rcve = 1;
sim_debug(STATUS_MSG, uptr->dptr, "new connection.\n"); sim_debug(STATUS_MSG, uptr->dptr, "new connection.\n");
} }
} }
/* Update incoming modem status bits */
if (uptr->flags & UNIT_ATT) {
xptr->stb = 0x00;
/* Enable receiver if DCD is active low */
xptr->tmln->rcve = 1;
}
/* TX data */ /* TX data */
if (xptr->txp) { if (xptr->txp) {
if (uptr->flags & UNIT_ATT) { if (uptr->flags & UNIT_ATT) {
r = tmxr_putc_ln(xptr->tmln, xptr->txb); r = tmxr_putc_ln(xptr->tmln, xptr->txb);
xptr->txp = FALSE; /* Reset TX Pending */ xptr->txp = FALSE; /* Reset TX Pending */
if (r == SCPE_LOST) {
xptr->conn = FALSE; /* Connection was lost */
sim_debug(STATUS_MSG, uptr->dptr, "lost connection.\n");
}
} else { } else {
r = sim_putchar(xptr->txb); r = sim_putchar(xptr->txb);
xptr->txp = FALSE; /* Reset TX Pending */ xptr->txp = FALSE; /* Reset TX Pending */
} xptr->stb |= TUART_TBE; /* Xmit buffer empty */
dr = FALSE; /* Skip read */
if (r == SCPE_LOST) {
xptr->conn = FALSE; /* Connection was lost */
sim_debug(STATUS_MSG, uptr->dptr, "lost connection.\n");
} }
/* If TX buffer now empty, send interrupt */ /* If TX buffer now empty, send interrupt */
@@ -422,21 +424,16 @@ static t_stat tuart_svc(UNIT *uptr)
xptr->intadr = TUART_TBSIA; xptr->intadr = TUART_TBSIA;
tuart_int(uptr); tuart_int(uptr);
} }
} }
/* Update TBE if not set and no character pending */ /* Update TBE if not set and no character pending */
if (!xptr->txp && !(xptr->stb & TUART_TBE)) { if (!xptr->txp && !(xptr->stb & TUART_TBE) && uptr->flags & UNIT_ATT) {
if (uptr->flags & UNIT_ATT) { tmxr_poll_tx(xptr->tmxr);
tmxr_poll_tx(xptr->tmxr); xptr->stb |= (tmxr_txdone_ln(xptr->tmln) && xptr->conn) ? TUART_TBE : 0;
xptr->stb |= (tmxr_txdone_ln(xptr->tmln) && xptr->conn) ? TUART_TBE : 0;
} else {
xptr->stb |= TUART_TBE;
}
} }
/* Check for Data if RX buffer empty */ /* Check for Data if RX buffer empty */
if (!(xptr->stb & TUART_RDA)) { if (dr && !(xptr->stb & TUART_RDA)) {
if (uptr->flags & UNIT_ATT) { if (uptr->flags & UNIT_ATT) {
tmxr_poll_rx(xptr->tmxr); tmxr_poll_rx(xptr->tmxr);
@@ -451,6 +448,7 @@ static t_stat tuart_svc(UNIT *uptr)
xptr->rxb = c & 0xff; xptr->rxb = c & 0xff;
xptr->stb |= TUART_RDA; xptr->stb |= TUART_RDA;
xptr->stb &= ~(TUART_FME | TUART_ORE); xptr->stb &= ~(TUART_FME | TUART_ORE);
if (xptr->intmask & TUART_RDAIE) { if (xptr->intmask & TUART_RDAIE) {
xptr->intadr = TUART_RDAIA; xptr->intadr = TUART_RDAIA;
tuart_int(uptr); tuart_int(uptr);
@@ -458,12 +456,11 @@ static t_stat tuart_svc(UNIT *uptr)
} }
} }
sim_activate_after_abs(uptr, uptr->wait); sim_activate_abs(uptr, uptr->wait);
return SCPE_OK; return SCPE_OK;
} }
/* Attach routine */ /* Attach routine */
static t_stat tuart_attach(UNIT *uptr, CONST char *cptr) static t_stat tuart_attach(UNIT *uptr, CONST char *cptr)
{ {
@@ -478,8 +475,6 @@ static t_stat tuart_attach(UNIT *uptr, CONST char *cptr)
xptr->tmln->rcve = 1; xptr->tmln->rcve = 1;
r = tuart_config_line(uptr); r = tuart_config_line(uptr);
sim_activate_after_abs(uptr, uptr->wait);
} }
return r; return r;
@@ -500,11 +495,7 @@ static t_stat tuart_detach(UNIT *uptr)
if (uptr->flags & UNIT_ATT) { if (uptr->flags & UNIT_ATT) {
xptr = (TUART_CTX *) uptr->dptr->ctxt; xptr = (TUART_CTX *) uptr->dptr->ctxt;
if (uptr->flags & UNIT_TUART_CONSOLE) { sim_cancel(uptr);
uptr->wait = TUART_WAIT;
} else {
sim_cancel(uptr);
}
return (tmxr_detach(xptr->tmxr, uptr)); return (tmxr_detach(xptr->tmxr, uptr));
} }
@@ -575,17 +566,8 @@ static t_stat tuart_config_line(UNIT *uptr)
if (xptr != NULL) { if (xptr != NULL) {
sprintf(config, "%d-8N%d", TUART_BAUD(xptr), xptr->sbits); sprintf(config, "%d-8N%d", TUART_BAUD(xptr), xptr->sbits);
if (uptr->flags & UNIT_ATT) { if ((uptr->flags & UNIT_ATT) && (xptr->tmln->serport)) {
r = tmxr_set_config_line(xptr->tmln, config); r = tmxr_set_config_line(xptr->tmln, config);
if (xptr->tmln->serport) {
uptr->wait = 9600000 / TUART_BAUD(xptr);
} else {
uptr->wait = TUART_WAIT;
}
xptr->tmln->txbps = 0; /* Get TMXR's timing out of our way */
xptr->tmln->rxbps = 0; /* Get TMXR's timing out of our way */
} }
sim_debug(STATUS_MSG, uptr->dptr, "Port configuration set to '%s'.\n", config); sim_debug(STATUS_MSG, uptr->dptr, "Port configuration set to '%s'.\n", config);
@@ -689,8 +671,8 @@ static int32 tuart_data(DEVICE *dptr, int32 io, int32 data)
xptr->stb &= ~(TUART_RDA | TUART_FME | TUART_ORE | TUART_IPG); xptr->stb &= ~(TUART_RDA | TUART_FME | TUART_ORE | TUART_IPG);
} else { } else {
xptr->txb = data; xptr->txb = data;
xptr->stb &= ~(TUART_TBE | TUART_IPG);
xptr->txp = TRUE; xptr->txp = TRUE;
xptr->stb &= ~(TUART_TBE | TUART_IPG);
} }
return r; return r;