3581beace0
The buffer's implementation wasn't buying us much in exchange for its complexity. A modern machine was still too fast for it (copy/pasting text from a modern machine would send bytes too fast for the RC2014) and in the (theoretical so far) case of COS-to-COS communication, the buffer didn't help in cases where the baud rate was faster than the processing of each byte received (for example, if the byte was written directly to EEPROM). I'm scrapping it and, instead, use the RTS flag to signal the other side when we're ready to receive a new byte. Also, implement driver for channel B in SIO. I will need it to talk to my TRS-80 4P.
88 lines
1.6 KiB
C
88 lines
1.6 KiB
C
#include <stdio.h>
|
|
#include "acia.h"
|
|
|
|
static void _check_irq(ACIA *acia)
|
|
{
|
|
// do we have RDRF?
|
|
if ((acia->status & 0x01) && (acia->control & 0x80)) {
|
|
acia->status |= 0x80;
|
|
}
|
|
// do we have TDRE?
|
|
if ((acia->status & 0x02) && ((acia->control & 0xe0) == 0xe0)) {
|
|
acia->status |= 0x80;
|
|
}
|
|
}
|
|
|
|
void acia_init(ACIA *acia)
|
|
{
|
|
acia->status = 0x02; // TDRE
|
|
acia->control = 0x00;
|
|
acia->rx = 0;
|
|
acia->tx = 0;
|
|
acia->in_int = false;
|
|
}
|
|
|
|
bool acia_has_irq(ACIA *acia)
|
|
{
|
|
if (acia->in_int) {
|
|
return false;
|
|
}
|
|
acia->in_int = acia->status & 0x80;
|
|
return acia->in_int;
|
|
}
|
|
|
|
bool acia_hasrx(ACIA *acia)
|
|
{
|
|
return acia->status & 0x01; // RDRF
|
|
}
|
|
|
|
bool acia_hastx(ACIA *acia)
|
|
{
|
|
return !(acia->status & 0x02); // TRDE
|
|
}
|
|
|
|
uint8_t acia_read(ACIA *acia)
|
|
{
|
|
acia->status |= 0x02; // TRDE high
|
|
_check_irq(acia);
|
|
return acia->tx;
|
|
}
|
|
|
|
void acia_write(ACIA *acia, uint8_t val)
|
|
{
|
|
if (acia->control & 0x40) { // RTS high
|
|
fprintf(stderr, "ACIA RTS high: can't send byte\n");
|
|
return;
|
|
}
|
|
acia->status |= 0x01; // RDRF high
|
|
acia->rx = val;
|
|
_check_irq(acia);
|
|
}
|
|
|
|
uint8_t acia_ctl_rd(ACIA *acia)
|
|
{
|
|
return acia->status;
|
|
}
|
|
|
|
void acia_ctl_wr(ACIA *acia, uint8_t val)
|
|
{
|
|
acia->control = val;
|
|
_check_irq(acia);
|
|
}
|
|
|
|
uint8_t acia_data_rd(ACIA *acia)
|
|
{
|
|
acia->status &= ~0x81; // RDRF and IRQ low
|
|
acia->in_int = false;
|
|
return acia->rx;
|
|
}
|
|
|
|
void acia_data_wr(ACIA *acia, uint8_t val)
|
|
{
|
|
acia->tx = val;
|
|
acia->status &= ~0x82; // TRDE and IRQ low
|
|
acia->in_int = false;
|
|
_check_irq(acia);
|
|
}
|
|
|