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)
This commit is contained in:
AJR 2016-12-28 18:13:08 -05:00 committed by angelosa
parent 2be714ea8c
commit b32c5200e3
7 changed files with 38 additions and 42 deletions

View File

@ -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);

View File

@ -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));

View File

@ -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 */

View File

@ -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;

View File

@ -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");
}

View File

@ -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;
};

View File

@ -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<cedar_magnet_sound_device>;
@ -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)