summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2018-03-03 13:46:36 -0500
committer AJR <ajrhacker@users.noreply.github.com>2018-03-03 13:46:46 -0500
commit6228bbe9422f2e2f2841699e07fe0615c97f0561 (patch)
tree322ce63bf4e21d88489dcf7a6640ccc761c961e7
parent6d854de3e54099654877f675f8577483e74d079f (diff)
pit8253: Counters are now subdevices
-rw-r--r--src/devices/machine/pit8253.cpp907
-rw-r--r--src/devices/machine/pit8253.h184
2 files changed, 523 insertions, 568 deletions
diff --git a/src/devices/machine/pit8253.cpp b/src/devices/machine/pit8253.cpp
index 5719b6289dd..94a99ff6fc4 100644
--- a/src/devices/machine/pit8253.cpp
+++ b/src/devices/machine/pit8253.cpp
@@ -23,13 +23,6 @@
#include "emu.h"
#include "machine/pit8253.h"
-/* device types */
-enum
-{
- TYPE_PIT8253 = 0,
- TYPE_PIT8254
-};
-
/***************************************************************************
@@ -42,138 +35,148 @@ enum
#define LOG1(msg) do { if (VERBOSE >= 1) logerror msg; } while (0)
#define LOG2(msg) do { if (VERBOSE >= 2) logerror msg; } while (0)
-
+DEFINE_DEVICE_TYPE(PIT_COUNTER, pit_counter_device, "pit_counter", "PIT Counter")
DEFINE_DEVICE_TYPE(PIT8253, pit8253_device, "pit8253", "Intel 8253 PIT")
DEFINE_DEVICE_TYPE(PIT8254, pit8254_device, "pit8254", "Intel 8254 PIT")
DEFINE_DEVICE_TYPE(FE2010_PIT, fe2010_pit_device, "fe2010_pit", "Faraday FE2010 PIT")
+pit_counter_device::pit_counter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, PIT_COUNTER, tag, owner, clock)
+{
+}
+
pit8253_device::pit8253_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- pit8253_device(mconfig, PIT8253, tag, owner, clock, I8253)
+ pit8253_device(mconfig, PIT8253, tag, owner, clock, pit_type::I8253)
{
}
-pit8253_device::pit8253_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int chip_type) :
+pit8253_device::pit8253_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, pit_type chip_type) :
device_t(mconfig, type, tag, owner, clock),
- m_clk0(0),
- m_clk1(0),
- m_clk2(0),
- m_out0_handler(*this),
- m_out1_handler(*this),
- m_out2_handler(*this),
+ m_clk{0, 0, 0},
+ m_out_handler{{*this}, {*this}, {*this}},
+ m_counter(*this, "counter%u", 0U),
m_type(chip_type)
{
}
pit8254_device::pit8254_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- pit8253_device(mconfig, PIT8254, tag, owner, clock, I8254)
+ pit8253_device(mconfig, PIT8254, tag, owner, clock, pit_type::I8254)
{
}
fe2010_pit_device::fe2010_pit_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- pit8253_device(mconfig, FE2010_PIT, tag, owner, clock, FE2010)
+ pit8253_device(mconfig, FE2010_PIT, tag, owner, clock, pit_type::FE2010)
{
}
-pit8253_device::pit8253_timer *pit8253_device::get_timer(int which)
-{
- which &= 3;
- if (which < PIT8253_MAX_TIMER)
- return &m_timers[which];
+//-------------------------------------------------
+// device_add_mconfig - add device configuration
+//-------------------------------------------------
- return nullptr;
-}
+MACHINE_CONFIG_START(pit8253_device::device_add_mconfig)
+ MCFG_DEVICE_ADD("counter0", PIT_COUNTER, 0)
+ MCFG_DEVICE_ADD("counter1", PIT_COUNTER, 0)
+ MCFG_DEVICE_ADD("counter2", PIT_COUNTER, 0)
+MACHINE_CONFIG_END
//-------------------------------------------------
-// device_start - device-specific startup
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
//-------------------------------------------------
-void pit8253_device::device_start()
+void pit8253_device::device_resolve_objects()
{
- m_timers[0].clockin = m_clk0;
- m_timers[1].clockin = m_clk1;
- m_timers[2].clockin = m_clk2;
-
- m_out0_handler.resolve_safe();
- m_out1_handler.resolve_safe();
- m_out2_handler.resolve_safe();
-
- for (int timerno = 0; timerno < PIT8253_MAX_TIMER; timerno++)
+ for (int timer = 0; timer < 3; timer++)
{
- pit8253_timer *timer = get_timer(timerno);
-
- /* initialize timer */
- timer->updatetimer = timer_alloc(timerno);
- timer->updatetimer->adjust(attotime::never, timerno);
-
- /* set up state save values */
- save_item(NAME(timer->clockin), timerno);
- save_item(NAME(timer->control), timerno);
- save_item(NAME(timer->status), timerno);
- save_item(NAME(timer->lowcount), timerno);
- save_item(NAME(timer->latch), timerno);
- save_item(NAME(timer->count), timerno);
- save_item(NAME(timer->value), timerno);
- save_item(NAME(timer->wmsb), timerno);
- save_item(NAME(timer->rmsb), timerno);
- save_item(NAME(timer->output), timerno);
- save_item(NAME(timer->gate), timerno);
- save_item(NAME(timer->latched_count), timerno);
- save_item(NAME(timer->latched_status), timerno);
- save_item(NAME(timer->null_count), timerno);
- save_item(NAME(timer->phase), timerno);
- save_item(NAME(timer->last_updated), timerno);
- save_item(NAME(timer->clock), timerno);
-
- /* zerofill */
- timer->gate = 1;
- timer->phase = 0;
- timer->clock = 0;
-
- timer->index = timerno;
- timer->control = timer->status = 0x30;
- timer->rmsb = timer->wmsb = 0;
- timer->count = timer->value = timer->latch = 0;
- timer->lowcount = 0;
-
- timer->output = 0;
- timer->latched_count = 0;
- timer->latched_status = 0;
- timer->null_count = 1;
-
- timer->last_updated = machine().time();
+ m_out_handler[timer].resolve_safe();
+ m_counter[timer]->m_index = timer;
+ m_counter[timer]->m_clockin = m_clk[timer];
}
}
//-------------------------------------------------
-// device_reset - device-specific reset
+// device_start - device-specific startup
//-------------------------------------------------
-void pit8253_device::device_reset()
+void pit_counter_device::device_start()
{
- for (int i = 0; i < PIT8253_MAX_TIMER; i++)
- {
- pit8253_timer *timer = get_timer(i);
+ /* initialize timer */
+ m_updatetimer = timer_alloc();
+ m_updatetimer->adjust(attotime::never);
+
+ /* set up state save values */
+ save_item(NAME(m_clockin));
+ save_item(NAME(m_control));
+ save_item(NAME(m_status));
+ save_item(NAME(m_lowcount));
+ save_item(NAME(m_latch));
+ save_item(NAME(m_count));
+ save_item(NAME(m_value));
+ save_item(NAME(m_wmsb));
+ save_item(NAME(m_rmsb));
+ save_item(NAME(m_output));
+ save_item(NAME(m_gate));
+ save_item(NAME(m_latched_count));
+ save_item(NAME(m_latched_status));
+ save_item(NAME(m_null_count));
+ save_item(NAME(m_phase));
+ save_item(NAME(m_last_updated));
+ save_item(NAME(m_clock_signal));
+
+ /* zerofill */
+ m_gate = 1;
+ m_phase = 0;
+ m_clock_signal = 0;
+
+ m_control = m_status = 0x30;
+ m_rmsb = m_wmsb = false;
+ m_count = m_value = m_latch = 0;
+ m_lowcount = 0;
+
+ m_output = 0;
+ m_latched_count = 0;
+ m_latched_status = 0;
+ m_null_count = 1;
+
+ m_last_updated = machine().time();
+}
+
- /* According to Intel's 8254 docs, the state of a timer is undefined
- until the first mode control word is written. Here we define this
- undefined behaviour */
- timer->control = timer->status = 0x30;
- timer->rmsb = timer->wmsb = 0;
- timer->count = timer->value = timer->latch = 0;
- timer->lowcount = 0;
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
- timer->output = 2; /* output is undetermined */
- timer->latched_count = 0;
- timer->latched_status = 0;
- timer->null_count = 1;
+void pit8253_device::device_start()
+{
+}
- timer->last_updated = machine().time();
- update(timer);
- }
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void pit_counter_device::device_reset()
+{
+ /* According to Intel's 8254 docs, the state of a timer is undefined
+ until the first mode control word is written. Here we define this
+ undefined behaviour */
+ m_control = m_status = 0x30;
+ m_rmsb = m_wmsb = false;
+ m_count = m_value = m_latch = 0;
+ m_lowcount = 0;
+
+ m_output = 2; /* output is undetermined */
+ m_latched_count = 0;
+ m_latched_status = 0;
+ m_null_count = 1;
+
+ m_last_updated = machine().time();
+
+ update();
}
@@ -188,9 +191,11 @@ void pit8253_device::device_reset()
#define CTRL_BCD(control) (((control) >> 0) & 0x01)
-inline uint32_t pit8253_device::adjusted_count(int bcd, uint16_t val)
+inline uint32_t pit_counter_device::adjusted_count() const
{
- if (!bcd)
+ uint16_t val = m_value;
+
+ if (!CTRL_BCD(m_control))
return (val == 0) ? 0x10000 : val;
else if (val == 0)
return 10000;
@@ -212,25 +217,21 @@ inline uint32_t pit8253_device::adjusted_count(int bcd, uint16_t val)
}
-/* This function subtracts 1 from timer->value "cycles" times, taking into
+/* This function subtracts 1 from m_value "cycles" times, taking into
account binary or BCD operation, and wrapping around from 0 to 0xFFFF or
0x9999 as necessary. */
-void pit8253_device::decrease_counter_value(pit8253_timer *timer, int64_t cycles)
+void pit_counter_device::decrease_counter_value(int64_t cycles)
{
- uint16_t value;
- uint8_t units, tens, hundreds, thousands;
-
- if (CTRL_BCD(timer->control) == 0)
+ if (CTRL_BCD(m_control) == 0)
{
- timer->value -= (cycles & 0xffff);
+ m_value -= (cycles & 0xffff);
return;
}
- value = timer->value;
- units = value & 0xf;
- tens = (value >> 4) & 0xf;
- hundreds = (value >> 8) & 0xf;
- thousands = (value >> 12) & 0xf;
+ uint8_t units = m_value & 0xf;
+ uint8_t tens = (m_value >> 4) & 0xf;
+ uint8_t hundreds = (m_value >> 8) & 0xf;
+ uint8_t thousands = (m_value >> 12) & 0xf;
if (cycles <= units)
{
@@ -266,58 +267,45 @@ void pit8253_device::decrease_counter_value(pit8253_timer *timer, int64_t cycles
}
}
- timer->value = (thousands << 12) | (hundreds << 8) | (tens << 4) | units;
+ m_value = (thousands << 12) | (hundreds << 8) | (tens << 4) | units;
}
/* Counter loading: transfer of a count from the CR to the CE */
-void pit8253_device::load_counter_value(pit8253_timer *timer)
+void pit_counter_device::load_counter_value()
{
- timer->value = timer->count;
- timer->null_count = 0;
+ m_value = m_count;
+ m_null_count = 0;
- if (CTRL_MODE(timer->control) == 3 && timer->output == 0)
- timer->value &= 0xfffe;
+ if (CTRL_MODE(m_control) == 3 && m_output == 0)
+ m_value &= 0xfffe;
}
-void pit8253_device::set_output(pit8253_timer *timer, int output)
+void pit_counter_device::set_output(int output)
{
- if (output != timer->output)
+ if (output != m_output)
{
- timer->output = output;
- LOG2(("set_output(): timer %d, %s\n", timer->index, output ? "low to high" : "high to low"));
+ m_output = output;
+ LOG2(("set_output(): %s\n", output ? "low to high" : "high to low"));
- switch (timer->index)
- {
- case 0:
- m_out0_handler(output);
- break;
-
- case 1:
- m_out1_handler(output);
- break;
-
- case 2:
- m_out2_handler(output);
- break;
- }
+ downcast<pit8253_device *>(owner())->m_out_handler[m_index](output);
}
}
/* This emulates timer "timer" for "elapsed_cycles" cycles and assumes no
callbacks occur during that time. */
-void pit8253_device::simulate2(pit8253_timer *timer, int64_t elapsed_cycles)
+void pit_counter_device::simulate2(int64_t elapsed_cycles)
{
uint32_t adjusted_value;
- int bcd = CTRL_BCD(timer->control);
- int mode = CTRL_MODE(timer->control);
+ int bcd = CTRL_BCD(m_control);
+ int mode = CTRL_MODE(m_control);
static const uint32_t CYCLES_NEVER = (0xffffffff);
uint32_t cycles_to_output = 0;
- LOG2(("simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x\n",
- (int)elapsed_cycles, timer->index, mode, bcd, timer->phase, timer->gate, timer->output, timer->value));
+ LOG2(("simulate2(): simulating %d cycles in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x\n",
+ (int)elapsed_cycles, mode, bcd, m_phase, m_gate, m_output, m_value));
switch (mode)
{
@@ -341,49 +329,49 @@ void pit8253_device::simulate2(pit8253_timer *timer, int64_t elapsed_cycles)
Gate level sensitive only. Low disables counting, high enables it. */
- if (timer->phase == 0)
+ if (m_phase == 0)
{
cycles_to_output = CYCLES_NEVER;
}
else
{
- if (elapsed_cycles >= 0 && timer->phase == 1)
+ if (elapsed_cycles >= 0 && m_phase == 1)
{
/* Counter load cycle */
if (elapsed_cycles > 0)
{
--elapsed_cycles;
- timer->phase = 2;
+ m_phase = 2;
}
- load_counter_value(timer);
+ load_counter_value();
}
- if (timer->gate == 0)
+ if (m_gate == 0)
{
cycles_to_output = CYCLES_NEVER;
}
else
{
- if (timer->phase == 2)
+ if (m_phase == 2)
{
- adjusted_value = adjusted_count(bcd, timer->value);
+ adjusted_value = adjusted_count();
if (elapsed_cycles >= adjusted_value)
{
/* Counter wrapped, output goes high */
elapsed_cycles -= adjusted_value;
- timer->phase = 3;
- timer->value = 0;
- set_output(timer, 1);
+ m_phase = 3;
+ m_value = 0;
+ set_output(1);
}
}
- decrease_counter_value(timer, elapsed_cycles);
+ decrease_counter_value(elapsed_cycles);
- switch (timer->phase)
+ switch (m_phase)
{
case 1: cycles_to_output = 1; break;
- case 2: cycles_to_output = adjusted_count(bcd, timer->value); break;
- case 3: cycles_to_output = adjusted_count(bcd, timer->value); break;
+ case 2: cycles_to_output = adjusted_count(); break;
+ case 3: cycles_to_output = adjusted_count(); break;
}
}
}
@@ -411,35 +399,35 @@ void pit8253_device::simulate2(pit8253_timer *timer, int64_t elapsed_cycles)
Gate rising-edge sensitive only.
Rising edge initiates counting and resets output after next clock. */
- if (elapsed_cycles >= 0 && timer->phase == 1)
+ if (elapsed_cycles >= 0 && m_phase == 1)
{
/* Counter load cycle, output goes low */
if (elapsed_cycles > 0)
{
--elapsed_cycles;
- timer->phase = 2;
+ m_phase = 2;
}
- load_counter_value(timer);
- set_output(timer, 0);
+ load_counter_value();
+ set_output(0);
}
- if (timer->phase == 2)
+ if (m_phase == 2)
{
- adjusted_value = adjusted_count(bcd, timer->value);
+ adjusted_value = adjusted_count();
if (elapsed_cycles >= adjusted_value)
{
/* Counter wrapped, output goes high */
- timer->phase = 3;
- set_output(timer, 1);
+ m_phase = 3;
+ set_output(1);
}
}
- decrease_counter_value(timer, elapsed_cycles);
+ decrease_counter_value(elapsed_cycles);
- switch (timer->phase)
+ switch (m_phase)
{
case 1: cycles_to_output = 1; break;
- case 2: cycles_to_output = adjusted_count(bcd, timer->value); break;
+ case 2: cycles_to_output = adjusted_count(); break;
default: cycles_to_output = CYCLES_NEVER; break;
}
break;
@@ -470,57 +458,57 @@ void pit8253_device::simulate2(pit8253_timer *timer, int64_t elapsed_cycles)
Rising-edge reloads count and initiates counting
Gate high enables counting. */
- if (timer->gate == 0 || timer->phase == 0)
+ if (m_gate == 0 || m_phase == 0)
{
/* Gate low or mode control write forces output high */
- set_output(timer, 1);
+ set_output(1);
cycles_to_output = CYCLES_NEVER;
}
else
{
- if (elapsed_cycles >= 0 && timer->phase == 1)
+ if (elapsed_cycles >= 0 && m_phase == 1)
{
if (elapsed_cycles > 0)
{
--elapsed_cycles;
- timer->phase = 2;
+ m_phase = 2;
}
- load_counter_value(timer);
+ load_counter_value();
}
- adjusted_value = adjusted_count(bcd, timer->value);
+ adjusted_value = adjusted_count();
do
{
- if (timer->phase == 2)
+ if (m_phase == 2)
{
if (elapsed_cycles + 1 >= adjusted_value)
{
/* Counter hits 1, output goes low */
- timer->phase = 3;
- set_output(timer, 0);
+ m_phase = 3;
+ set_output(0);
}
}
- if (elapsed_cycles > 0 && timer->phase == 3)
+ if (elapsed_cycles > 0 && m_phase == 3)
{
/* Reload counter, output goes high */
elapsed_cycles -= adjusted_value;
- timer->phase = 2;
- load_counter_value(timer);
- adjusted_value = adjusted_count(bcd, timer->value);
- set_output(timer, 1);
+ m_phase = 2;
+ load_counter_value();
+ adjusted_value = adjusted_count();
+ set_output(1);
}
}
while (elapsed_cycles >= adjusted_value);
/* Calculate counter value */
- decrease_counter_value(timer, elapsed_cycles);
+ decrease_counter_value(elapsed_cycles);
- switch (timer->phase)
+ switch (m_phase)
{
case 1: cycles_to_output = 1; break;
- default: cycles_to_output = (timer->value == 1) ? 1 : (adjusted_count(bcd, timer->value) - 1); break;
+ default: cycles_to_output = (m_value == 1) ? 1 : (adjusted_count() - 1); break;
}
}
break;
@@ -550,62 +538,62 @@ void pit8253_device::simulate2(pit8253_timer *timer, int64_t elapsed_cycles)
Rising-edge reloads count and initiates counting
Gate high enables counting. */
- if (timer->gate == 0 || timer->phase == 0)
+ if (m_gate == 0 || m_phase == 0)
{
/* Gate low or mode control write forces output high */
- set_output(timer, 1);
+ set_output(1);
cycles_to_output = CYCLES_NEVER;
- if(m_type == FE2010)
- load_counter_value(timer);
+ if (downcast<pit8253_device *>(owner())->m_type == pit_type::FE2010)
+ load_counter_value();
}
else
{
- if (elapsed_cycles >= 0 && timer->phase == 1)
+ if (elapsed_cycles >= 0 && m_phase == 1)
{
if (elapsed_cycles > 0)
{
--elapsed_cycles;
- timer->phase = 2;
+ m_phase = 2;
}
- load_counter_value(timer);
+ load_counter_value();
}
if (elapsed_cycles > 0)
{
- adjusted_value = adjusted_count(bcd, timer->value);
+ adjusted_value = adjusted_count();
do
{
- if (timer->phase == 2 && elapsed_cycles >= ((adjusted_value + 1) >> 1))
+ if (m_phase == 2 && elapsed_cycles >= ((adjusted_value + 1) >> 1))
{
/* High phase expired, output goes low */
elapsed_cycles -= ((adjusted_value + 1) >> 1);
- timer->phase = 3;
- load_counter_value(timer);
- adjusted_value = adjusted_count(bcd, timer->value);
- set_output(timer, 0);
+ m_phase = 3;
+ load_counter_value();
+ adjusted_value = adjusted_count();
+ set_output(0);
}
- if (timer->phase == 3 && elapsed_cycles >= (adjusted_value >> 1))
+ if (m_phase == 3 && elapsed_cycles >= (adjusted_value >> 1))
{
/* Low phase expired, output goes high */
elapsed_cycles -= (adjusted_value >> 1);
- timer->phase = 2;
- load_counter_value(timer);
- adjusted_value = adjusted_count(bcd, timer->value);
- set_output(timer, 1);
+ m_phase = 2;
+ load_counter_value();
+ adjusted_value = adjusted_count();
+ set_output(1);
}
}
- while ((timer->phase == 2 && elapsed_cycles >= ((adjusted_value + 1) >> 1)) ||
- (timer->phase == 3 && elapsed_cycles >= (adjusted_value >> 1)));
+ while ((m_phase == 2 && elapsed_cycles >= ((adjusted_value + 1) >> 1)) ||
+ (m_phase == 3 && elapsed_cycles >= (adjusted_value >> 1)));
- decrease_counter_value(timer, elapsed_cycles * 2);
+ decrease_counter_value(elapsed_cycles * 2);
- switch (timer->phase)
+ switch (m_phase)
{
case 1: cycles_to_output = 1; break;
- case 2: cycles_to_output = (adjusted_count(bcd, timer->value) + 1) >> 1; break;
- case 3: cycles_to_output = adjusted_count(bcd, timer->value) >> 1; break;
+ case 2: cycles_to_output = (adjusted_count() + 1) >> 1; break;
+ case 3: cycles_to_output = adjusted_count() >> 1; break;
}
}
}
@@ -638,112 +626,111 @@ void pit8253_device::simulate2(pit8253_timer *timer, int64_t elapsed_cycles)
Mode 4 only: Gate level sensitive only. Low disables counting, high enables it.
Mode 5 only: Gate rising-edge sensitive only. Rising edge initiates counting */
- if (timer->gate == 0 && mode == 4)
+ if (m_gate == 0 && mode == 4)
{
cycles_to_output = CYCLES_NEVER;
}
else
{
- if (elapsed_cycles >= 0 && timer->phase == 1)
+ if (elapsed_cycles >= 0 && m_phase == 1)
{
if (elapsed_cycles > 0)
{
--elapsed_cycles;
- timer->phase = 2;
+ m_phase = 2;
}
- load_counter_value(timer);
+ load_counter_value();
}
- if (timer->value == 0 && timer->phase == 2)
+ if (m_value == 0 && m_phase == 2)
adjusted_value = 0;
else
- adjusted_value = adjusted_count(bcd, timer->value);
+ adjusted_value = adjusted_count();
- if (timer->phase == 2 && elapsed_cycles >= adjusted_value)
+ if (m_phase == 2 && elapsed_cycles >= adjusted_value)
{
/* Counter has hit zero, set output to low */
elapsed_cycles -= adjusted_value;
- timer->phase = 3;
- timer->value = 0;
- set_output(timer, 0);
+ m_phase = 3;
+ m_value = 0;
+ set_output(0);
}
- if (elapsed_cycles > 0 && timer->phase == 3)
+ if (elapsed_cycles > 0 && m_phase == 3)
{
--elapsed_cycles;
- timer->phase = 0;
- decrease_counter_value(timer, 1);
- set_output(timer, 1);
+ m_phase = 0;
+ decrease_counter_value(1);
+ set_output(1);
}
- decrease_counter_value(timer, elapsed_cycles);
+ decrease_counter_value(elapsed_cycles);
- switch (timer->phase)
+ switch (m_phase)
{
case 1: cycles_to_output = 1; break;
- case 2: cycles_to_output = adjusted_count(bcd, timer->value); break;
+ case 2: cycles_to_output = adjusted_count(); break;
case 3: cycles_to_output = 1; break;
}
}
break;
}
- if (cycles_to_output == CYCLES_NEVER || timer->clockin == 0)
+ if (cycles_to_output == CYCLES_NEVER || m_clockin == 0)
{
- timer->updatetimer->adjust(attotime::never, timer->index);
+ m_updatetimer->adjust(attotime::never);
}
else
{
- attotime next_fire_time = timer->last_updated + cycles_to_output * attotime::from_hz(timer->clockin);
+ attotime next_fire_time = m_last_updated + cycles_to_output * attotime::from_hz(m_clockin);
- timer->updatetimer->adjust(next_fire_time - machine().time(), timer->index);
+ m_updatetimer->adjust(next_fire_time - machine().time());
}
- LOG2(("simulate2(): simulating %d cycles for %d in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x, cycles_to_output = %04x\n",
- (int)elapsed_cycles, timer->index, mode, bcd, timer->phase, timer->gate, timer->output, timer->value, cycles_to_output));
+ LOG2(("simulate2(): simulating %d cycles in mode %d, bcd = %d, phase = %d, gate = %d, output %d, value = 0x%04x, cycles_to_output = %04x\n",
+ (int)elapsed_cycles, mode, bcd, m_phase, m_gate, m_output, m_value, cycles_to_output));
}
/* This emulates timer "timer" for "elapsed_cycles" cycles, broken down into
sections punctuated by callbacks. */
-void pit8253_device::simulate(pit8253_timer *timer, int64_t elapsed_cycles)
+void pit_counter_device::simulate(int64_t elapsed_cycles)
{
if (elapsed_cycles > 0)
- simulate2(timer, elapsed_cycles);
- else if (timer->clockin)
- timer->updatetimer->adjust(attotime::from_hz(timer->clockin), timer->index);
+ simulate2(elapsed_cycles);
+ else if (m_clockin)
+ m_updatetimer->adjust(attotime::from_hz(m_clockin));
}
/* This brings timer "timer" up to date */
-void pit8253_device::update(pit8253_timer *timer)
+void pit_counter_device::update()
{
/* With the 82C54's maximum clockin of 10MHz, 64 bits is nearly 60,000
years of time. Should be enough for now. */
attotime now = machine().time();
- attotime elapsed_time = now - timer->last_updated;
- int64_t elapsed_cycles = elapsed_time.as_double() * timer->clockin;
+ attotime elapsed_time = now - m_last_updated;
+ int64_t elapsed_cycles = elapsed_time.as_double() * m_clockin;
- LOG2(("update(): timer %d, %d elapsed_cycles\n", timer->index, elapsed_cycles));
+ LOG2(("update(): %d elapsed_cycles\n", elapsed_cycles));
- if (timer->clockin)
- timer->last_updated += elapsed_cycles * attotime::from_hz(timer->clockin);
+ if (m_clockin)
+ m_last_updated += elapsed_cycles * attotime::from_hz(m_clockin);
else
- timer->last_updated = now;
+ m_last_updated = now;
- simulate(timer, elapsed_cycles);
+ simulate(elapsed_cycles);
}
-/* We recycle bit 0 of timer->value to hold the phase in mode 3 when count is
+/* We recycle bit 0 of m_value to hold the phase in mode 3 when count is
odd. Since read commands in mode 3 always return even numbers, we need to
mask this bit off. */
-uint16_t pit8253_device::masked_value(pit8253_timer *timer)
+uint16_t pit_counter_device::masked_value() const
{
- LOG2(("masked_value\n"));
- if ((CTRL_MODE(timer->control) == 3) && (m_type != FE2010))
- return timer->value & 0xfffe;
- return timer->value;
+ if ((CTRL_MODE(m_control) == 3) && (downcast<pit8253_device *>(owner())->m_type != pit_type::FE2010))
+ return m_value & 0xfffe;
+ return m_value;
}
/* Reads only affect the following bits of the counter state:
@@ -751,89 +738,98 @@ uint16_t pit8253_device::masked_value(pit8253_timer *timer)
latched_count
rmsb
so they don't affect any timer operations except other reads. */
-READ8_MEMBER( pit8253_device::read )
+uint8_t pit_counter_device::read()
{
- pit8253_timer *timer = get_timer(offset);
uint8_t data;
- uint16_t value;
- LOG2(("read(): offset %d\n", offset));
+ if (!machine().side_effects_disabled())
+ update();
- if (timer == nullptr)
+ if (m_latched_status)
{
- /* Reading mode control register is illegal according to docs */
- /* Experimentally determined: reading it returns 0 */
- data = 0;
+ /* Read status register (8254 only) */
+ data = m_status;
+ if (!machine().side_effects_disabled())
+ m_latched_status = 0;
}
else
{
- update(timer);
-
- if (timer->latched_status)
+ if (m_latched_count != 0)
{
- /* Read status register (8254 only) */
- data = timer->status;
- timer->latched_status = 0;
+ /* Read back latched count */
+ data = (m_latch >> (m_rmsb ? 8 : 0)) & 0xff;
+ if (!machine().side_effects_disabled())
+ {
+ m_rmsb = !m_rmsb;
+ --m_latched_count;
+ }
}
else
{
- if (timer->latched_count != 0)
- {
- /* Read back latched count */
- data = (timer->latch >> (timer->rmsb ? 8 : 0)) & 0xff;
- timer->rmsb = 1 - timer->rmsb;
- --timer->latched_count;
- }
- else
+ uint16_t value = masked_value();
+
+ /* Read back current count */
+ switch (CTRL_ACCESS(m_control))
{
- value = masked_value(timer);
+ case 0:
+ default:
+ /* This should never happen */
+ data = 0; /* Appease compiler */
+ break;
- /* Read back current count */
- switch (CTRL_ACCESS(timer->control))
- {
- case 0:
- default:
- /* This should never happen */
- data = 0; /* Appease compiler */
- break;
-
- case 1:
- /* read counter bits 0-7 only */
- data = (value >> 0) & 0xff;
- break;
-
- case 2:
- /* read counter bits 8-15 only */
- data = (value >> 8) & 0xff;
- break;
-
- case 3:
- /* read bits 0-7 first, then 8-15 */
-
- // reading back the current count while in the middle of a
- // 16-bit write returns a xor'ed version of the value written
- // (apricot diagnostic timer test tests this)
- if (timer->wmsb)
- data = ~timer->lowcount;
- else
- data = value >> (timer->rmsb ? 8 : 0);
-
- timer->rmsb = 1 - timer->rmsb;
- break;
- }
+ case 1:
+ /* read counter bits 0-7 only */
+ data = (value >> 0) & 0xff;
+ break;
+
+ case 2:
+ /* read counter bits 8-15 only */
+ data = (value >> 8) & 0xff;
+ break;
+
+ case 3:
+ /* read bits 0-7 first, then 8-15 */
+
+ // reading back the current count while in the middle of a
+ // 16-bit write returns a xor'ed version of the value written
+ // (apricot diagnostic timer test tests this)
+ if (m_wmsb)
+ data = ~m_lowcount;
+ else
+ data = value >> (m_rmsb ? 8 : 0);
+
+ if (!machine().side_effects_disabled())
+ m_rmsb = !m_rmsb;
+ break;
}
}
}
- LOG2(("read(): offset=%d data=0x%02x\n", offset, data));
+ LOG2(("read(): data=0x%02x\n", data));
return data;
}
+READ8_MEMBER( pit8253_device::read )
+{
+ offset &= 3;
+
+ LOG2(("read(): offset %d\n", offset));
+
+ if (offset == 3)
+ {
+ /* Reading mode control register is illegal according to docs */
+ /* Experimentally determined: reading it returns 0 */
+ return 0;
+ }
+ else
+ return m_counter[offset]->read();
+}
+
/* Loads a new value from the bus to the count register (CR) */
-void pit8253_device::load_count(pit8253_timer *timer, uint16_t newcount)
+void pit_counter_device::load_count(uint16_t newcount)
{
- int mode = CTRL_MODE(timer->control);
+ int mode = CTRL_MODE(m_control);
LOG1(("load_count(): %04x\n", newcount));
if (newcount == 1)
@@ -846,45 +842,44 @@ void pit8253_device::load_count(pit8253_timer *timer, uint16_t newcount)
newcount = 0;
}
- timer->count = newcount;
+ m_count = newcount;
if (mode == 2 || mode == 3)
{
- if (timer->phase == 0)
- timer->phase = 1;
+ if (m_phase == 0)
+ m_phase = 1;
}
else
{
if (mode == 0 || mode == 4)
- timer->phase = 1;
+ m_phase = 1;
}
}
-void pit8253_device::readback(pit8253_timer *timer, int command)
+void pit_counter_device::readback(int command)
{
- uint16_t value;
- update(timer);
+ update();
if ((command & 1) == 0)
{
/* readback status command */
- if (!timer->latched_status)
+ if (!m_latched_status)
{
- timer->status = (timer->control & 0x3f) | ((timer->output != 0) ? 0x80 : 0) | (timer->null_count ? 0x40 : 0);
- timer->latched_status = 1;
+ m_status = (m_control & 0x3f) | ((m_output != 0) ? 0x80 : 0) | (m_null_count ? 0x40 : 0);
+ m_latched_status = 1;
}
}
/* Experimentally determined: the read latch command seems to have no
effect if we're halfway through a 16-bit read */
- if ((command & 2) == 0 && !timer->rmsb)
+ if ((command & 2) == 0 && !m_rmsb)
{
/* readback count command */
- if (timer->latched_count == 0)
+ if (m_latched_count == 0)
{
- value = masked_value(timer);
- switch (CTRL_ACCESS(timer->control))
+ uint16_t value = masked_value();
+ switch (CTRL_ACCESS(m_control))
{
case 0:
/* This should never happen */
@@ -892,20 +887,20 @@ void pit8253_device::readback(pit8253_timer *timer, int command)
case 1:
/* latch bits 0-7 only */
- timer->latch = ((value << 8) & 0xff00) | (value & 0xff);
- timer->latched_count = 1;
+ m_latch = ((value << 8) & 0xff00) | (value & 0xff);
+ m_latched_count = 1;
break;
case 2:
/* read bits 8-15 only */
- timer->latch = (value & 0xff00) | ((value >> 8) & 0xff);
- timer->latched_count = 1;
+ m_latch = (value & 0xff00) | ((value >> 8) & 0xff);
+ m_latched_count = 1;
break;
case 3:
/* latch all 16 bits */
- timer->latch = value;
- timer->latched_count = 2;
+ m_latch = value;
+ m_latched_count = 2;
break;
}
}
@@ -925,214 +920,168 @@ void pit8254_device::readback_command(uint8_t data)
/* Bit 0 of data must be 0. Todo: find out what the hardware does if it isn't. */
int read_command = (data >> 4) & 3;
- if ((data & 2) != 0)
- readback(get_timer(0), read_command);
- if ((data & 4) != 0)
- readback(get_timer(1), read_command);
- if ((data & 8) != 0)
- readback(get_timer(2), read_command);
+ for (int timer = 0; timer < 3; timer++)
+ if (BIT(data, timer + 1) != 0)
+ m_counter[timer]->readback(read_command);
}
-void pit8253_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+void pit_counter_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
- update(get_timer(id));
+ update();
}
-WRITE8_MEMBER( pit8253_device::write )
+void pit_counter_device::control_w(uint8_t data)
{
- pit8253_timer *timer = get_timer(offset);
-
- LOG2(("write(): offset=%d data=0x%02x\n", offset, data));
+ update();
- if (timer == nullptr)
+ if (CTRL_ACCESS(data) == 0)
{
- /* Write to mode control register */
- timer = get_timer((data >> 6) & 3);
- if (timer == nullptr)
- {
- readback_command(data);
- return;
- }
-
- update(timer);
+ LOG1(("write(): readback\n"));
- if (CTRL_ACCESS(data) == 0)
- {
- LOG1(("write(): timer=%d readback\n", (data >> 6) & 3));
-
- /* Latch current timer value */
- /* Experimentally verified: this command does not affect the mode control register */
- readback(timer, 1);
- }
- else
- {
- LOG1(("write(): timer=%d bytes=%d mode=%d bcd=%d\n", (data >> 6) & 3, (data >> 4) & 3, (data >> 1) & 7, data & 1));
-
- timer->control = (data & 0x3f);
- timer->null_count = 1;
- timer->wmsb = timer->rmsb = 0;
- /* Phase 0 is always the phase after a mode control write */
- timer->phase = 0;
- set_output(timer, CTRL_MODE(timer->control) ? 1 : 0);
- }
+ /* Latch current timer value */
+ /* Experimentally verified: this command does not affect the mode control register */
+ readback(1);
}
else
{
- int middle_of_a_cycle = 0;
+ LOG1(("write(): bytes=%d mode=%d bcd=%d\n", (data >> 4) & 3, (data >> 1) & 7, data & 1));
+
+ m_control = (data & 0x3f);
+ m_null_count = 1;
+ m_wmsb = m_rmsb = false;
+ /* Phase 0 is always the phase after a mode control write */
+ m_phase = 0;
+ set_output(CTRL_MODE(m_control) ? 1 : 0);
+ }
+}
- update(timer);
+void pit_counter_device::count_w(uint8_t data)
+{
+ update();
- if (machine().time() > timer->last_updated && timer->clockin != 0)
- middle_of_a_cycle = 1;
+ bool middle_of_a_cycle = (machine().time() > m_last_updated && m_clockin != 0);
- switch (CTRL_ACCESS(timer->control))
- {
- case 0:
- /* This should never happen */
- break;
+ switch (CTRL_ACCESS(m_control))
+ {
+ case 0:
+ /* This should never happen */
+ break;
- case 1:
- /* read/write counter bits 0-7 only */
+ case 1:
+ /* read/write counter bits 0-7 only */
- /* check if we should compensate for not being on a cycle boundary */
- if (middle_of_a_cycle)
- timer->last_updated += attotime::from_hz(timer->clockin);
+ /* check if we should compensate for not being on a cycle boundary */
+ if (middle_of_a_cycle)
+ m_last_updated += attotime::from_hz(m_clockin);
- load_count(timer, data);
- simulate2(timer, 0);
+ load_count(data);
+ simulate2(0);
- if (CTRL_MODE(timer->control) == 0)
- {
- set_output(timer, 0);
- }
- break;
+ if (CTRL_MODE(m_control) == 0)
+ set_output(0);
+ break;
- case 2:
- /* read/write counter bits 8-15 only */
+ case 2:
+ /* read/write counter bits 8-15 only */
- /* check if we should compensate for not being on a cycle boundary */
- if (middle_of_a_cycle)
- timer->last_updated += attotime::from_hz(timer->clockin);
+ /* check if we should compensate for not being on a cycle boundary */
+ if (middle_of_a_cycle)
+ m_last_updated += attotime::from_hz(m_clockin);
- load_count(timer, data << 8);
- simulate2(timer, 0);
+ load_count(data << 8);
+ simulate2(0);
- if (CTRL_MODE(timer->control) == 0)
- {
- set_output(timer, 0);
- }
- break;
+ if (CTRL_MODE(m_control) == 0)
+ set_output(0);
+ break;
- case 3:
- /* read/write bits 0-7 first, then 8-15 */
- if (timer->wmsb)
- {
- /* check if we should compensate for not being on a cycle boundary */
- if (middle_of_a_cycle)
- timer->last_updated += attotime::from_hz(timer->clockin);
+ case 3:
+ /* read/write bits 0-7 first, then 8-15 */
+ if (m_wmsb)
+ {
+ /* check if we should compensate for not being on a cycle boundary */
+ if (middle_of_a_cycle)
+ m_last_updated += attotime::from_hz(m_clockin);
- load_count(timer, timer->lowcount | (data << 8));
- simulate2(timer, 0);
- }
- else
+ load_count(m_lowcount | (data << 8));
+ simulate2(0);
+ }
+ else
+ {
+ m_lowcount = data;
+ if (CTRL_MODE(m_control) == 0)
{
- timer->lowcount = data;
- if (CTRL_MODE(timer->control) == 0)
- {
- /* The Intel docs say that writing the MSB in mode 0, phase
- 2 won't stop the count, but this was experimentally
- determined to be false. */
- timer->phase = 0;
- set_output(timer, 0);
- }
+ /* The Intel docs say that writing the MSB in mode 0, phase
+ 2 won't stop the count, but this was experimentally
+ determined to be false. */
+ m_phase = 0;
+ set_output(0);
}
- timer->wmsb = 1 - timer->wmsb;
- break;
}
+ m_wmsb = !m_wmsb;
+ break;
}
}
-void pit8253_device::gate_w(int gate, int state)
+WRITE8_MEMBER( pit8253_device::write )
{
- pit8253_timer *timer = get_timer(gate);
-
- if (timer == nullptr)
- return;
+ offset &= 3;
- LOG2(("gate_w(): gate=%d state=%d\n", gate, state));
+ LOG2(("write(): offset=%d data=0x%02x\n", offset, data));
- if (state != timer->gate)
+ if (offset == 3)
{
- int mode = CTRL_MODE(timer->control);
-
- update(timer);
- timer->gate = state;
- if (state != 0 && ( mode == 1 || mode == 2 || mode == 5 ))
- {
- timer->phase = 1;
- }
- update(timer);
+ /* Write to mode control register */
+ int timer = (data >> 6) & 3;
+ if (timer == 3)
+ readback_command(data);
+ else
+ m_counter[timer]->control_w(data);
}
+ else
+ m_counter[offset]->count_w(data);
}
-WRITE_LINE_MEMBER( pit8253_device::write_gate0 )
+void pit_counter_device::gate_w(int state)
{
- gate_w(0, state);
-}
+ LOG2(("gate_w(): state=%d\n", state));
-WRITE_LINE_MEMBER( pit8253_device::write_gate1 )
-{
- gate_w(1, state);
-}
+ if (state != m_gate)
+ {
+ int mode = CTRL_MODE(m_control);
-WRITE_LINE_MEMBER( pit8253_device::write_gate2 )
-{
- gate_w(2, state);
+ update();
+ m_gate = state;
+ if (state != 0 && ( mode == 1 || mode == 2 || mode == 5 ))
+ {
+ m_phase = 1;
+ }
+ update();
+ }
}
/* ----------------------------------------------------------------------- */
-void pit8253_device::set_clockin(int timerno, double new_clockin)
+void pit_counter_device::set_clockin(double new_clockin)
{
- pit8253_timer *timer = get_timer(timerno);
- assert(timer != nullptr);
+ LOG2(("set_clockin(): clockin = %f\n", new_clockin));
- LOG2(("set_clockin(): PIT timer=%d, clockin = %f\n", timerno, new_clockin));
-
- update(timer);
- timer->clockin = new_clockin;
- update(timer);
+ update();
+ m_clockin = new_clockin;
+ update();
}
-void pit8253_device::set_clock_signal(int timerno, int state)
+void pit_counter_device::set_clock_signal(int state)
{
- pit8253_timer *timer = get_timer(timerno);
- assert(timer != nullptr);
-
- LOG2(("set_clock_signal(): PIT timer=%d, state = %d\n", timerno, state));
+ LOG2(("set_clock_signal(): state = %d\n", state));
/* Trigger on low to high transition */
- if (!timer->clock && state)
+ if (!m_clock_signal && state)
{
/* Advance a cycle */
- simulate2(timer, 1);
+ simulate2(1);
}
- timer->clock = state;
-}
-
-WRITE_LINE_MEMBER( pit8253_device::write_clk0 )
-{
- set_clock_signal(0, state);
-}
-
-WRITE_LINE_MEMBER( pit8253_device::write_clk1 )
-{
- set_clock_signal(1, state);
-}
-
-WRITE_LINE_MEMBER( pit8253_device::write_clk2 )
-{
- set_clock_signal(2, state);
+ m_clock_signal = state;
}
diff --git a/src/devices/machine/pit8253.h b/src/devices/machine/pit8253.h
index 69f25ba7484..4dc50854882 100644
--- a/src/devices/machine/pit8253.h
+++ b/src/devices/machine/pit8253.h
@@ -35,46 +35,111 @@
***************************************************************************/
#define MCFG_PIT8253_CLK0(_clk) \
- downcast<pit8253_device &>(*device).set_clk0(_clk);
+ downcast<pit8253_device &>(*device).set_clk<0>(_clk);
#define MCFG_PIT8253_CLK1(_clk) \
- downcast<pit8253_device &>(*device).set_clk1(_clk);
+ downcast<pit8253_device &>(*device).set_clk<1>(_clk);
#define MCFG_PIT8253_CLK2(_clk) \
- downcast<pit8253_device &>(*device).set_clk2(_clk);
+ downcast<pit8253_device &>(*device).set_clk<2>(_clk);
#define MCFG_PIT8253_OUT0_HANDLER(_devcb) \
- devcb = &downcast<pit8253_device &>(*device).set_out0_handler(DEVCB_##_devcb);
+ devcb = &downcast<pit8253_device &>(*device).set_out_handler<0>(DEVCB_##_devcb);
#define MCFG_PIT8253_OUT1_HANDLER(_devcb) \
- devcb = &downcast<pit8253_device &>(*device).set_out1_handler(DEVCB_##_devcb);
+ devcb = &downcast<pit8253_device &>(*device).set_out_handler<1>(DEVCB_##_devcb);
#define MCFG_PIT8253_OUT2_HANDLER(_devcb) \
- devcb = &downcast<pit8253_device &>(*device).set_out2_handler(DEVCB_##_devcb);
+ devcb = &downcast<pit8253_device &>(*device).set_out_handler<2>(DEVCB_##_devcb);
+enum class pit_type
+{
+ I8254,
+ I8253,
+ FE2010
+};
+
+class pit_counter_device : public device_t
+{
+ friend class pit8253_device;
+ friend class pit8254_device;
+
+public:
+ // construction/destruction
+ pit_counter_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
+
+private:
+ inline uint32_t adjusted_count() const;
+ void decrease_counter_value(int64_t cycles);
+ void load_counter_value();
+ void set_output(int output);
+ void simulate2(int64_t elapsed_cycles);
+ void simulate(int64_t elapsed_cycles);
+ void update();
+ uint16_t masked_value() const;
+ uint8_t read();
+ void load_count(uint16_t newcount);
+ void readback(int command);
+ void control_w(uint8_t data);
+ void count_w(uint8_t data);
+ void gate_w(int state);
+ void set_clock_signal(int state);
+ void set_clockin(double new_clockin);
+
+ // internal state
+ int m_index; // index number of the timer
+ double m_clockin; // input clock frequency in Hz
+ int m_clock_signal; // clock signal when clockin is 0
+
+ attotime m_last_updated; // time when last updated
+
+ emu_timer *m_updatetimer; // MAME timer to process updates
+
+ uint16_t m_value; // current counter value ("CE" in Intel docs)
+ uint16_t m_latch; // latched counter value ("OL" in Intel docs)
+ uint16_t m_count; // new counter value ("CR" in Intel docs)
+ uint8_t m_control; // 6-bit control byte
+ uint8_t m_status; // status byte - 8254 only
+ uint8_t m_lowcount; // LSB of new counter value for 16-bit writes
+ bool m_rmsb; // true = Next read is MSB of 16-bit value
+ bool m_wmsb; // true = Next write is MSB of 16-bit value
+ int m_output; // 0 = low, 1 = high
+
+ int m_gate; // gate input (0 = low, 1 = high)
+ int m_latched_count; // number of bytes of count latched
+ int m_latched_status; // 1 = status latched (8254 only)
+ int m_null_count; // 1 = mode control or count written, 0 = count loaded
+ int m_phase; // see phase definition tables in simulate2(), below
+};
+
+DECLARE_DEVICE_TYPE(PIT_COUNTER, pit_counter_device)
+
class pit8253_device : public device_t
{
+ friend class pit_counter_device;
+
public:
+ // construction/destruction
pit8253_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// configuration helpers
- void set_clk0(double clk0) { m_clk0 = clk0; }
- void set_clk1(double clk1) { m_clk1 = clk1; }
- void set_clk2(double clk2) { m_clk2 = clk2; }
- void set_clk0(const XTAL &xtal) { set_clk0(xtal.dvalue()); }
- void set_clk1(const XTAL &xtal) { set_clk1(xtal.dvalue()); }
- void set_clk2(const XTAL &xtal) { set_clk2(xtal.dvalue()); }
- template <class Object> devcb_base &set_out0_handler(Object &&cb) { return m_out0_handler.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_out1_handler(Object &&cb) { return m_out1_handler.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_out2_handler(Object &&cb) { return m_out2_handler.set_callback(std::forward<Object>(cb)); }
+ template <unsigned N> void set_clk(double clk) { m_clk[N] = clk; }
+ template <unsigned N> void set_clk(const XTAL &xtal) { set_clk<N>(xtal.dvalue()); }
+ template <unsigned N, class Object> devcb_base &set_out_handler(Object &&cb) { return m_out_handler[N].set_callback(std::forward<Object>(cb)); }
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
- WRITE_LINE_MEMBER(write_gate0);
- WRITE_LINE_MEMBER(write_gate1);
- WRITE_LINE_MEMBER(write_gate2);
+ WRITE_LINE_MEMBER(write_gate0) { m_counter[0]->gate_w(state); }
+ WRITE_LINE_MEMBER(write_gate1) { m_counter[1]->gate_w(state); }
+ WRITE_LINE_MEMBER(write_gate2) { m_counter[2]->gate_w(state); }
/* In the 8253/8254 the CLKx input lines can be attached to a regular clock
signal. Another option is to use the output from one timer as the input
@@ -86,87 +151,28 @@ public:
to 0 with pit8253_set_clockin and call pit8253_clkX_w to change
the state of the input CLKx signal.
*/
- WRITE_LINE_MEMBER(write_clk0);
- WRITE_LINE_MEMBER(write_clk1);
- WRITE_LINE_MEMBER(write_clk2);
+ WRITE_LINE_MEMBER(write_clk0) { m_counter[0]->set_clock_signal(state); }
+ WRITE_LINE_MEMBER(write_clk1) { m_counter[1]->set_clock_signal(state); }
+ WRITE_LINE_MEMBER(write_clk2) { m_counter[2]->set_clock_signal(state); }
- void set_clockin(int timer, double new_clockin);
+ void set_clockin(int timer, double new_clockin) { m_counter[timer]->set_clockin(new_clockin); }
protected:
- pit8253_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int chip_type);
+ pit8253_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, pit_type chip_type);
// device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual void device_resolve_objects() override;
virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
- // internal state
- struct pit8253_timer
- {
- int index; /* index number of the timer */
- double clockin; /* input clock frequency in Hz */
- int clock; /* clock signal when clockin is 0 */
-
- attotime last_updated; /* time when last updated */
-
- emu_timer *updatetimer; /* MAME timer to process updates */
-
- uint16_t value; /* current counter value ("CE" in Intel docs) */
- uint16_t latch; /* latched counter value ("OL" in Intel docs) */
- uint16_t count; /* new counter value ("CR" in Intel docs) */
- uint8_t control; /* 6-bit control byte */
- uint8_t status; /* status byte - 8254 only */
- uint8_t lowcount; /* LSB of new counter value for 16-bit writes */
- int rmsb; /* 1 = Next read is MSB of 16-bit value */
- int wmsb; /* 1 = Next write is MSB of 16-bit value */
- int output; /* 0 = low, 1 = high */
-
- int gate; /* gate input (0 = low, 1 = high) */
- int latched_count; /* number of bytes of count latched */
- int latched_status; /* 1 = status latched (8254 only) */
- int null_count; /* 1 = mode control or count written, 0 = count loaded */
- int phase; /* see phase definition tables in simulate2(), below */
- };
-
- void readback(pit8253_timer *timer, int command);
virtual void readback_command(uint8_t data);
- pit8253_timer *get_timer(int which);
- enum
- {
- I8254,
- I8253,
- FE2010
- };
+ double m_clk[3];
+ devcb_write_line m_out_handler[3];
-private:
- double m_clk0;
- double m_clk1;
- double m_clk2;
- devcb_write_line m_out0_handler;
- devcb_write_line m_out1_handler;
- devcb_write_line m_out2_handler;
-
- enum
- {
- PIT8253_MAX_TIMER = 3
- };
-
- pit8253_timer m_timers[PIT8253_MAX_TIMER];
-
- inline uint32_t adjusted_count(int bcd, uint16_t val);
- void decrease_counter_value(pit8253_timer *timer, int64_t cycles);
- void load_counter_value(pit8253_timer *timer);
- void set_output(pit8253_timer *timer, int output);
- void simulate2(pit8253_timer *timer, int64_t elapsed_cycles);
- void simulate(pit8253_timer *timer, int64_t elapsed_cycles);
- void update(pit8253_timer *timer);
- uint16_t masked_value(pit8253_timer *timer);
- void load_count(pit8253_timer *timer, uint16_t newcount);
- void gate_w(int gate, int state);
- void set_clock_signal(int timerno, int state);
-
- int m_type;
+ required_device_array<pit_counter_device, 3> m_counter;
+
+ pit_type m_type;
};
DECLARE_DEVICE_TYPE(PIT8253, pit8253_device)