X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?p=z80comp2;a=blobdiff_plain;f=emu%2Fsrc%2Fduart.c;fp=emu%2Fsrc%2Fduart.c;h=35e23128e3c83442223c1261b8ab6c7d4ced43bf;hp=0000000000000000000000000000000000000000;hb=a0a85eb847ff3bb5da13e78618efdcd1b9f588cf;hpb=b55f31d1ac4a1991f2ad7b2d17be06969ea25e47 diff --git a/emu/src/duart.c b/emu/src/duart.c new file mode 100644 index 0000000..35e2312 --- /dev/null +++ b/emu/src/duart.c @@ -0,0 +1,169 @@ +#include "duart.h" +#include "emu.h" + +enum { + REG_MRA = 0x0, + REG_SRA_CSRA = 0x1, + REG_CRA = 0x2, + REG_RBA_TBA = 0x3, + REG_IPCR_ACR = 0x4, + REG_ISR_IMR = 0x5, + REG_CUR_CTUR = 0x6, + REG_CLR_CTLR = 0x7, + REG_MRB = 0x8, + REG_SRB_CSRB = 0x9, + REG_CRB = 0xa, + REG_RBB_TBB = 0xb, + REG_IVR = 0xc, + REG_IP_OPCR = 0xd, + REG_CSTART_OPSET= 0xe, + REG_CSTOP_OPCLR = 0xf +}; + +enum { + CMD_RX_ONOFF = 0x03, + CMD_TX_ONOFF = 0x0c, + CMD_RST_MPTR = 0x10, + CMD_RST_RX = 0x20, + CMD_RST_TX = 0x30, + CMD_RST_ERR = 0x40, + CMD_RST_BRKINT = 0x50, + CMD_START_BRK = 0x60, + CMD_STOP_BRK = 0x70 +}; + +enum { + STAT_RXRDY = 0x01, + STAT_FFULL = 0x02, + STAT_TXRDY = 0x04, + STAT_TXEMPTY = 0x08, + STAT_ERR_OVR = 0x10, + STAT_ERR_PAR = 0x20, + STAT_ERR_FRM = 0x40, + STAT_ERR_BRK = 0x80 +}; + +struct port { + uint8_t mode[2]; + uint8_t clksel; + int modeptr; + int tx, rx; + uint8_t rxfifo[4]; + int rxfifo_in, rxfifo_out; + +}; + +static struct port port[2]; +static uint8_t reg_ipcr; +static uint8_t reg_auxctl; +static uint8_t reg_istat; +static uint8_t reg_imask; +static uint16_t reg_count; +static uint8_t reg_ivec; +static uint8_t reg_opcr; +static uint8_t oport; + +void duart_reset(void) +{ + int i; + + reg_imask = 0; + reg_istat = 0; + reg_opcr = 0; + reg_ivec = 0xf; + oport = 0; + + for(i=0; i<2; i++) { + port[i].mode[0] = port[i].mode[1] = 0; + port[i].modeptr = 0; + port[i].tx = port[i].rx = 0; + port[i].rxfifo_in = port[i].rxfifo_out = 0; + } +} + +void duart_serin(int port, int c) +{ +} + +static int tx_ready(int pidx) +{ + return port[pidx].tx; +} + +static int rx_ready(int pidx) +{ + return port[pidx].rxfifo_in != port[pidx].rxfifo_out; +} + +static int rx_full(int pidx) +{ + return ((port[pidx].rxfifo_in + 1) & 3) == port[pidx].rxfifo_out; +} + +static void command(int pidx, uint8_t data) +{ + if(data & CMD_RX_ONOFF) { + port[pidx].rx = (data & CMD_RX_ONOFF) == 1; + } + if(data & CMD_TX_ONOFF) { + port[pidx].tx = (data & CMD_TX_ONOFF) == 4; + } + switch(data & 0xf0) { + case CMD_RST_MPTR: + port[pidx].modeptr = 0; + break; + + default: + break; + } +} + +uint8_t duart_read(int rs) +{ + uint8_t res; + int pidx = (rs >> 3) & 1; + + switch(rs) { + case REG_SRA_CSRA: + case REG_SRB_CSRB: + res = STAT_TXEMPTY | STAT_TXRDY; + if(rx_ready(pidx)) { + res |= STAT_RXRDY; + } + if(rx_full(pidx)) { + res |= STAT_FFULL; + } + return res; + + default: + break; + } + return 0; +} + +void duart_write(int rs, uint8_t data) +{ + int mptr; + int pidx = (rs >> 3) & 1; + + switch(rs) { + case REG_CRA: + case REG_CRB: + command(pidx, data); + break; + + case REG_MRA: + case REG_MRB: + mptr = port[pidx].modeptr; + port[pidx].mode[mptr] = data; + if(!mptr) port[pidx].modeptr = 1; + break; + + case REG_RBA_TBA: + case REG_RBB_TBB: + if(tx_ready(pidx)) { + emu_serout(pidx, data); + } + break; + } +}