diff options
author | AJR <ajrhacker@users.noreply.github.com> | 2021-03-15 14:26:11 -0400 |
---|---|---|
committer | AJR <ajrhacker@users.noreply.github.com> | 2021-03-15 14:27:23 -0400 |
commit | 9a29c3be6a48fc189003a7ed2f386eb79a3fb5ea (patch) | |
tree | 6251e2cda9ac18ea504d02b85011fab62e2c7877 | |
parent | 6cb15599912c1d0d20b15f9d7ae6417f360d193d (diff) |
i186: Timer updates
- Implement retrigger mode
- Clean up code a little, removing redundant "active_count" flag
- Modernize save state registration
-rw-r--r-- | src/devices/cpu/i86/i186.cpp | 106 | ||||
-rw-r--r-- | src/devices/cpu/i86/i186.h | 7 |
2 files changed, 53 insertions, 60 deletions
diff --git a/src/devices/cpu/i86/i186.cpp b/src/devices/cpu/i86/i186.cpp index ee0500e0fc9..d1c87e1cd4d 100644 --- a/src/devices/cpu/i86/i186.cpp +++ b/src/devices/cpu/i86/i186.cpp @@ -634,27 +634,14 @@ void i80186_cpu_device::device_start() state_add( I80186_POLLSTS, "POLLSTS", m_intr.poll_status ).formatstr("%04X"); // register for savestates - save_item(NAME(m_timer[0].control)); - save_item(NAME(m_timer[0].maxA)); - save_item(NAME(m_timer[0].maxB)); - save_item(NAME(m_timer[0].active_count)); - save_item(NAME(m_timer[0].count)); - save_item(NAME(m_timer[1].control)); - save_item(NAME(m_timer[1].maxA)); - save_item(NAME(m_timer[1].maxB)); - save_item(NAME(m_timer[1].active_count)); - save_item(NAME(m_timer[1].count)); - save_item(NAME(m_timer[2].control)); - save_item(NAME(m_timer[2].maxA)); - save_item(NAME(m_timer[2].count)); - save_item(NAME(m_dma[0].source)); - save_item(NAME(m_dma[0].dest)); - save_item(NAME(m_dma[0].count)); - save_item(NAME(m_dma[0].control)); - save_item(NAME(m_dma[1].source)); - save_item(NAME(m_dma[1].dest)); - save_item(NAME(m_dma[1].count)); - save_item(NAME(m_dma[1].control)); + save_item(STRUCT_MEMBER(m_timer, control)); + save_item(STRUCT_MEMBER(m_timer, maxA)); + save_item(STRUCT_MEMBER(m_timer, maxB)); + save_item(STRUCT_MEMBER(m_timer, count)); + save_item(STRUCT_MEMBER(m_dma, source)); + save_item(STRUCT_MEMBER(m_dma, dest)); + save_item(STRUCT_MEMBER(m_dma, count)); + save_item(STRUCT_MEMBER(m_dma, control)); save_item(NAME(m_intr.vector)); save_item(NAME(m_intr.pending)); save_item(NAME(m_intr.ack_mask)); @@ -732,7 +719,6 @@ void i80186_cpu_device::device_reset() elem.control = 0; elem.maxA = 0; elem.maxB = 0; - elem.active_count = false; elem.count = 0; } } @@ -1260,36 +1246,21 @@ void i80186_cpu_device::device_timer(emu_timer &timer, device_timer_id id, int p else { if(which) - m_out_tmrout1_func(t->active_count); + m_out_tmrout1_func((t->control & 0x1000) ? 1 : 0); else - m_out_tmrout0_func(t->active_count); + m_out_tmrout0_func((t->control & 0x1000) ? 1 : 0); } } /* if we're continuous or altcounting, reset */ - if((t->control & 1) || ((t->control & 2) && (which != 2) && !t->active_count)) + if((t->control & 1) || ((t->control & 2) && !(t->control & 0x1000))) { - int count; - if((t->control & 2) && (which != 2)) - { - count = t->active_count ? t->maxA : t->maxB; - if(!t->active_count) - { - t->active_count = 1; - t->control |= 0x1000; - } - else - { - t->active_count = 0; - t->control &= ~0x1000; - } - } + if((t->control & 2) && !(t->control & 0x1000)) + t->control |= 0x1000; else - count = t->maxA; + t->control &= ~0x1000; - count = count ? count : 0x10000; - if(!(t->control & 4)) - t->int_timer->adjust((attotime::from_hz(clock()/8) * count), which); + restart_timer(which); if (LOG_TIMER) logerror(" Repriming interrupt\n"); } else @@ -1307,13 +1278,21 @@ void i80186_cpu_device::device_timer(emu_timer &timer, device_timer_id id, int p } +void i80186_cpu_device::restart_timer(int which) +{ + timer_state *t = &m_timer[which]; + int count = (t->control & 0x1000) ? t->maxB : t->maxA; + if(!(t->control & 4)) + t->int_timer->adjust((attotime::from_hz(clock()/8) * (count ? count : 0x10000)), which); +} + void i80186_cpu_device::internal_timer_sync(int which) { timer_state *t = &m_timer[which]; /* if we have a timing timer running, adjust the count */ - if ((t->control & 0x8000) && !(t->control & 0x0c)) - t->count = (((which != 2) && t->active_count) ? t->maxB : t->maxA) - t->int_timer->remaining().as_ticks(clock() / 8); + if ((t->control & 0x8000) && !(t->control & 0x0c) && t->int_timer->enabled()) + t->count = ((t->control & 0x1000) ? t->maxB : t->maxA) - t->int_timer->remaining().as_ticks(clock() / 8); } void i80186_cpu_device::inc_timer(int which) @@ -1323,7 +1302,7 @@ void i80186_cpu_device::inc_timer(int which) t->count++; if (t->control & 2) { - if (t->count == (t->active_count ? t->maxB : t->maxA)) + if (t->count == ((t->control & 0x1000) ? t->maxB : t->maxA)) device_timer(*t->int_timer, which, which, nullptr); } else if (t->count == t->maxA) @@ -1386,7 +1365,6 @@ void i80186_cpu_device::internal_timer_update(int which, int new_count, int new_ /* handle control changes */ if (new_control != -1) { - int diff; uint16_t resbits = (which == 2) ? 0x1fde : 0x1fc0; /* merge back in the bits we don't modify */ @@ -1397,12 +1375,8 @@ void i80186_cpu_device::internal_timer_update(int which, int new_count, int new_ new_control = (new_control & ~0x8000) | (t->control & 0x8000); new_control &= ~0x4000; - /* check for control bits we don't handle */ - diff = new_control ^ t->control; - if (diff & 0x0010) - logerror("%05X:ERROR! -unsupported timer mode %04X\n", m_pc, new_control); - /* if we have real changes, update things */ + uint16_t diff = new_control ^ t->control; if (diff != 0) { /* if we're going off, make sure our timers are gone */ @@ -1427,6 +1401,10 @@ void i80186_cpu_device::internal_timer_update(int which, int new_count, int new_ } } + /* RIU is cleared whenever ALT = 0 */ + if (!(new_control & 0x0002)) + new_control &= ~0x1000; + /* set the new control register */ t->control = new_control; } @@ -1434,11 +1412,9 @@ void i80186_cpu_device::internal_timer_update(int which, int new_count, int new_ /* update the interrupt timer */ if (update_int_timer) { - t->active_count = 0; - t->control &= ~0x1000; - if ((t->control & 0x8000) && !(t->control & 4)) + if ((t->control & 0x8004) == 0x8000 && (!(t->control & 0x10) || t->int_timer->enabled())) { - int diff = t->maxA - t->count; + int diff = ((t->control & 0x1000) ? t->maxB : t->maxA) - t->count; if (diff <= 0) diff += 0x10000; t->int_timer->adjust(attotime::from_hz(clock()/8) * diff, which); @@ -1451,6 +1427,22 @@ void i80186_cpu_device::internal_timer_update(int which, int new_count, int new_ } } +void i80186_cpu_device::external_tmrin(int which, int state) +{ + // TODO: make this an actual edge trigger + if (state) + { + if ((m_timer[which].control & 0x8004) == 0x8004) + inc_timer(which); + else if ((m_timer[which].control & 0x8014) == 0x8010) + { + m_timer[which].count = 0; + restart_timer(which); + if (LOG_TIMER) logerror("Retriggered timer %d\n", which); + } + } +} + /************************************* diff --git a/src/devices/cpu/i86/i186.h b/src/devices/cpu/i86/i186.h index f1bd6aa91b5..1ef28afca6e 100644 --- a/src/devices/cpu/i86/i186.h +++ b/src/devices/cpu/i86/i186.h @@ -27,8 +27,8 @@ public: IRQ_CALLBACK_MEMBER(inta_callback); DECLARE_WRITE_LINE_MEMBER(drq0_w) { m_dma[0].drq_state = state; } DECLARE_WRITE_LINE_MEMBER(drq1_w) { m_dma[1].drq_state = state; } - DECLARE_WRITE_LINE_MEMBER(tmrin0_w) { if(state && (m_timer[0].control & 0x8004) == 0x8004) { inc_timer(0); } } - DECLARE_WRITE_LINE_MEMBER(tmrin1_w) { if(state && (m_timer[1].control & 0x8004) == 0x8004) { inc_timer(1); } } + DECLARE_WRITE_LINE_MEMBER(tmrin0_w) { external_tmrin(0, state); } + DECLARE_WRITE_LINE_MEMBER(tmrin1_w) { external_tmrin(1, state); } DECLARE_WRITE_LINE_MEMBER(int0_w) { external_int(0, state); } DECLARE_WRITE_LINE_MEMBER(int1_w) { external_int(1, state); } DECLARE_WRITE_LINE_MEMBER(int2_w) { external_int(2, state); } @@ -86,8 +86,10 @@ private: void update_interrupt_state(); void handle_eoi(int data); void external_int(uint16_t intno, int state); + void restart_timer(int which); void internal_timer_sync(int which); void internal_timer_update(int which, int new_count, int new_maxA, int new_maxB, int new_control); + void external_tmrin(int which, int state); void update_dma_control(int which, int new_control); void drq_callback(int which); void inc_timer(int which); @@ -108,7 +110,6 @@ private: uint16_t control; uint16_t maxA; uint16_t maxB; - bool active_count; uint16_t count; emu_timer *int_timer; }; |