summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit9a29c3be6a48fc189003a7ed2f386eb79a3fb5ea (patch)
tree6251e2cda9ac18ea504d02b85011fab62e2c7877
parent6cb15599912c1d0d20b15f9d7ae6417f360d193d (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.cpp106
-rw-r--r--src/devices/cpu/i86/i186.h7
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;
};