2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
14 #define BUFFER_SIZE 0x40000
16 #define RECV_DELAY 100
17 #define SEND_DELAY 100
39 void I8251::initialize()
42 recv_buffer = new FIFO(BUFFER_SIZE);
43 send_buffer = new FIFO(4);
49 recv_buffer->release();
51 send_buffer->release();
58 recv = 0x00; // XM8 version 1.10
63 status |= TXRDY | TXE;
64 txen = rxen = loopback = false;
69 recv_id = send_id = -1;
72 void I8251::write_io8(uint32_t addr, uint32_t data)
79 } else if(data & 0x80) {
80 mode = MODE_SYNC2; // 1char
82 mode = MODE_SYNC1; // 2chars
98 status &= ~(PE | OE | FE);
101 write_signals(&outputs_dtr, (data & 2) ? 0xffffffff : 0);
103 write_signals(&outputs_rst, (data & 8) ? 0xffffffff : 0);
105 rxen = ((data & 4) != 0);
106 if(rxen && !recv_buffer->empty() && recv_id == -1) {
107 register_event(this, EVENT_RECV, RECV_DELAY, false, &recv_id);
110 txen = ((data & 1) != 0);
111 if(txen && !send_buffer->empty() && send_id == -1) {
112 register_event(this, EVENT_SEND, SEND_DELAY, false, &send_id);
114 // note: when txen=false, txrdy signal must be low
119 send_buffer->write(data);
121 if(send_buffer->full()) {
123 write_signals(&outputs_txrdy, 0);
127 write_signals(&outputs_txe, 0);
129 if(txen && send_id == -1) {
130 register_event(this, EVENT_SEND, SEND_DELAY, false, &send_id);
136 uint32_t I8251::read_io8(uint32_t addr)
141 return status & ~(TXRDY | TXE);
147 write_signals(&outputs_rxrdy, 0);
153 void I8251::write_signal(int id, uint32_t data, uint32_t mask)
155 if(id == SIG_I8251_RECV) {
156 recv_buffer->write(data & mask);
158 if(rxen && !recv_buffer->empty() && recv_id == -1) {
159 register_event(this, EVENT_RECV, RECV_DELAY, false, &recv_id);
161 } else if(id == SIG_I8251_BREAK) {
163 recv_buffer->write(RECV_BREAK);
165 if(rxen && !recv_buffer->empty() && recv_id == -1) {
166 register_event(this, EVENT_RECV, RECV_DELAY, false, &recv_id);
169 } else if(id == SIG_I8251_DSR) {
175 } else if(id == SIG_I8251_CLEAR) {
176 recv_buffer->clear();
177 } else if(id == SIG_I8251_LOOPBACK) {
178 loopback = ((data & mask) != 0);
182 void I8251::event_callback(int event_id, int err)
184 if(event_id == EVENT_RECV) {
185 if(rxen && !(status & RXRDY)) {
186 if(!recv_buffer->empty()) {
187 int val = recv_buffer->read();
188 if(val == RECV_BREAK) {
191 write_signals(&outputs_syndet, 0xffffffff);
195 write_signals(&outputs_rxrdy, 0xffffffff);
199 // if data is still left in buffer, register event for next data
200 if(rxen && !recv_buffer->empty()) {
201 register_event(this, EVENT_RECV, RECV_DELAY, false, &recv_id);
205 } else if(event_id == EVENT_SEND) {
206 if(txen && !send_buffer->empty()) {
207 uint8_t send = send_buffer->read();
209 // send to this device
210 write_signal(SIG_I8251_RECV, send, 0xff);
212 // send to external devices
213 write_signals(&outputs_out, send);
217 write_signals(&outputs_txrdy, 0xffffffff);
219 if(send_buffer->empty()) {
221 write_signals(&outputs_txe, 0xffffffff);
224 // if data is still left in buffer, register event for next data
225 if(txen && !send_buffer->empty()) {
226 register_event(this, EVENT_SEND, SEND_DELAY, false, &send_id);
233 #define STATE_VERSION 1
235 bool I8251::process_state(FILEIO* state_fio, bool loading)
237 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
240 if(!state_fio->StateCheckInt32(this_device_id)) {
243 state_fio->StateValue(recv);
244 state_fio->StateValue(status);
245 state_fio->StateValue(mode);
246 state_fio->StateValue(txen);
247 state_fio->StateValue(rxen);
248 state_fio->StateValue(loopback);
249 if(!recv_buffer->process_state((void *)state_fio, loading)) {
252 if(!send_buffer->process_state((void *)state_fio, loading)) {
255 state_fio->StateValue(recv_id);
256 state_fio->StateValue(send_id);