- reorganized project directory structure
[z80comp2] / emu / src / duart.c
1 #include "duart.h"
2 #include "emu.h"
3
4 enum {
5         REG_MRA                 = 0x0,
6         REG_SRA_CSRA    = 0x1,
7         REG_CRA                 = 0x2,
8         REG_RBA_TBA             = 0x3,
9         REG_IPCR_ACR    = 0x4,
10         REG_ISR_IMR             = 0x5,
11         REG_CUR_CTUR    = 0x6,
12         REG_CLR_CTLR    = 0x7,
13         REG_MRB                 = 0x8,
14         REG_SRB_CSRB    = 0x9,
15         REG_CRB                 = 0xa,
16         REG_RBB_TBB             = 0xb,
17         REG_IVR                 = 0xc,
18         REG_IP_OPCR             = 0xd,
19         REG_CSTART_OPSET= 0xe,
20         REG_CSTOP_OPCLR = 0xf
21 };
22
23 enum {
24         CMD_RX_ONOFF    = 0x03,
25         CMD_TX_ONOFF    = 0x0c,
26         CMD_RST_MPTR    = 0x10,
27         CMD_RST_RX              = 0x20,
28         CMD_RST_TX              = 0x30,
29         CMD_RST_ERR             = 0x40,
30         CMD_RST_BRKINT  = 0x50,
31         CMD_START_BRK   = 0x60,
32         CMD_STOP_BRK    = 0x70
33 };
34
35 enum {
36         STAT_RXRDY              = 0x01,
37         STAT_FFULL              = 0x02,
38         STAT_TXRDY              = 0x04,
39         STAT_TXEMPTY    = 0x08,
40         STAT_ERR_OVR    = 0x10,
41         STAT_ERR_PAR    = 0x20,
42         STAT_ERR_FRM    = 0x40,
43         STAT_ERR_BRK    = 0x80
44 };
45
46 struct port {
47         uint8_t mode[2];
48         uint8_t clksel;
49         int modeptr;
50         int tx, rx;
51         uint8_t rxfifo[4];
52         int rxfifo_in, rxfifo_out;
53
54 };
55
56 static struct port port[2];
57 static uint8_t reg_ipcr;
58 static uint8_t reg_auxctl;
59 static uint8_t reg_istat;
60 static uint8_t reg_imask;
61 static uint16_t reg_count;
62 static uint8_t reg_ivec;
63 static uint8_t reg_opcr;
64 static uint8_t oport;
65
66 void duart_reset(void)
67 {
68         int i;
69
70         reg_imask = 0;
71         reg_istat = 0;
72         reg_opcr = 0;
73         reg_ivec = 0xf;
74         oport = 0;
75
76         for(i=0; i<2; i++) {
77                 port[i].mode[0] = port[i].mode[1] = 0;
78                 port[i].modeptr = 0;
79                 port[i].tx = port[i].rx = 0;
80                 port[i].rxfifo_in = port[i].rxfifo_out = 0;
81         }
82 }
83
84 void duart_serin(int port, int c)
85 {
86 }
87
88 static int tx_ready(int pidx)
89 {
90         return port[pidx].tx;
91 }
92
93 static int rx_ready(int pidx)
94 {
95         return port[pidx].rxfifo_in != port[pidx].rxfifo_out;
96 }
97
98 static int rx_full(int pidx)
99 {
100         return ((port[pidx].rxfifo_in + 1) & 3) == port[pidx].rxfifo_out;
101 }
102
103 static void command(int pidx, uint8_t data)
104 {
105         if(data & CMD_RX_ONOFF) {
106                 port[pidx].rx = (data & CMD_RX_ONOFF) == 1;
107         }
108         if(data & CMD_TX_ONOFF) {
109                 port[pidx].tx = (data & CMD_TX_ONOFF) == 4;
110         }
111         switch(data & 0xf0) {
112         case CMD_RST_MPTR:
113                 port[pidx].modeptr = 0;
114                 break;
115
116         default:
117                 break;
118         }
119 }
120
121 uint8_t duart_read(int rs)
122 {
123         uint8_t res;
124         int pidx = (rs >> 3) & 1;
125
126         switch(rs) {
127         case REG_SRA_CSRA:
128         case REG_SRB_CSRB:
129                 res = STAT_TXEMPTY | STAT_TXRDY;
130                 if(rx_ready(pidx)) {
131                         res |= STAT_RXRDY;
132                 }
133                 if(rx_full(pidx)) {
134                         res |= STAT_FFULL;
135                 }
136                 return res;
137
138         default:
139                 break;
140         }
141         return 0;
142 }
143
144 void duart_write(int rs, uint8_t data)
145 {
146         int mptr;
147         int pidx = (rs >> 3) & 1;
148
149         switch(rs) {
150         case REG_CRA:
151         case REG_CRB:
152                 command(pidx, data);
153                 break;
154
155         case REG_MRA:
156         case REG_MRB:
157                 mptr = port[pidx].modeptr;
158                 port[pidx].mode[mptr] = data;
159                 if(!mptr) port[pidx].modeptr = 1;
160                 break;
161
162         case REG_RBA_TBA:
163         case REG_RBB_TBB:
164                 if(tx_ready(pidx)) {
165                         emu_serout(pidx, data);
166                 }
167                 break;
168         }
169 }