From b32c5200e3184ad28c96a62b67550f62c8668828 Mon Sep 17 00:00:00 2001 From: AJR Date: Wed, 28 Dec 2016 18:13:08 -0500 Subject: [PATCH] Z80 daisy chain stuff - Reconfigure Z80 daisy chain behavior to use the standard vector for an external IRQ, rather than a bogus one from the last device in the chain - Enable Z80 daisy chain on Cedar Magnet sound board (fake IRQ still necessary, though vectors are correct now) - Source note regarding IM 2 behavior contrary to Zilog datasheet (nw; was fixed way back in 0.35b11) --- src/devices/cpu/z180/z180.cpp | 2 ++ src/devices/cpu/z180/z180op.hxx | 9 ++------- src/devices/cpu/z80/z80.cpp | 23 +++++++++------------ src/devices/cpu/z80/z80.h | 1 - src/devices/cpu/z80/z80daisy.cpp | 16 ++++++++------- src/devices/cpu/z80/z80daisy.h | 2 ++ src/mame/machine/cedar_magnet_sound.cpp | 27 +++++++++++++------------ 7 files changed, 38 insertions(+), 42 deletions(-) diff --git a/src/devices/cpu/z180/z180.cpp b/src/devices/cpu/z180/z180.cpp index a9ba848ebdd..0c208a1f467 100644 --- a/src/devices/cpu/z180/z180.cpp +++ b/src/devices/cpu/z180/z180.cpp @@ -1969,6 +1969,8 @@ void z180_device::device_start() m_odirect = &m_oprogram->direct(); m_iospace = &space(AS_IO); + daisy_set_irq_callback(device_irq_acknowledge_delegate(FUNC(z180_device::standard_irq_callback_member), this)); + /* set up the state table */ { state_add(Z180_PC, "PC", m_PC.w.l); diff --git a/src/devices/cpu/z180/z180op.hxx b/src/devices/cpu/z180/z180op.hxx index 2479479344a..cad25aa4d1f 100644 --- a/src/devices/cpu/z180/z180op.hxx +++ b/src/devices/cpu/z180/z180op.hxx @@ -306,13 +306,8 @@ int z180_device::take_interrupt(int irq) if( irq == Z180_INT_IRQ0 ) { - /* Daisy chain mode? If so, call the requesting device */ - if (daisy_chain_present()) - irq_vector = daisy_call_ack_device(); - - /* else call back the cpu interface to retrieve the vector */ - else - irq_vector = standard_irq_callback(0); + // retrieve the IRQ vector from the daisy chain or CPU interface + irq_vector = daisy_call_ack_device(); LOG(("Z180 '%s' single int. irq_vector $%02x\n", tag(), irq_vector)); diff --git a/src/devices/cpu/z80/z80.cpp b/src/devices/cpu/z80/z80.cpp index 7799dff84d5..93b697b5edf 100644 --- a/src/devices/cpu/z80/z80.cpp +++ b/src/devices/cpu/z80/z80.cpp @@ -3146,32 +3146,27 @@ void z80_device::take_nmi() void z80_device::take_interrupt() { - int irq_vector; - PRVPC = 0xffff; // HACK: segag80r protection kludge - /* Check if processor was halted */ + // check if processor was halted leave_halt(); - /* Clear both interrupt flip flops */ + // clear both interrupt flip flops m_iff1 = m_iff2 = 0; - /* Daisy chain mode? If so, call the requesting device */ - if (daisy_chain_present()) - irq_vector = daisy_call_ack_device(); - - /* else call back the cpu interface to retrieve the vector */ - else - irq_vector = m_irq_callback(*this, 0); - - /* Say hi */ + // say hi m_irqack_cb(true); + // fetch the IRQ vector + int irq_vector = daisy_call_ack_device(); LOG(("Z80 '%s' single int. irq_vector $%02x\n", tag(), irq_vector)); /* Interrupt mode 2. Call [i:databyte] */ if( m_im == 2 ) { + // Zilog's datasheet claims that "the least-significant bit must be a zero." + // However, experiments have confirmed that IM 2 vectors do not have to be + // even, and all 8 bits will be used; even $FF is handled normally. irq_vector = (irq_vector & 0xff) | (m_i << 8); push(m_pc); rm16(irq_vector, m_pc); @@ -3415,7 +3410,7 @@ void z80_device::device_start() m_decrypted_opcodes_direct = &m_decrypted_opcodes->direct(); m_io = &space(AS_IO); - m_irq_callback = device_irq_acknowledge_delegate(FUNC(z80_device::standard_irq_callback_member), this); + daisy_set_irq_callback(device_irq_acknowledge_delegate(FUNC(z80_device::standard_irq_callback_member), this)); IX = IY = 0xffff; /* IX and IY are FFFF after a reset! */ F = ZF; /* Zero flag is set */ diff --git a/src/devices/cpu/z80/z80.h b/src/devices/cpu/z80/z80.h index ecfd106e1c1..664e484c565 100644 --- a/src/devices/cpu/z80/z80.h +++ b/src/devices/cpu/z80/z80.h @@ -276,7 +276,6 @@ protected: uint8_t m_after_ei; /* are we in the EI shadow? */ uint8_t m_after_ldair; /* same, but for LD A,I or LD A,R */ uint32_t m_ea; - device_irq_acknowledge_delegate m_irq_callback; int m_icount; uint8_t m_rtemp; diff --git a/src/devices/cpu/z80/z80daisy.cpp b/src/devices/cpu/z80/z80daisy.cpp index 82e41c42e1a..a46f7956179 100644 --- a/src/devices/cpu/z80/z80daisy.cpp +++ b/src/devices/cpu/z80/z80daisy.cpp @@ -11,6 +11,8 @@ #include "emu.h" #include "z80daisy.h" +#define VERBOSE 0 + //************************************************************************** // DEVICE Z80 DAISY INTERFACE @@ -170,19 +172,20 @@ int z80_daisy_chain_interface::daisy_update_irq_state() int z80_daisy_chain_interface::daisy_call_ack_device() { - int vector = 0; - // loop over all devices; dev[0] is the highest priority for (device_z80daisy_interface *intf = m_chain; intf != nullptr; intf = intf->m_daisy_next) { // if this device is asserting the INT line, that's the one we want int state = intf->z80daisy_irq_state(); - vector = intf->z80daisy_irq_ack(); if (state & Z80_DAISY_INT) - return vector; + return intf->z80daisy_irq_ack(); // call the requesting device } - //logerror("z80daisy_call_ack_device: failed to find an device to ack!\n"); - return vector; + + if (VERBOSE && daisy_chain_present()) + device().logerror("Interrupt from outside Z80 daisy chain\n"); + + // call back the CPU interface to retrieve the vector + return m_irq_callback(device(), 0); } @@ -204,7 +207,6 @@ void z80_daisy_chain_interface::daisy_call_reti_device() return; } } - //logerror("z80daisy_call_reti_device: failed to find an device to reti!\n"); } diff --git a/src/devices/cpu/z80/z80daisy.h b/src/devices/cpu/z80/z80daisy.h index 57d852261bc..7a11cb829c7 100644 --- a/src/devices/cpu/z80/z80daisy.h +++ b/src/devices/cpu/z80/z80daisy.h @@ -94,6 +94,7 @@ protected: // initialization void daisy_init(const z80_daisy_config *daisy); + void daisy_set_irq_callback(const device_irq_acknowledge_delegate &callback) { m_irq_callback = callback; } // callbacks int daisy_update_irq_state(); @@ -103,6 +104,7 @@ protected: private: const z80_daisy_config *m_daisy_config; device_z80daisy_interface *m_chain; // head of the daisy chain + device_irq_acknowledge_delegate m_irq_callback; }; diff --git a/src/mame/machine/cedar_magnet_sound.cpp b/src/mame/machine/cedar_magnet_sound.cpp index d289c1ad200..446751f8a16 100644 --- a/src/mame/machine/cedar_magnet_sound.cpp +++ b/src/mame/machine/cedar_magnet_sound.cpp @@ -10,20 +10,16 @@ 0xe6 - from ctc0 channel 3 (vector = E0) used to drive MSM5205 through FIFO 0xee - from ctc0 channel 3 (vector = E8) ^^ - 0xf6 - drive AY (once per frame?) triggered by ctc1 channel 3? (sets vector to f0, f6 = channel3?) - 0xff - read sound latch (triggered by write from master board) - - any attempts made to hook up the ctcs end up resulting in it taking an interrupt - with vector 0xf0, which points to 0x0000 and resets the cpu?! - - does the device here also need to add daisychain functions in order for the 0xff vector to be used - with the soundlatch writes? + 0xf6 - drive AY (once per frame?) triggered by ctc1 channel 3 (vector = F0) + 0xff - read sound latch (triggered by write from master board; default vector set by 5K/+5 pullups on D0-D7) */ #include "emu.h" #include "cedar_magnet_sound.h" +#include "machine/clock.h" + extern const device_type CEDAR_MAGNET_SOUND = &device_creator; @@ -47,7 +43,7 @@ void cedar_magnet_sound_device::write_command(uint8_t data) { m_command = data; // this interrupt causes it to read the soundlatch at 0x14 - m_cpu->set_input_line_and_vector(0, HOLD_LINE,0xff); + m_cpu->set_input_line_and_vector(0, HOLD_LINE, 0xff); } @@ -58,6 +54,7 @@ ADDRESS_MAP_END static ADDRESS_MAP_START( cedar_magnet_sound_io, AS_IO, 8, cedar_magnet_sound_device ) ADDRESS_MAP_GLOBAL_MASK(0xff) + ADDRESS_MAP_UNMAP_HIGH AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("ctc0", z80ctc_device, read, write) AM_RANGE(0x04, 0x07) AM_DEVREADWRITE("ctc1", z80ctc_device, read, write) @@ -133,15 +130,12 @@ WRITE_LINE_MEMBER(cedar_magnet_sound_device::fifo_dor_w) // combined with a clock signal and used to drive ctc0 channel 3 } -#if 0 static const z80_daisy_config daisy_chain[] = { { "ctc1" }, { "ctc0" }, -// soundlatch from main CPU needs to be able to generate a vector too? { nullptr } }; -#endif TIMER_CALLBACK_MEMBER(cedar_magnet_sound_device::reset_assert_callback) { @@ -169,7 +163,7 @@ static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound ) MCFG_CPU_ADD("topcpu", Z80, 4000000) MCFG_CPU_PROGRAM_MAP(cedar_magnet_sound_map) MCFG_CPU_IO_MAP(cedar_magnet_sound_io) -// MCFG_Z80_DAISY_CHAIN(daisy_chain) + MCFG_Z80_DAISY_CHAIN(daisy_chain) MCFG_CPU_PERIODIC_INT_DRIVER(cedar_magnet_sound_device, fake_irq, 4*60) MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000) @@ -184,6 +178,13 @@ static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound ) MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z1_w)) MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z2_w)) +#if 0 // does nothing useful now + MCFG_DEVICE_ADD("ck1mhz", CLOCK, 4000000/4) + MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("ctc1", z80ctc_device, trg0)) + MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("ctc1", z80ctc_device, trg1)) + MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("ctc1", z80ctc_device, trg2)) +#endif + MCFG_SPEAKER_STANDARD_MONO("mono") MCFG_SOUND_ADD("aysnd0", AY8910, 4000000/2)