diff options
Diffstat (limited to 'src/emu/cpu/upd7810/upd7810.c')
| -rw-r--r-- | src/emu/cpu/upd7810/upd7810.c | 375 |
1 files changed, 140 insertions, 235 deletions
diff --git a/src/emu/cpu/upd7810/upd7810.c b/src/emu/cpu/upd7810/upd7810.c index 1232fd20271..bc62fa33ffa 100644 --- a/src/emu/cpu/upd7810/upd7810.c +++ b/src/emu/cpu/upd7810/upd7810.c @@ -1174,84 +1174,78 @@ void upd7810_device::upd7810_sio_input() } } -void upd7810_device::handle_timers(int cycles) +void upd7810_device::upd7810_handle_timer0(int cycles, int clkdiv) { - /**** TIMER 0 ****/ - if (TMM & 0x10) /* timer 0 upcounter reset ? */ - CNT0 = 0; - else + OVC0 += cycles; + while (OVC0 >= clkdiv) { - switch (TMM & 0x0c) /* timer 0 clock source */ + OVC0 -= clkdiv; + CNT0++; + if (CNT0 == TM0) { - case 0x00: /* clock divided by 12 */ - OVC0 += cycles; - while (OVC0 >= 12) + CNT0 = 0; + IRR |= INTFT0; + /* timer F/F source is timer 0 ? */ + if (0x00 == (TMM & 0x03)) { - OVC0 -= 12; - CNT0++; - if (CNT0 == TM0) - { - CNT0 = 0; - IRR |= INTFT0; - /* timer F/F source is timer 0 ? */ - if (0x00 == (TMM & 0x03)) - { - TO ^= 1; - m_to_func(TO); - } - /* timer 1 chained with timer 0 ? */ - if ((TMM & 0xe0) == 0x60) - { - CNT1++; - if (CNT1 == TM1) - { - IRR |= INTFT1; - CNT1 = 0; - /* timer F/F source is timer 1 ? */ - if (0x01 == (TMM & 0x03)) - { - TO ^= 1; - m_to_func(TO); - } - } - } - } + TO ^= 1; + m_to_func(TO); } - break; - case 0x04: /* clock divided by 384 */ - OVC0 += cycles; - while (OVC0 >= 384) + /* timer 1 chained with timer 0 ? */ + if ((TMM & 0xe0) == 0x60) { - OVC0 -= 384; - CNT0++; - if (CNT0 == TM0) + CNT1++; + if (CNT1 == TM1) { - CNT0 = 0; - IRR |= INTFT0; - /* timer F/F source is timer 0 ? */ - if (0x00 == (TMM & 0x03)) + CNT1 = 0; + IRR |= INTFT1; + /* timer F/F source is timer 1 ? */ + if (0x01 == (TMM & 0x03)) { TO ^= 1; m_to_func(TO); } - /* timer 1 chained with timer 0 ? */ - if ((TMM & 0xe0) == 0x60) - { - CNT1++; - if (CNT1 == TM1) - { - CNT1 = 0; - IRR |= INTFT1; - /* timer F/F source is timer 1 ? */ - if (0x01 == (TMM & 0x03)) - { - TO ^= 1; - m_to_func(TO); - } - } - } } } + } + } +} + +void upd7810_device::upd7810_handle_timer1(int cycles, int clkdiv) +{ + OVC1 += cycles; + while (OVC1 >= clkdiv) + { + OVC1 -= clkdiv; + CNT1++; + if (CNT1 == TM1) + { + CNT1 = 0; + IRR |= INTFT1; + /* timer F/F source is timer 1 ? */ + if (0x01 == (TMM & 0x03)) + { + TO ^= 1; + m_to_func(TO); + } + } + } +} + +void upd7810_device::handle_timers(int cycles) +{ + /**** TIMER 0 ****/ + if (TMM & 0x10) /* timer 0 upcounter reset ? */ + CNT0 = 0; + else + { + switch (TMM & 0x0c) /* timer 0 clock source */ + { + case 0x00: /* clock divided by 12 */ + upd7810_handle_timer0(cycles, 12); + break; + case 0x04: /* clock divided by 384 */ + upd7810_handle_timer0(cycles, 384); break; case 0x08: /* external signal at TI */ break; @@ -1268,42 +1262,10 @@ void upd7810_device::handle_timers(int cycles) switch (TMM & 0x60) /* timer 1 clock source */ { case 0x00: /* clock divided by 12 */ - OVC1 += cycles; - while (OVC1 >= 12) - { - OVC1 -= 12; - CNT1++; - if (CNT1 == TM1) - { - CNT1 = 0; - IRR |= INTFT1; - /* timer F/F source is timer 1 ? */ - if (0x01 == (TMM & 0x03)) - { - TO ^= 1; - m_to_func(TO); - } - } - } + upd7810_handle_timer1(cycles, 12); break; case 0x20: /* clock divided by 384 */ - OVC1 += cycles; - while (OVC1 >= 384) - { - OVC1 -= 384; - CNT1++; - if (CNT1 == TM1) - { - CNT1 = 0; - IRR |= INTFT1; - /* timer F/F source is timer 1 ? */ - if (0x01 == (TMM & 0x03)) - { - TO ^= 1; - m_to_func(TO); - } - } - } + upd7810_handle_timer1(cycles, 384); break; case 0x40: /* external signal at TI */ break; @@ -1338,6 +1300,12 @@ void upd7810_device::handle_timers(int cycles) { OVCE -= 12; ECNT++; + /* Interrupt Control Circuit */ + if (ETM0 == ECNT) + IRR |= INTFE0; + if (ETM1 == ECNT) + IRR |= INTFE1; + /* How and When ECNT is Cleared */ switch (ETMM & 0x0c) { case 0x00: /* clear ECNT */ @@ -1353,117 +1321,43 @@ void upd7810_device::handle_timers(int cycles) ECNT = 0; break; } - switch (ETMM & 0x30) + /* Conditions When ECNT Causes a CO0 Output Change */ + if (((0x00 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 */ + /* ((0x10 == (ETMM & 0x30)) prohibited */ + ((0x20 == (ETMM & 0x30)) && (ETM0 == ECNT)) || /* set CO0 if ECNT == ETM0 or at falling CI input */ + ((0x30 == (ETMM & 0x30)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */ { - case 0x00: /* set CO0 if ECNT == ETM0 */ - if (ETM0 == ECNT) - { - switch (EOM & 0x0e) - { - case 0x02: /* toggle CO0 */ - CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2); - break; - case 0x04: /* reset CO0 */ - CO0 = 0; - break; - case 0x08: /* set CO0 */ - CO0 = 1; - break; - } - } - break; - case 0x10: /* prohibited */ - break; - case 0x20: /* set CO0 if ECNT == ETM0 or at falling CI input */ - if (ETM0 == ECNT) - { - switch (EOM & 0x0e) - { - case 0x02: /* toggle CO0 */ - CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2); - break; - case 0x04: /* reset CO0 */ - CO0 = 0; - break; - case 0x08: /* set CO0 */ - CO0 = 1; - break; - } - } - break; - case 0x30: /* latch CO0 if ECNT == ETM0 or ECNT == ETM1 */ - if (ETM0 == ECNT || ETM1 == ECNT) + switch (EOM & 0x0e) { - switch (EOM & 0x0e) - { - case 0x02: /* toggle CO0 */ - CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2); - break; - case 0x04: /* reset CO0 */ - CO0 = 0; - break; - case 0x08: /* set CO0 */ - CO0 = 1; - break; - } + case 0x02: /* toggle CO0 */ + CO0 = (CO0 >> 1) | ((CO0 ^ 2) & 2); + break; + case 0x04: /* reset CO0 */ + CO0 = 0; + break; + case 0x08: /* set CO0 */ + CO0 = 1; + break; } - break; } - switch (ETMM & 0xc0) + /* Conditions When ECNT Causes a CO1 Output Change */ + if (((0x00 == (ETMM & 0xc0)) && (ETM0 == ECNT)) || /* set CO1 if ECNT == ETM0 */ + /* ((0x40 == (ETMM & 0xc0)) prohibited */ + ((0x80 == (ETMM & 0xc0)) && (ETM0 == ECNT)) || /* set CO1 if ECNT == ETM0 or at falling CI input */ + ((0xc0 == (ETMM & 0xc0)) && (ETM0 == ECNT || ETM1 == ECNT))) /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */ { - case 0x00: /* lacth CO1 if ECNT == ETM1 */ - if (ETM1 == ECNT) - { - switch (EOM & 0xe0) - { - case 0x20: /* toggle CO1 */ - CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2); - break; - case 0x40: /* reset CO1 */ - CO1 = 0; - break; - case 0x80: /* set CO1 */ - CO1 = 1; - break; - } - } - break; - case 0x40: /* prohibited */ - break; - case 0x80: /* latch CO1 if ECNT == ETM1 or falling edge of CI input */ - if (ETM1 == ECNT) + switch (EOM & 0xe0) { - switch (EOM & 0xe0) - { - case 0x20: /* toggle CO1 */ - CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2); - break; - case 0x40: /* reset CO1 */ - CO1 = 0; - break; - case 0x80: /* set CO1 */ - CO1 = 1; - break; - } - } - break; - case 0xc0: /* latch CO1 if ECNT == ETM0 or ECNT == ETM1 */ - if (ETM0 == ECNT || ETM1 == ECNT) - { - switch (EOM & 0xe0) - { - case 0x20: /* toggle CO1 */ - CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2); - break; - case 0x40: /* reset CO1 */ - CO1 = 0; - break; - case 0x80: /* set CO1 */ - CO1 = 1; - break; - } + case 0x20: /* toggle CO1 */ + CO1 = (CO1 >> 1) | ((CO1 ^ 2) & 2); + break; + case 0x40: /* reset CO1 */ + CO1 = 0; + break; + case 0x80: /* set CO1 */ + CO1 = 1; + break; } - break; } } } @@ -1508,6 +1402,7 @@ void upd7810_device::handle_timers(int cycles) else m_adtot = 192; m_adout = 0; + m_shdone = 0; if (ANM & 0x01) { /* select mode */ @@ -1524,62 +1419,70 @@ void upd7810_device::handle_timers(int cycles) if (ANM & 0x01) { /* select mode */ - while (m_adcnt > m_adtot) + if (m_shdone == 0) { - UINT8 cr = 0; - m_adcnt -= m_adtot; switch (m_adin) { - case 0: cr = m_an0_func(); break; - case 1: cr = m_an1_func(); break; - case 2: cr = m_an2_func(); break; - case 3: cr = m_an3_func(); break; - case 4: cr = m_an4_func(); break; - case 5: cr = m_an5_func(); break; - case 6: cr = m_an6_func(); break; - case 7: cr = m_an7_func(); break; + case 0: m_tmpcr = m_an0_func(); break; + case 1: m_tmpcr = m_an1_func(); break; + case 2: m_tmpcr = m_an2_func(); break; + case 3: m_tmpcr = m_an3_func(); break; + case 4: m_tmpcr = m_an4_func(); break; + case 5: m_tmpcr = m_an5_func(); break; + case 6: m_tmpcr = m_an6_func(); break; + case 7: m_tmpcr = m_an7_func(); break; } + m_shdone = 1; + } + if (m_adcnt > m_adtot) + { + m_adcnt -= m_adtot; switch (m_adout) { - case 0: CR0 = cr; break; - case 1: CR1 = cr; break; - case 2: CR2 = cr; break; - case 3: CR3 = cr; break; + case 0: CR0 = m_tmpcr; break; + case 1: CR1 = m_tmpcr; break; + case 2: CR2 = m_tmpcr; break; + case 3: CR3 = m_tmpcr; break; } - m_adout = (m_adout + 1) & 0x07; + m_adout = (m_adout + 1) & 0x03; if (m_adout == 0) IRR |= INTFAD; + m_shdone = 0; } } else { /* scan mode */ - while (m_adcnt > m_adtot) + if (m_shdone == 0) { - UINT8 cr = 0; - m_adcnt -= m_adtot; switch (m_adin | m_adrange) { - case 0: cr = m_an0_func(); break; - case 1: cr = m_an1_func(); break; - case 2: cr = m_an2_func(); break; - case 3: cr = m_an3_func(); break; - case 4: cr = m_an4_func(); break; - case 5: cr = m_an5_func(); break; - case 6: cr = m_an6_func(); break; - case 7: cr = m_an7_func(); break; + case 0: m_tmpcr = m_an0_func(); break; + case 1: m_tmpcr = m_an1_func(); break; + case 2: m_tmpcr = m_an2_func(); break; + case 3: m_tmpcr = m_an3_func(); break; + case 4: m_tmpcr = m_an4_func(); break; + case 5: m_tmpcr = m_an5_func(); break; + case 6: m_tmpcr = m_an6_func(); break; + case 7: m_tmpcr = m_an7_func(); break; } + m_shdone = 1; + } + if (m_adcnt > m_adtot) + { + m_adcnt -= m_adtot; switch (m_adout) { - case 0: CR0 = cr; break; - case 1: CR1 = cr; break; - case 2: CR2 = cr; break; - case 3: CR3 = cr; break; + case 0: CR0 = m_tmpcr; break; + case 1: CR1 = m_tmpcr; break; + case 2: CR2 = m_tmpcr; break; + case 3: CR3 = m_tmpcr; break; } m_adin = (m_adin + 1) & 0x07; - m_adout = (m_adout + 1) & 0x07; + m_adout = (m_adout + 1) & 0x03; if (m_adout == 0) IRR |= INTFAD; + m_shdone = 0; } } @@ -1902,6 +1805,8 @@ void upd7810_device::device_reset() m_edges = 0; m_adcnt = 0; m_adtot = 0; + m_tmpcr = 0; + m_shdone = 0; m_adout = 0; m_adin = 0; m_adrange = 0; |
