mirror of
https://github.com/holub/mame
synced 2025-04-26 10:13:37 +03:00
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:
parent
2be714ea8c
commit
b32c5200e3
@ -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);
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user