OSDN Git Service

[General] Merge upstream 2015-01-31 , pc8801ma is still not working correct.
[csp-qt/common_source_project-fm7.git] / source / src / vm / z80sio.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2006.12.31 -
6
7         [ Z80SIO ]
8 */
9
10 #include "z80sio.h"
11 #include "../fifo.h"
12 #include "../fileio.h"
13
14 #define EVENT_SEND      2
15 #define EVENT_RECV      4
16
17
18 //#define SIO_DEBUG
19
20 #define MONOSYNC(ch)    ((port[ch].wr[4] & 0x3c) == 0x00)
21 #define BISYNC(ch)      ((port[ch].wr[4] & 0x3c) == 0x10)
22 //#define SDLC(ch)      ((port[ch].wr[4] & 0x3c) == 0x20)
23 //#define EXTSYNC(ch)   ((port[ch].wr[4] & 0x3c) == 0x30)
24 #define SYNC_MODE(ch)   (MONOSYNC(ch) || BISYNC(ch))
25
26 #define BIT_SYNC1       1
27 #define BIT_SYNC2       2
28
29 #define REGISTER_SEND_EVENT(ch) { \
30         if(port[ch].tx_clock != 0) { \
31                 if(port[ch].send_id == -1) { \
32                         register_event(this, EVENT_SEND + ch, port[ch].tx_interval, false, &port[ch].send_id); \
33                 } \
34         } else { \
35                 if(port[ch].tx_bits_x2_remain == 0) { \
36                         port[ch].tx_bits_x2_remain = port[ch].tx_bits_x2; \
37                 } \
38         } \
39 }
40
41 #define CANCEL_SEND_EVENT(ch) { \
42         if(port[ch].tx_clock != 0) { \
43                 if(port[ch].send_id != -1) { \
44                         cancel_event(this, port[ch].send_id); \
45                         port[ch].send_id = -1; \
46                 } \
47         } else { \
48                 port[ch].tx_bits_x2_remain = 0; \
49         } \
50 }
51
52 #define REGISTER_RECV_EVENT(ch) { \
53         if(port[ch].rx_clock != 0) { \
54                 if(port[ch].recv_id == -1) { \
55                         register_event(this, EVENT_RECV + ch, port[ch].rx_interval, false, &port[ch].recv_id); \
56                 } \
57         } else { \
58                 if(port[ch].rx_bits_x2_remain == 0) { \
59                         port[ch].rx_bits_x2_remain = port[ch].rx_bits_x2; \
60                 } \
61         } \
62 }
63
64 #define CANCEL_RECV_EVENT(ch) { \
65         if(port[ch].rx_clock != 0) { \
66                 if(port[ch].recv_id != -1) { \
67                         cancel_event(this, port[ch].recv_id); \
68                         port[ch].recv_id = -1; \
69                 } \
70         } else { \
71                 port[ch].rx_bits_x2_remain = 0; \
72         } \
73 }
74
75 void Z80SIO::initialize()
76 {
77         for(int ch = 0; ch < 2; ch++) {
78 #ifdef HAS_UPD7201
79                 port[ch].send = new FIFO(16);
80                 port[ch].recv = new FIFO(16);
81                 port[ch].rtmp = new FIFO(16);
82 #else
83                 port[ch].send = new FIFO(2);
84                 port[ch].recv = new FIFO(4);
85                 port[ch].rtmp = new FIFO(8);
86 #endif
87                 // input signals
88                 port[ch].dcd = true;
89                 port[ch].cts = true;
90                 port[ch].sync = true;
91                 port[ch].sync_bit = 0;
92         }
93 }
94
95 void Z80SIO::reset()
96 {
97         for(int ch = 0; ch < 2; ch++) {
98                 port[ch].pointer = 0;
99                 port[ch].nextrecv_intr = false;
100                 port[ch].first_data = false;
101                 port[ch].over_flow = false;
102                 port[ch].under_run = false;
103                 port[ch].abort = false;
104 #ifdef HAS_UPD7201
105                 port[ch].tx_count = 0;
106 #endif
107                 port[ch].send_id = -1;
108                 port[ch].recv_id = -1;
109                 port[ch].send->clear();
110                 port[ch].recv->clear();
111                 port[ch].rtmp->clear();
112                 memset(port[ch].wr, 0, sizeof(port[ch].wr));
113                 // interrupt
114                 port[ch].err_intr = false;
115                 port[ch].recv_intr = 0;
116                 port[ch].stat_intr = false;
117                 port[ch].send_intr = false;
118                 port[ch].req_intr = false;
119                 port[ch].in_service = false;
120         }
121         iei = oei = true;
122 }
123
124 void Z80SIO::release()
125 {
126         for(int ch = 0; ch < 2; ch++) {
127                 if(port[ch].send) {
128                         port[ch].send->release();
129                         delete port[ch].send;
130                 }
131                 if(port[ch].recv) {
132                         port[ch].recv->release();
133                         delete port[ch].recv;
134                 }
135                 if(port[ch].rtmp) {
136                         port[ch].rtmp->release();
137                         delete port[ch].rtmp;
138                 }
139         }
140 }
141
142 /*
143         0       ch.a data
144         1       ch.a control
145         2       ch.b data
146         3       ch.b control
147 */
148
149 void Z80SIO::write_io8(uint32 addr, uint32 data)
150 {
151         int ch = (addr >> 1) & 1;
152         bool update_intr_required = false;
153         bool update_tx_timing_required = false;
154         bool update_rx_timing_required = false;
155         
156         switch(addr & 3) {
157         case 0:
158         case 2:
159                 // send data
160                 port[ch].send->write(data);
161 #ifdef UPD7210
162                 port[ch].tx_count++;
163 #endif
164                 if(port[ch].send_intr) {
165                         port[ch].send_intr = false;
166                         update_intr();
167                 }
168                 // register next event
169                 CANCEL_SEND_EVENT(ch);
170                 if(port[ch].wr[5] & 8) {
171                         int tx_data_bits = 5;
172                         if((data & 0xe0) == 0x00) {
173                                 tx_data_bits = 5;
174                         } else if((data & 0xf0) == 0x80) {
175                                 tx_data_bits = 4;
176                         } else if((data & 0xf8) == 0xc0) {
177                                 tx_data_bits = 3;
178                         } else if((data & 0xfc) == 0xe0) {
179                                 tx_data_bits = 2;
180                         } else if((data & 0xfe) == 0xf0) {
181                                 tx_data_bits = 1;
182                         }
183                         if(port[ch].tx_data_bits != tx_data_bits) {
184                                 port[ch].tx_data_bits = tx_data_bits;
185                                 update_tx_timing(ch);
186                         }
187                         REGISTER_SEND_EVENT(ch);
188                 }
189                 break;
190         case 1:
191         case 3:
192                 // control
193 #ifdef SIO_DEBUG
194 //              emu->out_debug_log(_T("Z80SIO: ch=%d WR[%d]=%2x\n"), ch, port[ch].pointer, data);
195 #endif
196                 switch(port[ch].pointer) {
197                 case 0:
198                         switch(data & 0x38) {
199                         case 0x10:
200                                 if(port[ch].stat_intr) {
201                                         port[ch].stat_intr = false;
202                                         update_intr_required = true;
203                                 }
204                                 break;
205                         case 0x18:
206                                 CANCEL_SEND_EVENT(ch);
207                                 CANCEL_RECV_EVENT(ch);
208                                 port[ch].nextrecv_intr = false;
209                                 port[ch].first_data = false;
210                                 port[ch].over_flow = false;
211 #ifdef HAS_UPD7201
212                                 port[ch].tx_count = 0;  // is this correct ???
213 #endif
214                                 port[ch].send->clear();
215                                 port[ch].recv->clear();
216                                 port[ch].rtmp->clear();
217                                 memset(port[ch].wr, 0, sizeof(port[ch].wr));
218                                 // interrupt
219                                 if(port[ch].err_intr) {
220                                         port[ch].err_intr = false;
221                                         update_intr_required = true;
222                                 }
223                                 if(port[ch].recv_intr) {
224                                         port[ch].recv_intr = 0;
225                                         update_intr_required = true;
226                                 }
227                                 if(port[ch].stat_intr) {
228                                         port[ch].stat_intr = false;
229                                         update_intr_required = true;
230                                 }
231                                 if(port[ch].send_intr) {
232                                         port[ch].send_intr = false;
233                                         update_intr_required = true;
234                                 }
235                                 port[ch].req_intr = false;
236                                 break;
237                         case 0x20:
238                                 port[ch].nextrecv_intr = true;
239                                 break;
240                         case 0x28:
241                                 if(port[ch].send_intr) {
242                                         port[ch].send_intr = false;
243                                         update_intr_required = true;
244                                 }
245                                 break;
246                         case 0x30:
247                                 port[ch].over_flow = false;
248                                 if(port[ch].err_intr) {
249                                         port[ch].err_intr = false;
250                                         update_intr_required = true;
251                                 }
252                                 break;
253                         case 0x38:
254                                 // end of interrupt
255                                 if(ch == 0) {
256                                         for(int c = 0; c < 2; c++) {
257                                                 if(port[c].in_service) {
258                                                         port[c].in_service = false;
259                                                         update_intr_required = true;
260                                                         break;
261                                                 }
262                                         }
263                                 }
264                                 break;
265                         }
266                         switch(data & 0xc0) {
267                         case 0x40:
268                                 // reset receive crc checker
269                                 break;
270                         case 0x80:
271                                 // reset transmit crc generator
272                                 break;
273                         case 0xc0:
274                                 // reset transmit underrun
275                                 if(port[ch].under_run) {
276                                         port[ch].under_run = false;
277                                         if(port[ch].stat_intr) {
278                                                 port[ch].stat_intr = false;
279                                                 update_intr_required = true;
280                                         }
281                                 }
282                                 break;
283                         }
284                         break;
285                 case 1:
286                 case 2:
287                         if(port[ch].wr[port[ch].pointer] != data) {
288                                 update_intr_required = true;
289                         }
290                         break;
291                 case 3:
292                         if((data & 0x11) == 0x11) {
293                                 // enter hunt/sync phase
294                                 if(MONOSYNC(ch)) {
295 #ifdef SIO_DEBUG
296                                         emu->out_debug_log(_T("Z80SIO: ch=%d enter hunt/sync phase (monosync)\n"), ch);
297 #endif
298                                         port[ch].sync_bit = BIT_SYNC1;
299                                 } else if(BISYNC(ch)) {
300 #ifdef SIO_DEBUG
301                                         emu->out_debug_log(_T("Z80SIO: ch=%d enter hunt/sync phase (bisync)\n"), ch);
302 #endif
303                                         port[ch].sync_bit = BIT_SYNC1 | BIT_SYNC2;
304                                 }
305                                 port[ch].sync = false;
306                                 write_signals(&port[ch].outputs_sync, 0xffffffff);
307                         }
308                         if((port[ch].wr[3] & 0xc0) != (data & 0xc0)) {
309                                 update_rx_timing_required = true;
310                         }
311                         break;
312                 case 4:
313                         if((port[ch].wr[4] & 0xcd) != (data & 0xcd)) {
314                                 update_tx_timing_required = update_rx_timing_required = true;
315                         }
316                         break;
317                 case 5:
318                         if((uint32)(port[ch].wr[5] & 2) != (data & 2)) {
319                                 // rts
320                                 write_signals(&port[ch].outputs_rts, (data & 2) ? 0 : 0xffffffff);
321                         }
322                         if((uint32)(port[ch].wr[5] & 0x80) != (data & 0x80)) {
323                                 // dtr
324                                 write_signals(&port[ch].outputs_dtr, (data & 0x80) ? 0 : 0xffffffff);
325                         }
326                         if(data & 8) {
327                                 REGISTER_SEND_EVENT(ch);
328                         } else {
329                                 CANCEL_SEND_EVENT(ch);
330                         }
331                         if(data & 0x10) {
332                                 // send break
333                                 write_signals(&port[ch].outputs_break, 0xffffffff);
334                         }
335                         if((port[ch].wr[5] & 0x60) != (data & 0x60)) {
336                                 update_tx_timing_required = true;
337                         }
338                         break;
339                 }
340                 port[ch].wr[port[ch].pointer] = data;
341                 if(update_intr_required) {
342                         update_intr();
343                 }
344                 if(update_tx_timing_required) {
345                         update_tx_timing(ch);
346                 }
347                 if(update_rx_timing_required) {
348                         update_rx_timing(ch);
349                 }
350                 port[ch].pointer = (port[ch].pointer == 0) ? (data & 7) : 0;
351                 break;
352         }
353 }
354
355 uint32 Z80SIO::read_io8(uint32 addr)
356 {
357         int ch = (addr >> 1) & 1;
358         uint32 val = 0;
359         
360         switch(addr & 3) {
361         case 0:
362         case 2:
363                 // recv data;
364                 if(port[ch].recv_intr) {
365                         // cancel pending interrupt
366                         if(--port[ch].recv_intr == 0) {
367                                 update_intr();
368                         }
369                 }
370                 return port[ch].recv->read();
371         case 1:
372         case 3:
373                 if(port[ch].pointer == 0) {
374                         if(!port[ch].recv->empty()) {
375                                 val |= 1;
376                         }
377                         if(ch == 0 && (port[0].req_intr || port[1].req_intr)) {
378                                 val |= 2;
379                         }
380                         if(!port[ch].send->full()) {
381                                 val |= 4;       // ???
382                         }
383                         if(!port[ch].dcd) {
384                                 val |= 8;
385                         }
386                         if(!port[ch].sync) {
387                                 val |= 0x10;
388                         }
389                         if(!port[ch].cts) {
390                                 val |= 0x20;
391                         }
392                         if(port[ch].under_run) {
393                                 val |= 0x40;
394                         }
395                         if(port[ch].abort) {
396                                 val |= 0x80;
397                         }
398                 } else if(port[ch].pointer == 1) {
399                         val = 0x8e;     // TODO
400                         if(port[ch].send->empty()) {
401                                 val |= 1;
402                         }
403                         if(port[ch].over_flow) {
404                                 val |= 0x20;
405                         }
406                 } else if(port[ch].pointer == 2) {
407                         val = port[ch].vector;
408 #ifdef HAS_UPD7201
409                 } else if(port[ch].pointer == 3) {
410                         val = port[ch].tx_count & 0xff;
411                 } else if(port[ch].pointer == 4) {
412                         val = (port[ch].tx_count >> 8) & 0xff;
413 #endif
414                 }
415                 port[ch].pointer = 0;
416                 return val;
417         }
418         return 0xff;
419 }
420
421 void Z80SIO::write_signal(int id, uint32 data, uint32 mask)
422 {
423         // recv data
424         int ch = id & 1;
425         bool signal = ((data & mask) != 0);
426         
427         switch(id) {
428         case SIG_Z80SIO_RECV_CH0:
429         case SIG_Z80SIO_RECV_CH1:
430                 // recv data
431                 REGISTER_RECV_EVENT(ch);
432                 if(port[ch].rtmp->empty()) {
433                         port[ch].first_data = true;
434                 }
435                 port[ch].rtmp->write(data & mask);
436                 break;
437         case SIG_Z80SIO_BREAK_CH0:
438         case SIG_Z80SIO_BREAK_CH1:
439                 // recv break
440                 if((data & mask) && !port[ch].abort) {
441                         port[ch].abort = true;
442                         if(!port[ch].stat_intr) {
443                                 port[ch].stat_intr = true;
444                                 update_intr();
445                         }
446                 }
447                 break;
448         case SIG_Z80SIO_DCD_CH0:
449         case SIG_Z80SIO_DCD_CH1:
450                 if(port[ch].dcd != signal) {
451                         port[ch].dcd = signal;
452                         if(!signal && (port[ch].wr[3] & 0x20)) {
453                                 // auto enables
454                                 port[ch].wr[3] |= 1;
455                         }
456                         if(!port[ch].stat_intr) {
457                                 port[ch].stat_intr = true;
458                                 update_intr();
459                         }
460                 }
461                 break;
462         case SIG_Z80SIO_CTS_CH0:
463         case SIG_Z80SIO_CTS_CH1:
464                 if(port[ch].cts != signal) {
465                         port[ch].cts = signal;
466                         if(!signal && (port[ch].wr[3] & 0x20)) {
467                                 // auto enables
468                                 REGISTER_SEND_EVENT(ch);
469                                 port[ch].wr[5] |= 8;
470                         }
471                         if(!port[ch].stat_intr) {
472                                 port[ch].stat_intr = true;
473                                 update_intr();
474                         }
475                 }
476         case SIG_Z80SIO_SYNC_CH0:
477         case SIG_Z80SIO_SYNC_CH1:
478                 if(port[ch].sync != signal) {
479                         port[ch].sync = signal;
480                         if(!port[ch].stat_intr) {
481                                 port[ch].stat_intr = true;
482                                 update_intr();
483                         }
484                 }
485                 break;
486         case SIG_Z80SIO_TX_CLK_CH0:
487         case SIG_Z80SIO_TX_CLK_CH1:
488                 if(port[ch].prev_tx_clock_signal != signal) {
489                         if(port[ch].tx_bits_x2_remain > 0 && --port[ch].tx_bits_x2_remain == 0) {
490                                 event_callback(EVENT_SEND + ch, 0);
491                         }
492                         port[ch].prev_tx_clock_signal = signal;
493                 }
494                 break;
495         case SIG_Z80SIO_RX_CLK_CH0:
496         case SIG_Z80SIO_RX_CLK_CH1:
497                 if(port[ch].prev_rx_clock_signal != signal) {
498                         if(port[ch].rx_bits_x2_remain > 0 && --port[ch].rx_bits_x2_remain == 0) {
499                                 event_callback(EVENT_RECV + ch, 0);
500                         }
501                         port[ch].prev_rx_clock_signal = signal;
502                 }
503                 break;
504         case SIG_Z80SIO_CLEAR_CH0:
505         case SIG_Z80SIO_CLEAR_CH1:
506                 // hack: clear recv buffer
507                 if(data & mask) {
508                         CANCEL_RECV_EVENT(ch);
509                         port[ch].rtmp->clear();
510                         port[ch].recv->clear();
511                         if(port[ch].recv_intr) {
512                                 port[ch].recv_intr = 0;
513                                 update_intr();
514                         }
515                 }
516                 break;
517         }
518 }
519
520 void Z80SIO::event_callback(int event_id, int err)
521 {
522         int ch = event_id & 1;
523         
524         if(event_id & EVENT_SEND) {
525                 // send
526                 port[ch].send_id = -1;
527                 port[ch].tx_bits_x2_remain = 0;
528                 
529                 if(port[ch].send->empty()) {
530                         // underrun interrupt
531                         if(!port[ch].under_run) {
532                                 port[ch].under_run = true;
533                                 if(!port[ch].stat_intr) {
534                                         port[ch].stat_intr = true;
535                                         update_intr();
536                                 }
537                         }
538                 } else {
539                         uint32 data = port[ch].send->read();
540                         write_signals(&port[ch].outputs_send, data);
541                 }
542                 if(port[ch].send->empty()) {
543                         // transmitter interrupt
544                         if(!port[ch].send_intr) {
545                                 port[ch].send_intr = true;
546                                 update_intr();
547                         }
548                         write_signals(&port[ch].outputs_txdone, 0xffffffff);
549                 }
550                 // register next event
551                 REGISTER_SEND_EVENT(ch);
552         } else if(event_id & EVENT_RECV) {
553                 // recv
554                 port[ch].recv_id = -1;
555                 port[ch].rx_bits_x2_remain = 0;
556                 
557                 if(!(port[ch].wr[3] & 1)) {
558                         REGISTER_RECV_EVENT(ch);
559                         return;
560                 }
561                 bool update_intr_required = false;
562                 
563                 if(port[ch].recv->full()) {
564                         // overflow
565                         if(!port[ch].over_flow) {
566                                 port[ch].over_flow = true;
567                                 if(!port[ch].err_intr) {
568                                         port[ch].err_intr = true;
569                                         update_intr_required = true;
570                                 }
571                         }
572                 } else {
573                         // no error
574                         int data = port[ch].rtmp->read();
575                         
576                         if(SYNC_MODE(ch) && port[ch].sync_bit != 0) {
577                                 // receive sync data in monosync/bisync mode ?
578                                 if(port[ch].sync_bit & BIT_SYNC1) {
579                                         if(data != port[ch].wr[6]) {
580                                                 goto request_next_data;
581                                         }
582 #ifdef SIO_DEBUG
583                                         emu->out_debug_log(_T("Z80SIO: ch=%d recv sync1\n"), ch);
584 #endif
585                                         port[ch].sync_bit &= ~BIT_SYNC1;
586                                 } else if(port[ch].sync_bit & BIT_SYNC2) {
587                                         if(data != port[ch].wr[7]) {
588                                                 port[ch].sync_bit |= BIT_SYNC1;
589                                                 goto request_next_data;
590                                         }
591 #ifdef SIO_DEBUG
592                                         emu->out_debug_log(_T("Z80SIO: ch=%d recv sync2\n"), ch);
593 #endif
594                                         port[ch].sync_bit &= ~BIT_SYNC2;
595                                 }
596                                 if(port[ch].sync_bit == 0) {
597 #ifdef SIO_DEBUG
598                                         emu->out_debug_log(_T("Z80SIO: ch=%d leave hunt/sync phase\n"), ch);
599 #endif
600                                         if(!port[ch].stat_intr) {
601                                                 port[ch].stat_intr = true;
602                                                 update_intr_required = true;
603                                         }
604                                         port[ch].sync = true;
605                                         write_signals(&port[ch].outputs_sync, 0);
606                                 }
607                                 if(port[ch].wr[3] & 2) {
608                                         // sync char is not loaded into buffer
609                                         goto request_next_data;
610                                 }
611                         }
612                         // load received data into buffer
613 #ifdef SIO_DEBUG
614                         emu->out_debug_log(_T("Z80SIO: ch=%d recv %2x\n"), ch, data);
615 #endif
616                         port[ch].recv->write(data);
617                         
618                         // quit abort
619                         if(port[ch].abort) {
620                                 port[ch].abort = false;
621                                 if(!port[ch].stat_intr) {
622                                         port[ch].stat_intr = true;
623                                         update_intr_required = true;
624                                 }
625                         }
626                         
627                         // check receive interrupt
628                         bool req = false;
629                         if((port[ch].wr[1] & 0x18) == 8 && (port[ch].first_data || port[ch].nextrecv_intr)) {
630                                 req = true;
631                         } else if(port[ch].wr[1] & 0x10) {
632                                 req = true;
633                         }
634                         if(req) {
635                                 if(port[ch].recv_intr++ == 0) {
636                                         update_intr_required = true;
637                                 }
638                         }
639                         port[ch].first_data = port[ch].nextrecv_intr = false;
640                 }
641 request_next_data:
642                 bool first_data = port[ch].first_data;
643                 if(port[ch].rtmp->empty()) {
644                         // request data in this message
645                         write_signals(&port[ch].outputs_rxdone, 0xffffffff);
646                 }
647                 if(port[ch].rtmp->empty()) {
648                         // no data received
649 #ifdef SIO_DEBUG
650                         emu->out_debug_log(_T("Z80SIO: ch=%d end of block\n"), ch);
651 #endif
652                         port[ch].recv_id = -1;
653                 } else {
654                         REGISTER_RECV_EVENT(ch);
655                         port[ch].first_data = first_data;
656                 }
657                 if(update_intr_required) {
658                         update_intr();
659                 }
660         }
661 }
662
663 void Z80SIO::update_tx_timing(int ch)
664 {
665         port[ch].tx_bits_x2 = (port[ch].wr[4] & 1) * 2;
666         switch(port[ch].wr[5] & 0x60) {
667         case 0x00: port[ch].tx_bits_x2 += 2 * port[ch].tx_data_bits; break;
668         case 0x20: port[ch].tx_bits_x2 += 2 * 7; break;
669         case 0x40: port[ch].tx_bits_x2 += 2 * 6; break;
670         case 0x60: port[ch].tx_bits_x2 += 2 * 8; break;
671         }
672         switch(port[ch].wr[4] & 0x0c) {
673         case 0x00: port[ch].tx_bits_x2 += 0; break;     // sync mode
674         case 0x04: port[ch].tx_bits_x2 += 4; break;     // 2 * (1 + 1)
675         case 0x08: port[ch].tx_bits_x2 += 5; break;     // 2 * (1 + 1.5)
676         case 0x0c: port[ch].tx_bits_x2 += 6; break;     // 2 * (1 + 2)
677         }
678         switch(port[ch].wr[4] & 0xc0) {
679         case 0x40: port[ch].tx_bits_x2 *= 16; break;
680         case 0x80: port[ch].tx_bits_x2 *= 32; break;
681         case 0xc0: port[ch].tx_bits_x2 *= 64; break;
682         }
683         if(port[ch].tx_clock != 0) {
684                 port[ch].tx_interval = 1000000.0 / port[ch].tx_clock * (double)port[ch].tx_bits_x2 / 2.0;
685         }
686 }
687
688 void Z80SIO::update_rx_timing(int ch)
689 {
690         port[ch].rx_bits_x2 = (port[ch].wr[4] & 1) * 2;
691         switch(port[ch].wr[3] & 0xc0) {
692         case 0x00: port[ch].rx_bits_x2 += 2 * 5; break;
693         case 0x40: port[ch].rx_bits_x2 += 2 * 7; break;
694         case 0x80: port[ch].rx_bits_x2 += 2 * 6; break;
695         case 0xc0: port[ch].rx_bits_x2 += 2 * 8; break;
696         }
697         switch(port[ch].wr[4] & 0x0c) {
698         case 0x00: port[ch].rx_bits_x2 += 0; break;     // sync mode
699         case 0x04: port[ch].rx_bits_x2 += 4; break;     // 2 * (1 + 1)
700         case 0x08: port[ch].rx_bits_x2 += 5; break;     // 2 * (1 + 1.5)
701         case 0x0c: port[ch].rx_bits_x2 += 6; break;     // 2 * (1 + 2)
702         }
703         switch(port[ch].wr[4] & 0xc0) {
704         case 0x40: port[ch].rx_bits_x2 *= 16; break;
705         case 0x80: port[ch].rx_bits_x2 *= 32; break;
706         case 0xc0: port[ch].rx_bits_x2 *= 64; break;
707         }
708         if(port[ch].rx_clock != 0) {
709                 port[ch].rx_interval = 1000000.0 / port[ch].rx_clock * (double)port[ch].rx_bits_x2 / 2.0;
710         }
711 }
712
713 void Z80SIO::set_intr_iei(bool val)
714 {
715         if(iei != val) {
716                 iei = val;
717                 update_intr();
718         }
719 }
720
721 #define set_intr_oei(val) { \
722         if(oei != val) { \
723                 oei = val; \
724                 if(d_child) { \
725                         d_child->set_intr_iei(oei); \
726                 } \
727         } \
728 }
729
730 void Z80SIO::update_intr()
731 {
732         bool next;
733         
734         // set oei signal
735         if((next = iei) == true) {
736                 for(int ch = 0; ch < 2; ch++) {
737                         if(port[ch].in_service) {
738                                 next = false;
739                                 break;
740                         }
741                 }
742         }
743         set_intr_oei(next);
744         
745         // check interrupt status
746         for(int ch = 0; ch < 2; ch++) {
747                 if(port[ch].err_intr) {
748                         port[ch].req_intr = true;
749                         port[ch].affect = (ch ? 0 : 4) | 3;
750                 } else if(port[ch].recv_intr && (port[ch].wr[1] & 0x18)) {
751                         port[ch].req_intr = true;
752                         port[ch].affect = (ch ? 0 : 4) | 2;
753                 } else if(port[ch].stat_intr && (port[ch].wr[1] & 1)) {
754                         port[ch].req_intr = true;
755                         port[ch].affect = (ch ? 0 : 4) | 1;
756                 } else if(port[ch].send_intr && (port[ch].wr[1] & 2)) {
757                         port[ch].req_intr = true;
758                         port[ch].affect = (ch ? 0 : 4) | 0;
759                 } else {
760                         port[ch].req_intr = false;
761                 }
762         }
763         
764         // create vector
765         if(port[1].wr[1] & 4) {
766 #ifdef HAS_UPD7201
767                 uint8 affect = 7;       // no interrupt pending
768                 for(int ch = 0; ch < 2; ch++) {
769                         if(port[ch].in_service) {
770                                 break;
771                         }
772                         if(port[ch].req_intr) {
773                                 affect = port[ch].affect;
774                                 break;
775                         }
776                 }
777                 uint8 mode = port[0].wr[2] & 0x38;
778                 if(mode == 0 || mode == 8 || mode == 0x20 || mode == 0x28 || mode == 0x38) {
779                         port[1].vector = (port[1].wr[2] & 0xe3) | (affect << 2);        // 8085
780                 } else {
781                         port[1].vector = (port[1].wr[2] & 0xf8) | (affect << 0);        // 8086
782                 }
783 #else
784                 uint8 affect = 3;       // no interrupt pending
785                 for(int ch = 0; ch < 2; ch++) {
786                         if(port[ch].in_service) {
787                                 break;
788                         }
789                         if(port[ch].req_intr) {
790                                 affect = port[ch].affect;
791                                 break;
792                         }
793                 }
794                 port[1].vector = (port[1].wr[2] & 0xf1) | (affect << 1);
795 #endif
796         } else {
797                 port[1].vector = port[1].wr[2];
798         }
799         
800         // set int signal
801         if((next = iei) == true) {
802                 next = false;
803                 for(int ch = 0; ch < 2; ch++) {
804                         if(port[ch].in_service) {
805                                 break;
806                         }
807                         if(port[ch].req_intr) {
808                                 next = true;
809                                 break;
810                         }
811                 }
812         }
813         if(d_cpu) {
814                 d_cpu->set_intr_line(next, true, intr_bit);
815         }
816 }
817
818 uint32 Z80SIO::intr_ack()
819 {
820         // ack (M1=IORQ=L)
821         for(int ch = 0; ch < 2; ch++) {
822                 if(port[ch].in_service) {
823                         // invalid interrupt status
824                         return 0xff;
825                 }
826                 // priority is error > receive > status > send ???
827                 if(port[ch].err_intr) {
828                         port[ch].err_intr = false;
829                         port[ch].in_service = true;
830                 } else if(port[ch].recv_intr && (port[ch].wr[1] & 0x18)) {
831                         port[ch].recv_intr = 0;
832                         port[ch].in_service = true;
833                 } else if(port[ch].stat_intr && (port[ch].wr[1] & 1)) {
834                         port[ch].stat_intr = false;
835                         port[ch].in_service = true;
836                 } else if(port[ch].send_intr && (port[ch].wr[1] & 2)) {
837                         port[ch].send_intr = false;
838                         port[ch].in_service = true;
839                 }
840                 if(port[ch].in_service) {
841                         uint8 vector = port[1].vector;
842                         update_intr();
843                         return vector;
844                 }
845         }
846         if(d_child) {
847                 return d_child->intr_ack();
848         }
849         return 0xff;
850 }
851
852 void Z80SIO::intr_reti()
853 {
854         // detect RETI
855         for(int ch = 0; ch < 2; ch++) {
856                 if(port[ch].in_service) {
857                         port[ch].in_service = false;
858                         update_intr();
859                         return;
860                 }
861         }
862         if(d_child) {
863                 d_child->intr_reti();
864         }
865 }
866
867 #define STATE_VERSION   2
868
869 void Z80SIO::save_state(FILEIO* state_fio)
870 {
871         state_fio->FputUint32(STATE_VERSION);
872         state_fio->FputInt32(this_device_id);
873         
874         for(int i = 0; i < 2; i++) {
875                 state_fio->FputInt32(port[i].pointer);
876                 state_fio->Fwrite(port[i].wr, sizeof(port[i].wr), 1);
877                 state_fio->FputUint8(port[i].vector);
878                 state_fio->FputUint8(port[i].affect);
879                 state_fio->FputBool(port[i].nextrecv_intr);
880                 state_fio->FputBool(port[i].first_data);
881                 state_fio->FputBool(port[i].over_flow);
882                 state_fio->FputBool(port[i].under_run);
883                 state_fio->FputBool(port[i].abort);
884                 state_fio->FputBool(port[i].sync);
885                 state_fio->FputUint8(port[i].sync_bit);
886 #ifdef HAS_UPD7201
887                 state_fio->FputUint16(port[i].tx_count);
888 #endif
889                 state_fio->FputDouble(port[i].tx_clock);
890                 state_fio->FputDouble(port[i].tx_interval);
891                 state_fio->FputDouble(port[i].rx_clock);
892                 state_fio->FputDouble(port[i].rx_interval);
893                 state_fio->FputInt32(port[i].tx_data_bits);
894                 state_fio->FputInt32(port[i].tx_bits_x2);
895                 state_fio->FputInt32(port[i].tx_bits_x2_remain);
896                 state_fio->FputInt32(port[i].rx_bits_x2);
897                 state_fio->FputInt32(port[i].rx_bits_x2_remain);
898                 state_fio->FputBool(port[i].prev_tx_clock_signal);
899                 state_fio->FputBool(port[i].prev_rx_clock_signal);
900                 port[i].send->save_state((void *)state_fio);
901                 port[i].recv->save_state((void *)state_fio);
902                 port[i].rtmp->save_state((void *)state_fio);
903                 state_fio->FputInt32(port[i].send_id);
904                 state_fio->FputInt32(port[i].recv_id);
905                 state_fio->FputBool(port[i].err_intr);
906                 state_fio->FputInt32(port[i].recv_intr);
907                 state_fio->FputBool(port[i].stat_intr);
908                 state_fio->FputBool(port[i].send_intr);
909                 state_fio->FputBool(port[i].req_intr);
910                 state_fio->FputBool(port[i].in_service);
911                 state_fio->FputBool(port[i].dcd);
912                 state_fio->FputBool(port[i].cts);
913         }
914         state_fio->FputBool(iei);
915         state_fio->FputBool(oei);
916         state_fio->FputUint32(intr_bit);
917 }
918
919 bool Z80SIO::load_state(FILEIO* state_fio)
920 {
921         if(state_fio->FgetUint32() != STATE_VERSION) {
922                 return false;
923         }
924         if(state_fio->FgetInt32() != this_device_id) {
925                 return false;
926         }
927         for(int i = 0; i < 2; i++) {
928                 port[i].pointer = state_fio->FgetInt32();
929                 state_fio->Fread(port[i].wr, sizeof(port[i].wr), 1);
930                 port[i].vector = state_fio->FgetUint8();
931                 port[i].affect = state_fio->FgetUint8();
932                 port[i].nextrecv_intr = state_fio->FgetBool();
933                 port[i].first_data = state_fio->FgetBool();
934                 port[i].over_flow = state_fio->FgetBool();
935                 port[i].under_run = state_fio->FgetBool();
936                 port[i].abort = state_fio->FgetBool();
937                 port[i].sync = state_fio->FgetBool();
938                 port[i].sync_bit = state_fio->FgetUint8();
939 #ifdef HAS_UPD7201
940                 port[i].tx_count = state_fio->FgetUint16();
941 #endif
942                 port[i].tx_clock = state_fio->FgetDouble();
943                 port[i].tx_interval = state_fio->FgetDouble();
944                 port[i].rx_clock = state_fio->FgetDouble();
945                 port[i].rx_interval = state_fio->FgetDouble();
946                 port[i].tx_data_bits = state_fio->FgetInt32();
947                 port[i].tx_bits_x2 = state_fio->FgetInt32();
948                 port[i].tx_bits_x2_remain = state_fio->FgetInt32();
949                 port[i].rx_bits_x2 = state_fio->FgetInt32();
950                 port[i].rx_bits_x2_remain = state_fio->FgetInt32();
951                 port[i].prev_tx_clock_signal = state_fio->FgetBool();
952                 port[i].prev_rx_clock_signal = state_fio->FgetBool();
953                 if(!port[i].send->load_state((void *)state_fio)) {
954                         return false;
955                 }
956                 if(!port[i].recv->load_state((void *)state_fio)) {
957                         return false;
958                 }
959                 if(!port[i].rtmp->load_state((void *)state_fio)) {
960                         return false;
961                 }
962                 port[i].send_id = state_fio->FgetInt32();
963                 port[i].recv_id = state_fio->FgetInt32();
964                 port[i].err_intr = state_fio->FgetBool();
965                 port[i].recv_intr = state_fio->FgetInt32();
966                 port[i].stat_intr = state_fio->FgetBool();
967                 port[i].send_intr = state_fio->FgetBool();
968                 port[i].req_intr = state_fio->FgetBool();
969                 port[i].in_service = state_fio->FgetBool();
970                 port[i].dcd = state_fio->FgetBool();
971                 port[i].cts = state_fio->FgetBool();
972         }
973         iei = state_fio->FgetBool();
974         oei = state_fio->FgetBool();
975         intr_bit = state_fio->FgetUint32();
976         return true;
977 }
978