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;
68 recv_id = send_id = -1;
71 void I8251::write_io8(uint32_t addr, uint32_t data)
78 } else if(data & 0x80) {
79 mode = MODE_SYNC2; // 1char
81 mode = MODE_SYNC1; // 2chars
97 status &= ~(PE | OE | FE);
100 write_signals(&outputs_dtr, (data & 2) ? 0xffffffff : 0);
102 write_signals(&outputs_rst, (data & 8) ? 0xffffffff : 0);
104 rxen = ((data & 4) != 0);
105 if(rxen && !recv_buffer->empty() && recv_id == -1) {
106 register_event(this, EVENT_RECV, RECV_DELAY, false, &recv_id);
109 txen = ((data & 1) != 0);
110 if(txen && !send_buffer->empty() && send_id == -1) {
111 register_event(this, EVENT_SEND, SEND_DELAY, false, &send_id);
113 // note: when txen=false, txrdy signal must be low
118 send_buffer->write(data);
120 if(send_buffer->full()) {
122 write_signals(&outputs_txrdy, 0);
126 write_signals(&outputs_txe, 0);
128 if(txen && send_id == -1) {
129 register_event(this, EVENT_SEND, SEND_DELAY, false, &send_id);
135 uint32_t I8251::read_io8(uint32_t addr)
140 return status & ~(TXRDY | TXE);
146 write_signals(&outputs_rxrdy, 0);
152 void I8251::write_signal(int id, uint32_t data, uint32_t mask)
154 if(id == SIG_I8251_RECV) {
155 recv_buffer->write(data & mask);
157 if(rxen && !recv_buffer->empty() && recv_id == -1) {
158 register_event(this, EVENT_RECV, RECV_DELAY, false, &recv_id);
160 } else if(id == SIG_I8251_BREAK) {
162 recv_buffer->write(RECV_BREAK);
164 if(rxen && !recv_buffer->empty() && recv_id == -1) {
165 register_event(this, EVENT_RECV, RECV_DELAY, false, &recv_id);
168 } else if(id == SIG_I8251_DSR) {
174 } else if(id == SIG_I8251_CLEAR) {
175 recv_buffer->clear();
176 } else if(id == SIG_I8251_LOOPBACK) {
177 loopback = ((data & mask) != 0);
181 void I8251::event_callback(int event_id, int err)
183 if(event_id == EVENT_RECV) {
184 if(rxen && !(status & RXRDY)) {
185 if(!recv_buffer->empty()) {
186 int val = recv_buffer->read();
187 if(val == RECV_BREAK) {
190 write_signals(&outputs_syndet, 0xffffffff);
194 write_signals(&outputs_rxrdy, 0xffffffff);
198 // if data is still left in buffer, register event for next data
199 if(rxen && !recv_buffer->empty()) {
200 register_event(this, EVENT_RECV, RECV_DELAY, false, &recv_id);
204 } else if(event_id == EVENT_SEND) {
205 if(txen && !send_buffer->empty()) {
206 uint8_t send = send_buffer->read();
208 // send to this device
209 write_signal(SIG_I8251_RECV, send, 0xff);
211 // send to external devices
212 write_signals(&outputs_out, send);
216 write_signals(&outputs_txrdy, 0xffffffff);
218 if(send_buffer->empty()) {
220 write_signals(&outputs_txe, 0xffffffff);
223 // if data is still left in buffer, register event for next data
224 if(txen && !send_buffer->empty()) {
225 register_event(this, EVENT_SEND, SEND_DELAY, false, &send_id);
232 #define STATE_VERSION 1
234 void I8251::save_state(FILEIO* state_fio)
236 state_fio->FputUint32(STATE_VERSION);
237 state_fio->FputInt32(this_device_id);
239 state_fio->FputUint8(recv);
240 state_fio->FputUint8(status);
241 state_fio->FputUint8(mode);
242 state_fio->FputBool(txen);
243 state_fio->FputBool(rxen);
244 state_fio->FputBool(loopback);
245 recv_buffer->save_state((void *)state_fio);
246 send_buffer->save_state((void *)state_fio);
247 state_fio->FputInt32(recv_id);
248 state_fio->FputInt32(send_id);
251 bool I8251::load_state(FILEIO* state_fio)
253 if(state_fio->FgetUint32() != STATE_VERSION) {
256 if(state_fio->FgetInt32() != this_device_id) {
259 recv = state_fio->FgetUint8();
260 status = state_fio->FgetUint8();
261 mode = state_fio->FgetUint8();
262 txen = state_fio->FgetBool();
263 rxen = state_fio->FgetBool();
264 loopback = state_fio->FgetBool();
265 if(!recv_buffer->load_state((void *)state_fio)) {
268 if(!send_buffer->load_state((void *)state_fio)) {
271 recv_id = state_fio->FgetInt32();
272 send_id = state_fio->FgetInt32();