OSDN Git Service

[VM] .
[csp-qt/common_source_project-fm7.git] / source / src / vm / sy6522.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MAME 0.164 Rockwell 6522 VIA
5         Author : Takeda.Toshiya
6         Date   : 2015.08.27-
7
8         [ SY6522 ]
9 */
10
11 // license:BSD-3-Clause
12 // copyright-holders:Peter Trauner, Mathis Rosenhauer
13 /**********************************************************************
14
15     Rockwell 6522 VIA interface and emulation
16
17     This function emulates the functionality of up to 8 6522
18     versatile interface adapters.
19
20     This is based on the M6821 emulation in MAME.
21
22     To do:
23
24     T2 pulse counting mode
25     Pulse mode handshake output
26     More shift register
27
28 **********************************************************************/
29
30 /*
31   1999-Dec-22 PeT
32    vc20 random number generation only partly working
33    (reads (uninitialized) timer 1 and timer 2 counter)
34    timer init, reset, read changed
35  */
36
37 //#include "vm.h"
38 //#include "../emu.h"
39 #include "sy6522.h"
40
41 /***************************************************************************
42     MACROS
43 ***************************************************************************/
44
45 /* Macros for PCR */
46 #define CA1_LOW_TO_HIGH(c)      (c & 0x01)
47 #define CA1_HIGH_TO_LOW(c)      (!(c & 0x01))
48
49 #define CB1_LOW_TO_HIGH(c)      (c & 0x10)
50 #define CB1_HIGH_TO_LOW(c)      (!(c & 0x10))
51
52 #define CA2_INPUT(c)            (!(c & 0x08))
53 #define CA2_LOW_TO_HIGH(c)      ((c & 0x0c) == 0x04)
54 #define CA2_HIGH_TO_LOW(c)      ((c & 0x0c) == 0x00)
55 #define CA2_IND_IRQ(c)          ((c & 0x0a) == 0x02)
56
57 #define CA2_OUTPUT(c)           (c & 0x08)
58 #define CA2_AUTO_HS(c)          ((c & 0x0c) == 0x08)
59 #define CA2_HS_OUTPUT(c)        ((c & 0x0e) == 0x08)
60 #define CA2_PULSE_OUTPUT(c)     ((c & 0x0e) == 0x0a)
61 #define CA2_FIX_OUTPUT(c)       ((c & 0x0c) == 0x0c)
62 #define CA2_OUTPUT_LEVEL(c)     ((c & 0x02) >> 1)
63
64 #define CB2_INPUT(c)            (!(c & 0x80))
65 #define CB2_LOW_TO_HIGH(c)      ((c & 0xc0) == 0x40)
66 #define CB2_HIGH_TO_LOW(c)      ((c & 0xc0) == 0x00)
67 #define CB2_IND_IRQ(c)          ((c & 0xa0) == 0x20)
68
69 #define CB2_OUTPUT(c)           (c & 0x80)
70 #define CB2_AUTO_HS(c)          ((c & 0xc0) == 0x80)
71 #define CB2_HS_OUTPUT(c)        ((c & 0xe0) == 0x80)
72 #define CB2_PULSE_OUTPUT(c)     ((c & 0xe0) == 0xa0)
73 #define CB2_FIX_OUTPUT(c)       ((c & 0xc0) == 0xc0)
74 #define CB2_OUTPUT_LEVEL(c)     ((c & 0x20) >> 5)
75
76 /* Macros for ACR */
77 #define PA_LATCH_ENABLE(c)      (c & 0x01)
78 #define PB_LATCH_ENABLE(c)      (c & 0x02)
79
80 #define SR_DISABLED(c)          (!(c & 0x1c))
81 #define SI_T2_CONTROL(c)        ((c & 0x1c) == 0x04)
82 #define SI_O2_CONTROL(c)        ((c & 0x1c) == 0x08)
83 #define SI_EXT_CONTROL(c)       ((c & 0x1c) == 0x0c)
84 #define SO_T2_RATE(c)           ((c & 0x1c) == 0x10)
85 #define SO_T2_CONTROL(c)        ((c & 0x1c) == 0x14)
86 #define SO_O2_CONTROL(c)        ((c & 0x1c) == 0x18)
87 #define SO_EXT_CONTROL(c)       ((c & 0x1c) == 0x1c)
88
89 #define T1_SET_PB7(c)           (c & 0x80)
90 #define T1_CONTINUOUS(c)        (c & 0x40)
91 #define T2_COUNT_PB6(c)         (c & 0x20)
92
93 /* Interrupt flags */
94 #define INT_CA2 0x01
95 #define INT_CA1 0x02
96 #define INT_SR  0x04
97 #define INT_CB2 0x08
98 #define INT_CB1 0x10
99 #define INT_T2  0x20
100 #define INT_T1  0x40
101 #define INT_ANY 0x80
102
103 #define CLR_PA_INT()    clear_int(INT_CA1 | ((!CA2_IND_IRQ(m_pcr)) ? INT_CA2: 0))
104 #define CLR_PB_INT()    clear_int(INT_CB1 | ((!CB2_IND_IRQ(m_pcr)) ? INT_CB2: 0))
105
106 #define IFR_DELAY 3
107
108 #define TIMER1_VALUE    (m_t1ll+(m_t1lh<<8))
109 #define TIMER2_VALUE    (m_t2ll+(m_t2lh<<8))
110
111 // XXX: from 6522via.h
112
113 enum
114 {
115         TIMER_SHIFT = 0,
116         TIMER_T1 = 1,
117         TIMER_T2 = 2,
118         TIMER_CA2 = 3
119 };
120
121 enum
122 {
123         VIA_PB = 0,
124         VIA_PA = 1,
125         VIA_DDRB = 2,
126         VIA_DDRA = 3,
127         VIA_T1CL = 4,
128         VIA_T1CH = 5,
129         VIA_T1LL = 6,
130         VIA_T1LH = 7,
131         VIA_T2CL = 8,
132         VIA_T2CH = 9,
133         VIA_SR = 10,
134         VIA_ACR = 11,
135         VIA_PCR = 12,
136         VIA_IFR = 13,
137         VIA_IER = 14,
138         VIA_PANH = 15
139 };
140
141 // XXX: definitions for conversion
142
143 #define clocks_to_attotime(c)   (1000000.0 * (c) / clock)
144 #define attotime_to_clocks(u)   (int)(clock * (u) / 1000000.0 + 0.5)
145
146 #define m_out_a_handler(v)      write_signals(&outputs_a, (v))
147 #define m_out_b_handler(v)      write_signals(&outputs_b, (v))
148 #define m_ca2_handler(v)        write_signals(&outputs_ca2, (v) ? 0xffffffff : 0)
149 #define m_cb1_handler(v)        write_signals(&outputs_cb1, (v) ? 0xffffffff : 0)
150 #define m_cb2_handler(v)        write_signals(&outputs_cb2, (v) ? 0xffffffff : 0)
151 #define m_irq_handler(v)        write_signals(&outputs_irq, (v) ? 0xffffffff : 0)
152
153 #define ASSERT_LINE             1
154 #define CLEAR_LINE              0
155
156 /***************************************************************************
157     INLINE FUNCTIONS
158 ***************************************************************************/
159
160 uint16_t SY6522::get_counter1_value()
161 {
162         uint16_t val;
163
164         if(m_t1_active)
165         {
166                 val = attotime_to_clocks(get_event_remaining_usec(m_t1)) - IFR_DELAY;
167         }
168         else
169         {
170                 val = 0xffff - attotime_to_clocks(get_passed_usec(m_time1));
171         }
172
173         return val;
174 }
175
176
177 //**************************************************************************
178 //  LIVE DEVICE
179 //**************************************************************************
180
181 //-------------------------------------------------
182 //  device_start - device-specific startup
183 //-------------------------------------------------
184
185 void SY6522::initialize()
186 {
187         DEVICE::initialize();
188         m_t1ll = 0xf3; /* via at 0x9110 in vic20 show these values */
189         m_t1lh = 0xb5; /* ports are not written by kernel! */
190         m_t2ll = 0xff; /* taken from vice */
191         m_t2lh = 0xff;
192         m_sr = 0;
193
194         m_time2 = m_time1 = 0;//machine().time();
195 }
196
197
198 //-------------------------------------------------
199 //  device_reset - device-specific reset
200 //-------------------------------------------------
201
202 void SY6522::reset()
203 {
204         m_out_a = 0;
205         m_out_ca2 = 1;
206         m_ddr_a = 0;
207         m_latch_a = 0;
208
209         m_out_b = 0;
210         m_out_cb1 = 1;
211         m_out_cb2 = 1;
212         m_ddr_b = 0;
213         m_latch_b = 0;
214
215         m_t1cl = 0;
216         m_t1ch = 0;
217         m_t2cl = 0;
218         m_t2ch = 0;
219
220         m_pcr = 0;
221         m_acr = 0;
222         m_ier = 0;
223         m_ifr = 0;
224         m_t1_active = 0;
225         m_t1_pb7 = 1;
226         m_t2_active = 0;
227         m_shift_counter = 0;
228
229         output_pa();
230         output_pb();
231         m_ca2_handler(m_out_ca2);
232         m_cb1_handler(m_out_cb1);
233         m_cb2_handler(m_out_cb2);
234
235         // XXX: non loop events are canceled in reset()
236         m_t1_active = 0;
237         m_t2_active = 0;
238         m_t1 = -1;
239         m_t2 = -1;
240         m_ca2_timer = -1;
241         m_shift_timer = -1;
242 }
243
244
245 void SY6522::output_irq()
246 {
247         if (m_ier & m_ifr & 0x7f)
248         {
249                 if ((m_ifr & INT_ANY) == 0)
250                 {
251                         m_ifr |= INT_ANY;
252                         m_irq_handler(ASSERT_LINE);
253                 }
254         }
255         else
256         {
257                 if (m_ifr & INT_ANY)
258                 {
259                         m_ifr &= ~INT_ANY;
260                         m_irq_handler(CLEAR_LINE);
261                 }
262         }
263 }
264
265
266 /*-------------------------------------------------
267     via_set_int - external interrupt check
268 -------------------------------------------------*/
269
270 void SY6522::set_int(int data)
271 {
272         if (!(m_ifr & data))
273         {
274                 m_ifr |= data;
275
276                 output_irq();
277         }
278 }
279
280
281 /*-------------------------------------------------
282     via_clear_int - external interrupt check
283 -------------------------------------------------*/
284
285 void SY6522::clear_int(int data)
286 {
287         if (m_ifr & data)
288         {
289                 m_ifr &= ~data;
290
291                 output_irq();
292         }
293 }
294
295
296 /*-------------------------------------------------
297     via_shift
298 -------------------------------------------------*/
299
300 void SY6522::shift_out()
301 {
302         m_out_cb2 = (m_sr >> 7) & 1;
303         m_sr =  (m_sr << 1) | m_out_cb2;
304
305         m_cb2_handler(m_out_cb2);
306
307         if (!SO_T2_RATE(m_acr))
308         {
309                 m_shift_counter = (m_shift_counter + 1) % 8;
310
311                 if (m_shift_counter == 0)
312                 {
313                         set_int(INT_SR);
314                 }
315         }
316 }
317
318 void SY6522::shift_in()
319 {
320         m_sr =  (m_sr << 1) | (m_in_cb2 & 1);
321
322         m_shift_counter = (m_shift_counter + 1) % 8;
323
324         if (m_shift_counter == 0)
325         {
326                 set_int(INT_SR);
327         }
328 }
329
330
331 void SY6522::event_callback(int id, int err)
332 {
333         switch (id)
334         {
335                 case TIMER_SHIFT:
336                         m_shift_timer = -1;
337                         m_out_cb1 = 0;
338                         m_cb1_handler(m_out_cb1);
339
340                         if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
341                         {
342                                 shift_out();
343                         }
344
345                         m_out_cb1 = 1;
346                         m_cb1_handler(m_out_cb1);
347
348                         if (SI_T2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr))
349                         {
350                                 shift_in();
351                         }
352
353                         if (SO_T2_RATE(m_acr) || m_shift_counter)
354                         {
355                                 if (SI_O2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
356                                 {
357                                         register_event(this, TIMER_SHIFT, clocks_to_attotime(2), false, &m_shift_timer);
358                                 }
359                                 else
360                                 {
361                                         register_event(this, TIMER_SHIFT, clocks_to_attotime((m_t2ll + 2)*2), false, &m_shift_timer);
362                                 }
363                         }
364                         break;
365
366                 case TIMER_T1:
367                         m_t1 = -1;
368
369                         if (T1_CONTINUOUS (m_acr))
370                         {
371                                 m_t1_pb7 = !m_t1_pb7;
372                                 register_event(this, TIMER_T1, clocks_to_attotime(TIMER1_VALUE + IFR_DELAY), false, &m_t1);
373                         }
374                         else
375                         {
376                                 m_t1_pb7 = 1;
377                                 m_t1_active = 0;
378                                 m_time1 = get_current_clock();
379                         }
380
381                         if (T1_SET_PB7(m_acr))
382                         {
383                                 output_pb();
384                         }
385
386                         set_int(INT_T1);
387                         break;
388
389                 case TIMER_T2:
390                         m_t2 = -1;
391                         m_t2_active = 0;
392                         m_time2 = get_current_clock();
393
394                         set_int(INT_T2);
395                         break;
396
397                 case TIMER_CA2:
398                         m_ca2_timer = -1;
399                         m_out_ca2 = 1;
400                         m_ca2_handler(m_out_ca2);
401                         break;
402         }
403 }
404
405 uint8_t SY6522::input_pa()
406 {
407         /// TODO: REMOVE THIS
408 //      if (!m_in_a_handler.isnull())
409 //      {
410 //              if (m_ddr_a != 0xff)
411 //                      m_in_a = m_in_a_handler(0);
412 //
413 //              return (m_out_a & m_ddr_a) + (m_in_a & ~m_ddr_a);
414 //      }
415
416         return m_in_a & (m_out_a | ~m_ddr_a);
417 }
418
419 void SY6522::output_pa()
420 {
421         uint8_t pa = (m_out_a & m_ddr_a) | ~m_ddr_a;
422         m_out_a_handler(pa);
423 }
424
425 uint8_t SY6522::input_pb()
426 {
427         /// TODO: REMOVE THIS
428 //      if (m_ddr_b != 0xff && !m_in_b_handler.isnull())
429 //      {
430 //              m_in_b = m_in_b_handler(0);
431 //      }
432
433         uint8_t pb = (m_out_b & m_ddr_b) + (m_in_b & ~m_ddr_b);
434
435         if (T1_SET_PB7(m_acr))
436                 pb = (pb & 0x7f) | (m_t1_pb7 << 7);
437
438         return pb;
439 }
440
441 void SY6522::output_pb()
442 {
443         uint8_t pb = (m_out_b & m_ddr_b) | ~m_ddr_b;
444
445         if (T1_SET_PB7(m_acr))
446                 pb = (pb & 0x7f) | (m_t1_pb7 << 7);
447
448         m_out_b_handler(pb);
449 }
450
451 /*-------------------------------------------------
452     via_r - CPU interface for VIA read
453 -------------------------------------------------*/
454
455 uint32_t SY6522::read_io8(uint32_t offset)
456 {
457         uint32_t val = 0;
458 //      if (space.debugger_access())
459 //              return 0;
460
461         offset &= 0xf;
462
463         switch (offset)
464         {
465         case VIA_PB:
466                 /* update the input */
467                 if (PB_LATCH_ENABLE(m_acr) == 0)
468                 {
469                         val = input_pb();
470                 }
471                 else
472                 {
473                         val = m_latch_b;
474                 }
475
476                 CLR_PB_INT();
477                 break;
478
479         case VIA_PA:
480                 /* update the input */
481                 if (PA_LATCH_ENABLE(m_acr) == 0)
482                 {
483                         val = input_pa();
484                 }
485                 else
486                 {
487                         val = m_latch_a;
488                 }
489
490                 CLR_PA_INT();
491
492                 if (m_out_ca2 && (CA2_PULSE_OUTPUT(m_pcr) || CA2_AUTO_HS(m_pcr)))
493                 {
494                         m_out_ca2 = 0;
495                         m_ca2_handler(m_out_ca2);
496                 }
497
498                 if (CA2_PULSE_OUTPUT(m_pcr))
499                 {
500                         if(m_ca2_timer != -1)
501                                 cancel_event(this, m_ca2_timer);
502                         register_event(this, TIMER_CA2, clocks_to_attotime(1), false, &m_ca2_timer);
503                 }
504
505                 break;
506
507         case VIA_PANH:
508                 /* update the input */
509                 if (PA_LATCH_ENABLE(m_acr) == 0)
510                 {
511                         val = input_pa();
512                 }
513                 else
514                 {
515                         val = m_latch_a;
516                 }
517                 break;
518
519         case VIA_DDRB:
520                 val = m_ddr_b;
521                 break;
522
523         case VIA_DDRA:
524                 val = m_ddr_a;
525                 break;
526
527         case VIA_T1CL:
528                 clear_int(INT_T1);
529                 val = get_counter1_value() & 0xFF;
530                 break;
531
532         case VIA_T1CH:
533                 val = get_counter1_value() >> 8;
534                 break;
535
536         case VIA_T1LL:
537                 val = m_t1ll;
538                 break;
539
540         case VIA_T1LH:
541                 val = m_t1lh;
542                 break;
543
544         case VIA_T2CL:
545                 clear_int(INT_T2);
546                 if (m_t2_active)
547                 {
548                         val = attotime_to_clocks(get_event_remaining_usec(m_t2)) & 0xff;
549                 }
550                 else
551                 {
552                         if (T2_COUNT_PB6(m_acr))
553                         {
554                                 val = m_t2cl;
555                         }
556                         else
557                         {
558                                 val = (0x10000 - (attotime_to_clocks(get_passed_usec(m_time2)) & 0xffff) - 1) & 0xff;
559                         }
560                 }
561                 break;
562
563         case VIA_T2CH:
564                 if (m_t2_active)
565                 {
566                         val = attotime_to_clocks(get_event_remaining_usec(m_t2)) >> 8;
567                 }
568                 else
569                 {
570                         if (T2_COUNT_PB6(m_acr))
571                         {
572                                 val = m_t2ch;
573                         }
574                         else
575                         {
576                                 val = (0x10000 - (attotime_to_clocks(get_passed_usec(m_time2)) & 0xffff) - 1) >> 8;
577                         }
578                 }
579                 break;
580
581         case VIA_SR:
582                 val = m_sr;
583                 m_shift_counter=0;
584                 clear_int(INT_SR);
585                 if (SI_O2_CONTROL(m_acr))
586                 {
587                         if(m_shift_timer != -1)
588                                 cancel_event(this, m_shift_timer);
589                         register_event(this, TIMER_SHIFT, clocks_to_attotime(2), false, &m_shift_timer);
590                 }
591                 if (SI_T2_CONTROL(m_acr))
592                 {
593                         if(m_shift_timer != -1)
594                                 cancel_event(this, m_shift_timer);
595                         register_event(this, TIMER_SHIFT, clocks_to_attotime((m_t2ll + 2)*2), false, &m_shift_timer);
596                 }
597                 break;
598
599         case VIA_PCR:
600                 val = m_pcr;
601                 break;
602
603         case VIA_ACR:
604                 val = m_acr;
605                 break;
606
607         case VIA_IER:
608                 val = m_ier | 0x80;
609                 break;
610
611         case VIA_IFR:
612                 val = m_ifr;
613                 break;
614         }
615         return val & 0xff;
616 }
617
618
619 /*-------------------------------------------------
620     via_w - CPU interface for VIA write
621 -------------------------------------------------*/
622
623 void SY6522::write_io8(uint32_t offset, uint32_t data)
624 {
625         offset &=0x0f;
626
627         switch (offset)
628         {
629         case VIA_PB:
630                 m_out_b = data;
631
632                 if (m_ddr_b != 0)
633                 {
634                         output_pb();
635                 }
636
637                 CLR_PB_INT();
638
639                 if (m_out_cb2 && CB2_AUTO_HS(m_pcr))
640                 {
641                         m_out_cb2 = 0;
642                         m_cb2_handler(m_out_cb2);
643                 }
644                 break;
645
646         case VIA_PA:
647                 m_out_a = data;
648
649                 if (m_ddr_a != 0)
650                 {
651                         output_pa();
652                 }
653
654                 CLR_PA_INT();
655
656                 if (m_out_ca2 && (CA2_PULSE_OUTPUT(m_pcr) || CA2_AUTO_HS(m_pcr)))
657                 {
658                         m_out_ca2 = 0;
659                         m_ca2_handler(m_out_ca2);
660                 }
661
662                 if (CA2_PULSE_OUTPUT(m_pcr))
663                 {
664                         if(m_ca2_timer != -1)
665                                 cancel_event(this, m_ca2_timer);
666                         register_event(this, TIMER_CA2, clocks_to_attotime(1), false, &m_ca2_timer);
667                 }
668
669                 break;
670
671         case VIA_PANH:
672                 m_out_a = data;
673
674                 if (m_ddr_a != 0)
675                 {
676                         output_pa();
677                 }
678
679                 break;
680
681         case VIA_DDRB:
682                 if ( data != m_ddr_b )
683                 {
684                         m_ddr_b = data;
685
686                         output_pb();
687                 }
688                 break;
689
690         case VIA_DDRA:
691                 if (m_ddr_a != data)
692                 {
693                         m_ddr_a = data;
694
695                         output_pa();
696                 }
697                 break;
698
699         case VIA_T1CL:
700         case VIA_T1LL:
701                 m_t1ll = data;
702                 break;
703
704         case VIA_T1LH:
705                 m_t1lh = data;
706                 clear_int(INT_T1);
707                 break;
708
709         case VIA_T1CH:
710                 m_t1ch = m_t1lh = data;
711                 m_t1cl = m_t1ll;
712
713                 clear_int(INT_T1);
714
715                 m_t1_pb7 = 0;
716
717                 if (T1_SET_PB7(m_acr))
718                 {
719                         output_pb();
720                 }
721
722                 if(m_t1 != -1)
723                         cancel_event(this, m_t1);
724                 register_event(this, TIMER_T1, clocks_to_attotime(TIMER1_VALUE + IFR_DELAY), false, &m_t1);
725                 m_t1_active = 1;
726                 break;
727
728         case VIA_T2CL:
729                 m_t2ll = data;
730                 break;
731
732         case VIA_T2CH:
733                 m_t2ch = m_t2lh = data;
734                 m_t2cl = m_t2ll;
735
736                 clear_int(INT_T2);
737
738                 if (!T2_COUNT_PB6(m_acr))
739                 {
740                         if(m_t2 != -1)
741                                 cancel_event(this, m_t2);
742                         register_event(this, TIMER_T2, clocks_to_attotime(TIMER2_VALUE + IFR_DELAY), false, &m_t2);
743                         m_t2_active = 1;
744                 }
745                 else
746                 {
747                         if(m_t2 != -1)
748                                 cancel_event(this, m_t2);
749                         register_event(this, TIMER_T2, clocks_to_attotime(TIMER2_VALUE), false, &m_t2);
750                         m_t2_active = 1;
751                         m_time2 = get_current_clock();
752                 }
753                 break;
754
755         case VIA_SR:
756                 m_sr = data;
757                 m_shift_counter=0;
758                 clear_int(INT_SR);
759                 if (SO_O2_CONTROL(m_acr))
760                 {
761                         if(m_shift_timer != -1)
762                                 cancel_event(this, m_shift_timer);
763                         register_event(this, TIMER_SHIFT, clocks_to_attotime(2), false, &m_shift_timer);
764                 }
765                 if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr))
766                 {
767                         if(m_shift_timer != -1)
768                                 cancel_event(this, m_shift_timer);
769                         register_event(this, TIMER_SHIFT, clocks_to_attotime((m_t2ll + 2)*2), false, &m_shift_timer);
770                 }
771                 break;
772
773         case VIA_PCR:
774                 m_pcr = data;
775
776                 if (CA2_FIX_OUTPUT(data) && m_out_ca2 != CA2_OUTPUT_LEVEL(data))
777                 {
778                         m_out_ca2 = CA2_OUTPUT_LEVEL(data);
779                         m_ca2_handler(m_out_ca2);
780                 }
781
782                 if (CB2_FIX_OUTPUT(data) && m_out_cb2 != CB2_OUTPUT_LEVEL(data))
783                 {
784                         m_out_cb2 = CB2_OUTPUT_LEVEL(data);
785                         m_cb2_handler(m_out_cb2);
786                 }
787                 break;
788
789         case VIA_ACR:
790                 {
791                         uint16_t counter1 = get_counter1_value();
792                         m_acr = data;
793
794                         output_pb();
795
796                         if (T1_CONTINUOUS(data))
797                         {
798                                 if(m_t1 != -1)
799                                         cancel_event(this, m_t1);
800                                 register_event(this, TIMER_T1, clocks_to_attotime(counter1 + IFR_DELAY), false, &m_t1);
801                                 m_t1_active = 1;
802                         }
803                 }
804                 break;
805
806         case VIA_IER:
807                 if (data & 0x80)
808                 {
809                         m_ier |= data & 0x7f;
810                 }
811                 else
812                 {
813                         m_ier &= ~(data & 0x7f);
814                 }
815
816                 output_irq();
817                 break;
818
819         case VIA_IFR:
820                 if (data & INT_ANY)
821                 {
822                         data = 0x7f;
823                 }
824                 clear_int(data);
825                 break;
826         }
827 }
828
829 void SY6522::write_signal(int id, uint32_t data, uint32_t mask)
830 {
831         int state = (data & mask) ? 1 : 0;
832         
833         switch(id) {
834         case SIG_SY6522_PORT_A:
835                 m_in_a &= ~mask;
836                 m_in_a |= (data & mask);
837                 break;
838
839         case SIG_SY6522_PORT_CA1:
840                 /*-------------------------------------------------
841                     ca1_w - interface setting VIA port CA1 input
842                 -------------------------------------------------*/
843                 if (m_in_ca1 != state)
844                 {
845                         m_in_ca1 = state;
846
847                         if ((m_in_ca1 && CA1_LOW_TO_HIGH(m_pcr)) || (!m_in_ca1 && CA1_HIGH_TO_LOW(m_pcr)))
848                         {
849                                 if (PA_LATCH_ENABLE(m_acr))
850                                 {
851                                         m_latch_a = input_pa();
852                                 }
853
854                                 set_int(INT_CA1);
855
856                                 if (!m_out_ca2 && CA2_AUTO_HS(m_pcr))
857                                 {
858                                         m_out_ca2 = 1;
859                                         m_ca2_handler(m_out_ca2);
860                                 }
861                         }
862                 }
863                 break;
864
865         case SIG_SY6522_PORT_CA2:
866                 /*-------------------------------------------------
867                     ca2_w - interface setting VIA port CA2 input
868                 -------------------------------------------------*/
869                 if (m_in_ca2 != state)
870                 {
871                         m_in_ca2 = state;
872
873                         if (CA2_INPUT(m_pcr))
874                         {
875                                 if ((m_in_ca2 && CA2_LOW_TO_HIGH(m_pcr)) || (!m_in_ca2 && CA2_HIGH_TO_LOW(m_pcr)))
876                                 {
877                                         set_int(INT_CA2);
878                                 }
879                         }
880                 }
881                 break;
882
883         case SIG_SY6522_PORT_B:
884                 m_in_b &= ~mask;
885                 m_in_b |= (data & mask);
886                 break;
887
888         case SIG_SY6522_PORT_CB1:
889                 /*-------------------------------------------------
890                     cb1_w - interface setting VIA port CB1 input
891                 -------------------------------------------------*/
892                 if (m_in_cb1 != state)
893                 {
894                         m_in_cb1 = state;
895
896                         if ((m_in_cb1 && CB1_LOW_TO_HIGH(m_pcr)) || (!m_in_cb1 && CB1_HIGH_TO_LOW(m_pcr)))
897                         {
898                                 if (PB_LATCH_ENABLE(m_acr))
899                                 {
900                                         m_latch_b = input_pb();
901                                 }
902
903                                 if (SO_EXT_CONTROL(m_acr))
904                                 {
905                                         shift_out();
906                                 }
907
908                                 if (SI_EXT_CONTROL(m_acr))
909                                 {
910                                         shift_in();
911                                 }
912
913                                 set_int(INT_CB1);
914
915                                 if (!m_out_cb2 && CB2_AUTO_HS(m_pcr))
916                                 {
917                                         m_out_cb2 = 1;
918                                         m_cb2_handler(1);
919                                 }
920                         }
921                 }
922                 break;
923
924         case SIG_SY6522_PORT_CB2:
925                 /*-------------------------------------------------
926                     cb2_w - interface setting VIA port CB2 input
927                 -------------------------------------------------*/
928                 if (m_in_cb2 != state)
929                 {
930                         m_in_cb2 = state;
931
932                         if (CB2_INPUT(m_pcr))
933                         {
934                                 if ((m_in_cb2 && CB2_LOW_TO_HIGH(m_pcr)) || (!m_in_cb2 && CB2_HIGH_TO_LOW(m_pcr)))
935                                 {
936                                         set_int(INT_CB2);
937                                 }
938                         }
939                 }
940                 break;
941         }
942 }
943
944 #define STATE_VERSION   1
945
946 bool SY6522::process_state(FILEIO* state_fio, bool loading)
947 {
948         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
949                 return false;
950         }
951         if(!state_fio->StateCheckInt32(this_device_id)) {
952                 return false;
953         }
954         state_fio->StateUint8(m_in_a);
955         state_fio->StateInt32(m_in_ca1);
956         state_fio->StateInt32(m_in_ca2);
957         state_fio->StateUint8(m_out_a);
958         state_fio->StateInt32(m_out_ca2);
959         state_fio->StateUint8(m_ddr_a);
960         state_fio->StateUint8(m_latch_a);
961         state_fio->StateUint8(m_in_b);
962         state_fio->StateInt32(m_in_cb1);
963         state_fio->StateInt32(m_in_cb2);
964         state_fio->StateUint8(m_out_b);
965         state_fio->StateInt32(m_out_cb1);
966         state_fio->StateInt32(m_out_cb2);
967         state_fio->StateUint8(m_ddr_b);
968         state_fio->StateUint8(m_latch_b);
969         state_fio->StateUint8(m_t1cl);
970         state_fio->StateUint8(m_t1ch);
971         state_fio->StateUint8(m_t1ll);
972         state_fio->StateUint8(m_t1lh);
973         state_fio->StateUint8(m_t2cl);
974         state_fio->StateUint8(m_t2ch);
975         state_fio->StateUint8(m_t2ll);
976         state_fio->StateUint8(m_t2lh);
977         state_fio->StateUint8(m_sr);
978         state_fio->StateUint8(m_pcr);
979         state_fio->StateUint8(m_acr);
980         state_fio->StateUint8(m_ier);
981         state_fio->StateUint8(m_ifr);
982         state_fio->StateInt32(m_t1);
983         state_fio->StateUint32(m_time1);
984         state_fio->StateUint8(m_t1_active);
985         state_fio->StateInt32(m_t1_pb7);
986         state_fio->StateInt32(m_t2);
987         state_fio->StateUint32(m_time2);
988         state_fio->StateUint8(m_t2_active);
989         state_fio->StateInt32(m_ca2_timer);
990         state_fio->StateInt32(m_shift_timer);
991         state_fio->StateUint8(m_shift_counter);
992         return true;
993 }
994