summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2018-04-14 17:53:55 -0400
committer AJR <ajrhacker@users.noreply.github.com>2018-04-14 17:53:55 -0400
commitf6554879ce7b7802f6e1312531775642f8a279ea (patch)
treecee38d7e81c9b482d61e166868fdaf5c4ceb7746
parentedd4afbe8f7c092ebbdb5914764b5b11798e4680 (diff)
z80ctc: Make channels into subdevices
-rw-r--r--src/devices/machine/z80ctc.cpp234
-rw-r--r--src/devices/machine/z80ctc.h96
2 files changed, 165 insertions, 165 deletions
diff --git a/src/devices/machine/z80ctc.cpp b/src/devices/machine/z80ctc.cpp
index efc8eae1aea..a28991e021f 100644
--- a/src/devices/machine/z80ctc.cpp
+++ b/src/devices/machine/z80ctc.cpp
@@ -19,9 +19,7 @@
//**************************************************************************
#define VERBOSE 0
-
-#define VPRINTF(x) do { if (VERBOSE) logerror x; } while (0)
-#define VPRINTF_CHANNEL(x) do { if (VERBOSE) m_device->logerror x; } while (0)
+#include "logmacro.h"
@@ -30,40 +28,40 @@
//**************************************************************************
// these are the bits of the incoming commands to the CTC
-const int INTERRUPT = 0x80;
-const int INTERRUPT_ON = 0x80;
-//const int INTERRUPT_OFF = 0x00;
+constexpr u16 INTERRUPT = 0x80;
+constexpr u16 INTERRUPT_ON = 0x80;
+//constexpr u16 INTERRUPT_OFF = 0x00;
-const int MODE = 0x40;
-const int MODE_TIMER = 0x00;
-const int MODE_COUNTER = 0x40;
+constexpr u16 MODE = 0x40;
+constexpr u16 MODE_TIMER = 0x00;
+constexpr u16 MODE_COUNTER = 0x40;
-const int PRESCALER = 0x20;
-//const int PRESCALER_256 = 0x20;
-const int PRESCALER_16 = 0x00;
+constexpr u16 PRESCALER = 0x20;
+//constexpr u16 PRESCALER_256 = 0x20;
+constexpr u16 PRESCALER_16 = 0x00;
-const int EDGE = 0x10;
-const int EDGE_FALLING = 0x00;
-const int EDGE_RISING = 0x10;
+constexpr u16 EDGE = 0x10;
+constexpr u16 EDGE_FALLING = 0x00;
+constexpr u16 EDGE_RISING = 0x10;
-const int TRIGGER = 0x08;
-const int TRIGGER_AUTO = 0x00;
-//const int TRIGGER_CLOCK = 0x08;
+constexpr u16 TRIGGER = 0x08;
+constexpr u16 TRIGGER_AUTO = 0x00;
+//constexpr u16 TRIGGER_CLOCK = 0x08;
-const int CONSTANT = 0x04;
-const int CONSTANT_LOAD = 0x04;
-//const int CONSTANT_NONE = 0x00;
+constexpr u16 CONSTANT = 0x04;
+constexpr u16 CONSTANT_LOAD = 0x04;
+//constexpr u16 CONSTANT_NONE = 0x00;
-const int RESET = 0x02;
-//const int RESET_CONTINUE = 0x00;
-const int RESET_ACTIVE = 0x02;
+constexpr u16 RESET = 0x02;
+//constexpr u16 RESET_CONTINUE = 0x00;
+constexpr u16 RESET_ACTIVE = 0x02;
-const int CONTROL = 0x01;
-const int CONTROL_VECTOR = 0x00;
-const int CONTROL_WORD = 0x01;
+constexpr u16 CONTROL = 0x01;
+constexpr u16 CONTROL_VECTOR = 0x00;
+constexpr u16 CONTROL_WORD = 0x01;
// these extra bits help us keep things accurate
-const int WAITING_FOR_TRIG = 0x100;
+constexpr u16 WAITING_FOR_TRIG = 0x100;
@@ -71,22 +69,21 @@ const int WAITING_FOR_TRIG = 0x100;
// LIVE DEVICE
//**************************************************************************
-// device type definition
+// device type definitions
DEFINE_DEVICE_TYPE(Z80CTC, z80ctc_device, "z80ctc", "Z80 CTC")
+DEFINE_DEVICE_TYPE(Z80CTC_CHANNEL, z80ctc_channel_device, "z80ctc_channel", "Z80 CTC Channel")
//-------------------------------------------------
// z80ctc_device - constructor
//-------------------------------------------------
-z80ctc_device::z80ctc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+z80ctc_device::z80ctc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, Z80CTC, tag, owner, clock),
device_z80daisy_interface(mconfig, *this),
m_intr_cb(*this),
- m_zc0_cb(*this),
- m_zc1_cb(*this),
- m_zc2_cb(*this),
- m_zc3_cb(*this),
- m_vector(0)
+ m_zc_cb{*this, *this, *this, *this},
+ m_vector(0),
+ m_channel(*this, "ch%u", 0U)
{
}
@@ -97,7 +94,7 @@ z80ctc_device::z80ctc_device(const machine_config &mconfig, const char *tag, dev
READ8_MEMBER( z80ctc_device::read )
{
- return m_channel[offset & 3].read();
+ return m_channel[offset & 3]->read();
}
@@ -107,7 +104,7 @@ READ8_MEMBER( z80ctc_device::read )
WRITE8_MEMBER( z80ctc_device::write )
{
- m_channel[offset & 3].write(data);
+ m_channel[offset & 3]->write(data);
}
@@ -116,31 +113,51 @@ WRITE8_MEMBER( z80ctc_device::write )
// trigger
//-------------------------------------------------
-WRITE_LINE_MEMBER( z80ctc_device::trg0 ) { m_channel[0].trigger(state); }
-WRITE_LINE_MEMBER( z80ctc_device::trg1 ) { m_channel[1].trigger(state); }
-WRITE_LINE_MEMBER( z80ctc_device::trg2 ) { m_channel[2].trigger(state); }
-WRITE_LINE_MEMBER( z80ctc_device::trg3 ) { m_channel[3].trigger(state); }
+WRITE_LINE_MEMBER( z80ctc_device::trg0 ) { m_channel[0]->trigger(state != 0); }
+WRITE_LINE_MEMBER( z80ctc_device::trg1 ) { m_channel[1]->trigger(state != 0); }
+WRITE_LINE_MEMBER( z80ctc_device::trg2 ) { m_channel[2]->trigger(state != 0); }
+WRITE_LINE_MEMBER( z80ctc_device::trg3 ) { m_channel[3]->trigger(state != 0); }
//-------------------------------------------------
-// device_start - device-specific startup
+// device_add_mconfig - add device-specific
+// machine configuration
//-------------------------------------------------
-void z80ctc_device::device_start()
+MACHINE_CONFIG_START(z80ctc_device::device_add_mconfig)
+ MCFG_DEVICE_ADD("ch0", Z80CTC_CHANNEL, 0)
+ MCFG_DEVICE_ADD("ch1", Z80CTC_CHANNEL, 0)
+ MCFG_DEVICE_ADD("ch2", Z80CTC_CHANNEL, 0)
+ MCFG_DEVICE_ADD("ch3", Z80CTC_CHANNEL, 0)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// device_resolve_objects - resolve objects that
+// may be needed for other devices to set
+// initial conditions at start time
+//-------------------------------------------------
+
+void z80ctc_device::device_resolve_objects()
{
// resolve callbacks
m_intr_cb.resolve_safe();
- m_zc0_cb.resolve_safe();
- m_zc1_cb.resolve_safe();
- m_zc2_cb.resolve_safe();
- m_zc3_cb.resolve_safe();
+ for (int ch = 0; ch < 4; ch++)
+ {
+ m_zc_cb[ch].resolve_safe();
- // start each channel
- m_channel[0].start(this, 0);
- m_channel[1].start(this, 1);
- m_channel[2].start(this, 2);
- m_channel[3].start(this, 3);
+ // assign channel index
+ m_channel[ch]->m_index = ch;
+ }
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void z80ctc_device::device_start()
+{
// register for save states
save_item(NAME(m_vector));
}
@@ -150,17 +167,11 @@ void z80ctc_device::device_start()
// device_reset - device-specific reset
//-------------------------------------------------
-void z80ctc_device::device_reset()
+void z80ctc_device::device_reset_after_children()
{
- // reset each channel
- m_channel[0].reset();
- m_channel[1].reset();
- m_channel[2].reset();
- m_channel[3].reset();
-
// check for interrupts
interrupt_check();
- VPRINTF(("CTC Reset\n"));
+ LOG("CTC Reset\n");
}
@@ -176,19 +187,19 @@ void z80ctc_device::device_reset()
int z80ctc_device::z80daisy_irq_state()
{
- VPRINTF(("CTC IRQ state = %d%d%d%d\n", m_channel[0].m_int_state, m_channel[1].m_int_state, m_channel[2].m_int_state, m_channel[3].m_int_state));
+ LOG("CTC IRQ state = %d%d%d%d\n", m_channel[0]->m_int_state, m_channel[1]->m_int_state, m_channel[2]->m_int_state, m_channel[3]->m_int_state);
// loop over all channels
int state = 0;
- for (auto & channel : m_channel)
+ for (int ch = 0; ch < 4; ch++)
{
// if we're servicing a request, don't indicate more interrupts
- if (channel.m_int_state & Z80_DAISY_IEO)
+ if (m_channel[ch]->m_int_state & Z80_DAISY_IEO)
{
state |= Z80_DAISY_IEO;
break;
}
- state |= channel.m_int_state;
+ state |= m_channel[ch]->m_int_state;
}
return state;
@@ -205,12 +216,12 @@ int z80ctc_device::z80daisy_irq_ack()
// loop over all channels
for (int ch = 0; ch < 4; ch++)
{
- ctc_channel &channel = m_channel[ch];
+ z80ctc_channel_device &channel = *m_channel[ch];
// find the first channel with an interrupt requested
if (channel.m_int_state & Z80_DAISY_INT)
{
- VPRINTF(("CTC IRQAck ch%d\n", ch));
+ LOG("CTC IRQAck ch%d\n", ch);
// clear interrupt, switch to the IEO state, and update the IRQs
channel.m_int_state = Z80_DAISY_IEO;
@@ -234,12 +245,12 @@ void z80ctc_device::z80daisy_irq_reti()
// loop over all channels
for (int ch = 0; ch < 4; ch++)
{
- ctc_channel &channel = m_channel[ch];
+ z80ctc_channel_device &channel = *m_channel[ch];
// find the first channel with an IEO pending
if (channel.m_int_state & Z80_DAISY_IEO)
{
- VPRINTF(("CTC IRQReti ch%d\n", ch));
+ LOG("CTC IRQReti ch%d\n", ch);
// clear the IEO state and update the IRQs
channel.m_int_state &= ~Z80_DAISY_IEO;
@@ -275,11 +286,12 @@ void z80ctc_device::interrupt_check()
//**************************************************************************
//-------------------------------------------------
-// ctc_channel - constructor
+// z80ctc_channel_device - constructor
//-------------------------------------------------
-z80ctc_device::ctc_channel::ctc_channel()
- : m_device(nullptr),
+z80ctc_channel_device::z80ctc_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, Z80CTC_CHANNEL, tag, owner, clock),
+ m_device(*this, DEVICE_SELF_OWNER),
m_index(0),
m_mode(0),
m_tconst(0),
@@ -292,30 +304,28 @@ z80ctc_device::ctc_channel::ctc_channel()
//-------------------------------------------------
-// start - set up at device start time
+// device_start - set up at device start time
//-------------------------------------------------
-void z80ctc_device::ctc_channel::start(z80ctc_device *device, int index)
+void z80ctc_channel_device::device_start()
{
// initialize state
- m_device = device;
- m_index = index;
- m_timer = m_device->machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z80ctc_device::ctc_channel::timer_callback), this));
+ m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z80ctc_channel_device::timer_callback), this));
// register for save states
- m_device->save_item(NAME(m_mode), m_index);
- m_device->save_item(NAME(m_tconst), m_index);
- m_device->save_item(NAME(m_down), m_index);
- m_device->save_item(NAME(m_extclk), m_index);
- m_device->save_item(NAME(m_int_state), m_index);
+ save_item(NAME(m_mode));
+ save_item(NAME(m_tconst));
+ save_item(NAME(m_down));
+ save_item(NAME(m_extclk));
+ save_item(NAME(m_int_state));
}
//-------------------------------------------------
-// reset - reset the channel
+// device_reset - reset the channel
//-------------------------------------------------
-void z80ctc_device::ctc_channel::reset()
+void z80ctc_channel_device::device_reset()
{
m_mode = RESET_ACTIVE;
m_tconst = 0x100;
@@ -328,7 +338,7 @@ void z80ctc_device::ctc_channel::reset()
// period - return the current channel's period
//-------------------------------------------------
-attotime z80ctc_device::ctc_channel::period() const
+attotime z80ctc_channel_device::period() const
{
// if reset active, no period
if ((m_mode & RESET) == RESET_ACTIVE)
@@ -337,7 +347,7 @@ attotime z80ctc_device::ctc_channel::period() const
// if counter mode, no real period
if ((m_mode & MODE) == MODE_COUNTER)
{
- m_device->logerror("CTC %d is CounterMode : Can't calculate period\n", m_index);
+ logerror("CounterMode : Can't calculate period\n");
return attotime::zero;
}
@@ -351,7 +361,7 @@ attotime z80ctc_device::ctc_channel::period() const
// read - read the channel's state
//-------------------------------------------------
-uint8_t z80ctc_device::ctc_channel::read()
+u8 z80ctc_channel_device::read()
{
// if we're in counter mode, just return the count
if ((m_mode & MODE) == MODE_COUNTER || (m_mode & WAITING_FOR_TRIG))
@@ -362,7 +372,7 @@ uint8_t z80ctc_device::ctc_channel::read()
{
attotime period = m_device->clocks_to_attotime((m_mode & PRESCALER) == PRESCALER_16 ? 16 : 256);
- VPRINTF_CHANNEL(("CTC clock %f\n",ATTOSECONDS_TO_HZ(period.attoseconds())));
+ LOG("CTC clock %f\n",ATTOSECONDS_TO_HZ(period.attoseconds()));
if (m_timer != nullptr)
return ((int)(m_timer->remaining().as_double() / period.as_double()) + 1) & 0xff;
@@ -376,12 +386,12 @@ uint8_t z80ctc_device::ctc_channel::read()
// write - handle writes to a channel
//-------------------------------------------------
-void z80ctc_device::ctc_channel::write(uint8_t data)
+void z80ctc_channel_device::write(u8 data)
{
// if we're waiting for a time constant, this is it
if ((m_mode & CONSTANT) == CONSTANT_LOAD)
{
- VPRINTF_CHANNEL(("CTC ch.%d constant = %02x\n", m_index, data));
+ LOG("Time constant = %02x\n", data);
// set the time constant (0 -> 0x100)
m_tconst = data ? data : 0x100;
@@ -399,7 +409,7 @@ void z80ctc_device::ctc_channel::write(uint8_t data)
if ((m_mode & TRIGGER) == TRIGGER_AUTO)
{
attotime curperiod = period();
- m_timer->adjust(curperiod, m_index, curperiod);
+ m_timer->adjust(curperiod, 0, curperiod);
}
// else set the bit indicating that we're waiting for the appropriate trigger
@@ -421,7 +431,7 @@ void z80ctc_device::ctc_channel::write(uint8_t data)
#endif
{
m_device->m_vector = data & 0xf8;
- VPRINTF_CHANNEL(("CTC Vector = %02x\n", m_device->m_vector));
+ LOG("Vector = %02x\n", m_device->m_vector);
}
// this must be a control word
@@ -435,7 +445,7 @@ void z80ctc_device::ctc_channel::write(uint8_t data)
// set the new mode
m_mode = data;
- VPRINTF_CHANNEL(("CTC ch.%d mode = %02x\n", m_index, data));
+ LOG("Channel mode = %02x\n", data);
// if we're being reset, clear out any pending timers for this channel
if ((data & RESET) == RESET_ACTIVE)
@@ -452,25 +462,22 @@ void z80ctc_device::ctc_channel::write(uint8_t data)
// side-effects
//-------------------------------------------------
-void z80ctc_device::ctc_channel::trigger(uint8_t data)
+void z80ctc_channel_device::trigger(bool state)
{
- // normalize data
- data = data ? 1 : 0;
-
// see if the trigger value has changed
- if (data != m_extclk)
+ if (state != m_extclk)
{
- m_extclk = data;
+ m_extclk = state;
// see if this is the active edge of the trigger
- if (((m_mode & EDGE) == EDGE_RISING && data) || ((m_mode & EDGE) == EDGE_FALLING && !data))
+ if (((m_mode & EDGE) == EDGE_RISING && state) || ((m_mode & EDGE) == EDGE_FALLING && !state))
{
// if we're waiting for a trigger, start the timer
if ((m_mode & WAITING_FOR_TRIG) && (m_mode & MODE) == MODE_TIMER)
{
attotime curperiod = period();
- VPRINTF_CHANNEL(("CTC period %s\n", curperiod.as_string()));
- m_timer->adjust(curperiod, m_index, curperiod);
+ LOG("Period = %s\n", curperiod.as_string());
+ m_timer->adjust(curperiod, 0, curperiod);
}
// we're no longer waiting
@@ -493,36 +500,19 @@ void z80ctc_device::ctc_channel::trigger(uint8_t data)
// side-effects
//-------------------------------------------------
-TIMER_CALLBACK_MEMBER(z80ctc_device::ctc_channel::timer_callback)
+TIMER_CALLBACK_MEMBER(z80ctc_channel_device::timer_callback)
{
// down counter has reached zero - see if we should interrupt
if ((m_mode & INTERRUPT) == INTERRUPT_ON)
{
m_int_state |= Z80_DAISY_INT;
- VPRINTF_CHANNEL(("CTC timer ch%d\n", m_index));
+ LOG("Timer interrupt\n");
m_device->interrupt_check();
}
// generate the clock pulse
- switch (m_index)
- {
- case 0:
- m_device->m_zc0_cb(1);
- m_device->m_zc0_cb(0);
- break;
- case 1:
- m_device->m_zc1_cb(1);
- m_device->m_zc1_cb(0);
- break;
- case 2:
- m_device->m_zc2_cb(1);
- m_device->m_zc2_cb(0);
- break;
- case 3:
- m_device->m_zc3_cb(1);
- m_device->m_zc3_cb(0);
- break;
- }
+ m_device->m_zc_cb[m_index](1);
+ m_device->m_zc_cb[m_index](0);
// reset the down counter
m_down = m_tconst;
diff --git a/src/devices/machine/z80ctc.h b/src/devices/machine/z80ctc.h
index 7da3f480bf7..724a6dbb9c0 100644
--- a/src/devices/machine/z80ctc.h
+++ b/src/devices/machine/z80ctc.h
@@ -39,33 +39,68 @@
devcb = &downcast<z80ctc_device &>(*device).set_intr_callback(DEVCB_##_devcb);
#define MCFG_Z80CTC_ZC0_CB(_devcb) \
- devcb = &downcast<z80ctc_device &>(*device).set_zc0_callback(DEVCB_##_devcb);
+ devcb = &downcast<z80ctc_device &>(*device).set_zc_callback<0>(DEVCB_##_devcb);
#define MCFG_Z80CTC_ZC1_CB(_devcb) \
- devcb = &downcast<z80ctc_device &>(*device).set_zc1_callback(DEVCB_##_devcb);
+ devcb = &downcast<z80ctc_device &>(*device).set_zc_callback<1>(DEVCB_##_devcb);
#define MCFG_Z80CTC_ZC2_CB(_devcb) \
- devcb = &downcast<z80ctc_device &>(*device).set_zc2_callback(DEVCB_##_devcb);
+ devcb = &downcast<z80ctc_device &>(*device).set_zc_callback<2>(DEVCB_##_devcb);
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
+// forward declaration
+class z80ctc_device;
+
+// ======================> z80ctc_channel_device
+
+// a single channel within the CTC
+class z80ctc_channel_device : public device_t
+{
+ friend class z80ctc_device;
+
+public:
+ // construction/destruction
+ z80ctc_channel_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ u8 read();
+ void write(u8 data);
+
+ attotime period() const;
+ void trigger(bool state);
+ TIMER_CALLBACK_MEMBER(timer_callback);
+
+ required_device<z80ctc_device> m_device; // pointer back to our device
+ int m_index; // our channel index
+ u16 m_mode; // current mode
+ u16 m_tconst; // time constant
+ u16 m_down; // down counter (clock mode only)
+ bool m_extclk; // current signal from the external clock
+ emu_timer * m_timer; // array of active timers
+ u8 m_int_state; // interrupt status (for daisy chain)
+};
// ======================> z80ctc_device
class z80ctc_device : public device_t,
public device_z80daisy_interface
{
+ friend class z80ctc_channel_device;
+
public:
// construction/destruction
- z80ctc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ z80ctc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
template <class Object> devcb_base &set_intr_callback(Object &&cb) { return m_intr_cb.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_zc0_callback(Object &&cb) { return m_zc0_cb.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_zc1_callback(Object &&cb) { return m_zc1_cb.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_zc2_callback(Object &&cb) { return m_zc2_cb.set_callback(std::forward<Object>(cb)); }
+ template <int Channel, class Object> devcb_base &set_zc_callback(Object &&cb) { return m_zc_cb[Channel].set_callback(std::forward<Object>(cb)); }
// read/write handlers
DECLARE_READ8_MEMBER( read );
@@ -75,12 +110,14 @@ public:
DECLARE_WRITE_LINE_MEMBER( trg2 );
DECLARE_WRITE_LINE_MEMBER( trg3 );
- uint16_t get_channel_constant(uint8_t channel) { return m_channel[channel].m_tconst; }
+ u16 get_channel_constant(u8 channel) const { return m_channel[channel]->m_tconst; }
protected:
// 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_reset_after_children() override;
// z80daisy_interface overrides
virtual int z80daisy_irq_state() override;
@@ -91,46 +128,19 @@ private:
// internal helpers
void interrupt_check();
- // a single channel within the CTC
- class ctc_channel
- {
- public:
- ctc_channel();
-
- void start(z80ctc_device *device, int index);
- void reset();
-
- uint8_t read();
- void write(uint8_t data);
-
- attotime period() const;
- void trigger(uint8_t data);
- TIMER_CALLBACK_MEMBER(timer_callback);
-
- z80ctc_device * m_device; // pointer back to our device
- int m_index; // our channel index
- uint16_t m_mode; // current mode
- uint16_t m_tconst; // time constant
- uint16_t m_down; // down counter (clock mode only)
- uint8_t m_extclk; // current signal from the external clock
- emu_timer * m_timer; // array of active timers
- uint8_t m_int_state; // interrupt status (for daisy chain)
- };
-
// internal state
devcb_write_line m_intr_cb; // interrupt callback
- devcb_write_line m_zc0_cb; // channel 0 zero crossing callbacks
- devcb_write_line m_zc1_cb; // channel 1 zero crossing callbacks
- devcb_write_line m_zc2_cb; // channel 2 zero crossing callbacks
- devcb_write_line m_zc3_cb; // channel 3 zero crossing callbacks = nullptr ?
+ devcb_write_line m_zc_cb[4]; // zero crossing/timer output callbacks
- uint8_t m_vector; // interrupt vector
- ctc_channel m_channel[4]; // data for each channel
+ u8 m_vector; // interrupt vector
+
+ // subdevice for each channel
+ required_device_array<z80ctc_channel_device, 4> m_channel;
};
-// device type definition
+// device type definitions
DECLARE_DEVICE_TYPE(Z80CTC, z80ctc_device)
-
+DECLARE_DEVICE_TYPE(Z80CTC_CHANNEL, z80ctc_channel_device)
#endif // MAME_MACHINE_Z80CTC_H