Merge pull request #1888 from ajrhacker/z80_intack

Z80 daisy chain stuff
This commit is contained in:
R. Belmont 2016-12-29 16:35:46 -05:00 committed by GitHub
commit 2b74e4c0be
7 changed files with 39 additions and 66 deletions

View File

@ -306,13 +306,9 @@ 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
device_z80daisy_interface *intf = daisy_get_irq_device();
irq_vector = (intf != nullptr) ? intf->z80daisy_irq_ack() : standard_irq_callback_member(*this, 0);
LOG(("Z180 '%s' single int. irq_vector $%02x\n", tag(), irq_vector));

View File

@ -3146,32 +3146,28 @@ 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
device_z80daisy_interface *intf = daisy_get_irq_device();
int irq_vector = (intf != nullptr) ? intf->z80daisy_irq_ack() : standard_irq_callback_member(*this, 0);
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,8 +3411,6 @@ 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);
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
@ -164,25 +166,24 @@ int z80_daisy_chain_interface::daisy_update_irq_state()
//-------------------------------------------------
// call_ack_device - acknowledge an interrupt
// from a chained device and return the vector
// daisy_get_irq_device - return the device
// in the chain that requested the interrupt
//-------------------------------------------------
int z80_daisy_chain_interface::daisy_call_ack_device()
device_z80daisy_interface *z80_daisy_chain_interface::daisy_get_irq_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;
}
//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");
return nullptr;
}
@ -204,7 +205,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

@ -97,7 +97,7 @@ protected:
// callbacks
int daisy_update_irq_state();
int daisy_call_ack_device();
device_z80daisy_interface *daisy_get_irq_device();
void daisy_call_reti_device();
private:

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)
{
@ -153,37 +147,31 @@ TIMER_CALLBACK_MEMBER(cedar_magnet_sound_device::reset_assert_callback)
INTERRUPT_GEN_MEMBER(cedar_magnet_sound_device::fake_irq)
{
// these should be coming from the CTC...
// if (m_fake_counter==0) m_cpu->set_input_line_and_vector(0, HOLD_LINE,0xe6);
// if (m_fake_counter==1) m_cpu->set_input_line_and_vector(0, HOLD_LINE,0xee);
if (m_fake_counter==2) m_cpu->set_input_line_and_vector(0, HOLD_LINE,0xf6); // drives the AY, should be from ctc1 4th counter?
m_fake_counter++;
if (m_fake_counter == 4) m_fake_counter = 0;
}
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_CPU_PERIODIC_INT_DRIVER(cedar_magnet_sound_device, fake_irq, 4*60)
MCFG_Z80_DAISY_CHAIN(daisy_chain)
MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000)
// MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z0_w))
MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z1_w))
MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z2_w))
MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000)
// MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z0_w))
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)
@ -216,6 +204,5 @@ void cedar_magnet_sound_device::device_start()
void cedar_magnet_sound_device::device_reset()
{
m_command = 0;
m_fake_counter = 0;
cedar_magnet_board_device::device_reset();
}

View File

@ -49,9 +49,6 @@ public:
TIMER_CALLBACK_MEMBER(reset_assert_callback) override;
int m_fake_counter;
INTERRUPT_GEN_MEMBER(fake_irq);
protected:
virtual machine_config_constructor device_mconfig_additions() const override;
virtual void device_start() override;