diff --git a/src/emu/machine/6525tpi.c b/src/emu/machine/6525tpi.c index 226705b2316..cebc31f2d04 100644 --- a/src/emu/machine/6525tpi.c +++ b/src/emu/machine/6525tpi.c @@ -74,7 +74,6 @@ #include "emu.h" #include "6525tpi.h" -#include "devlegcy.h" /*************************************************************************** @@ -93,536 +92,39 @@ } while (0) -#define INTERRUPT_MODE (tpi6525->cr & 1) -#define PRIORIZED_INTERRUPTS (tpi6525->cr & 2) -#define INTERRUPT3_RISING_EDGE (tpi6525->cr & 4) -#define INTERRUPT4_RISING_EDGE (tpi6525->cr & 8) -#define CA_MANUAL_OUT (tpi6525->cr & 0x20) -#define CA_MANUAL_LEVEL ((tpi6525->cr & 0x10) ? 1 : 0) -#define CB_MANUAL_OUT (tpi6525->cr & 0x80) -#define CB_MANUAL_LEVEL ((tpi6525->cr & 0x40) ? 1 : 0) +#define INTERRUPT_MODE (m_cr & 1) +#define PRIORIZED_INTERRUPTS (m_cr & 2) +#define INTERRUPT3_RISING_EDGE (m_cr & 4) +#define INTERRUPT4_RISING_EDGE (m_cr & 8) +#define CA_MANUAL_OUT (m_cr & 0x20) +#define CA_MANUAL_LEVEL ((m_cr & 0x10) ? 1 : 0) +#define CB_MANUAL_OUT (m_cr & 0x80) +#define CB_MANUAL_LEVEL ((m_cr & 0x40) ? 1 : 0) -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ - -struct tpi6525_state -{ - devcb_resolved_write_line out_irq_func; - devcb_resolved_read8 in_pa_func; - devcb_resolved_write8 out_pa_func; - devcb_resolved_read8 in_pb_func; - devcb_resolved_write8 out_pb_func; - devcb_resolved_read8 in_pc_func; - devcb_resolved_write8 out_pc_func; - devcb_resolved_write_line out_ca_func; - devcb_resolved_write_line out_cb_func; - - UINT8 port_a, ddr_a, in_a; - UINT8 port_b, ddr_b, in_b; - UINT8 port_c, ddr_c, in_c; - - UINT8 ca_level, cb_level, interrupt_level; - - UINT8 cr; - UINT8 air; - - UINT8 irq_level[5]; -}; - - -/***************************************************************************** - INLINE FUNCTIONS -*****************************************************************************/ - -INLINE tpi6525_state *get_safe_token(device_t *device) -{ - assert(device != NULL); - assert(device->type() == TPI6525); - - return (tpi6525_state *)downcast(device)->token(); -} - - -/***************************************************************************** - DEVICE INTERFACE -*****************************************************************************/ - -static DEVICE_START( tpi6525 ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - const tpi6525_interface *intf = (const tpi6525_interface*)device->static_config(); - - // resolve callbacks - tpi6525->out_irq_func.resolve(intf->out_irq_func, *device); - tpi6525->in_pa_func.resolve(intf->in_pa_func, *device); - tpi6525->out_pa_func.resolve(intf->out_pa_func, *device); - tpi6525->in_pb_func.resolve(intf->in_pb_func, *device); - tpi6525->out_pb_func.resolve(intf->out_pb_func, *device); - tpi6525->in_pc_func.resolve(intf->in_pc_func, *device); - tpi6525->out_pc_func.resolve(intf->out_pc_func, *device); - tpi6525->out_ca_func.resolve(intf->out_ca_func, *device); - tpi6525->out_cb_func.resolve(intf->out_cb_func, *device); - - /* verify that we have an interface assigned */ - assert(device->static_config() != NULL); - - /* register for state saving */ - device->save_item(NAME(tpi6525->port_a)); - device->save_item(NAME(tpi6525->ddr_a)); - device->save_item(NAME(tpi6525->in_a)); - device->save_item(NAME(tpi6525->port_b)); - device->save_item(NAME(tpi6525->ddr_b)); - device->save_item(NAME(tpi6525->in_b)); - device->save_item(NAME(tpi6525->port_c)); - device->save_item(NAME(tpi6525->ddr_c)); - device->save_item(NAME(tpi6525->in_c)); - device->save_item(NAME(tpi6525->ca_level)); - device->save_item(NAME(tpi6525->cb_level)); - device->save_item(NAME(tpi6525->interrupt_level)); - device->save_item(NAME(tpi6525->cr)); - device->save_item(NAME(tpi6525->air)); - device->save_item(NAME(tpi6525->irq_level)); -} - - -static DEVICE_RESET( tpi6525 ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - /* setup some initial values */ - tpi6525->in_a = 0xff; - tpi6525->in_b = 0xff; - tpi6525->in_c = 0xff; -} - -/*************************************************************************** - IMPLEMENTATION -***************************************************************************/ - -static void tpi6525_set_interrupt(device_t *device) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - if (!tpi6525->interrupt_level && (tpi6525->air != 0)) - { - tpi6525->interrupt_level = 1; - - DBG_LOG(device->machine(), 3, "tpi6525", ("%s set interrupt\n", device->tag())); - - tpi6525->out_irq_func(tpi6525->interrupt_level); - } -} - - -static void tpi6525_clear_interrupt(device_t *device) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - if (tpi6525->interrupt_level && (tpi6525->air == 0)) - { - tpi6525->interrupt_level = 0; - - DBG_LOG(device->machine(), 3, "tpi6525", ("%s clear interrupt\n", device->tag())); - - tpi6525->out_irq_func(tpi6525->interrupt_level); - } -} - - -WRITE_LINE_DEVICE_HANDLER( tpi6525_i0_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - if (INTERRUPT_MODE && (state != tpi6525->irq_level[0])) - { - tpi6525->irq_level[0] = state; - - if ((state == 0) && !(tpi6525->air & 1) && (tpi6525->ddr_c & 1)) - { - tpi6525->air |= 1; - tpi6525_set_interrupt(device); - } - } -} - - -WRITE_LINE_DEVICE_HANDLER( tpi6525_i1_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - if (INTERRUPT_MODE && (state != tpi6525->irq_level[1])) - { - tpi6525->irq_level[1] = state; - - if ((state == 0) && !(tpi6525->air & 2) && (tpi6525->ddr_c & 2)) - { - tpi6525->air |= 2; - tpi6525_set_interrupt(device); - } - } -} - - -WRITE_LINE_DEVICE_HANDLER( tpi6525_i2_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - if (INTERRUPT_MODE && (state != tpi6525->irq_level[2])) - { - tpi6525->irq_level[2] = state; - - if ((state == 0) && !(tpi6525->air & 4) && (tpi6525->ddr_c & 4)) - { - tpi6525->air |= 4; - tpi6525_set_interrupt(device); - } - } -} - - -WRITE_LINE_DEVICE_HANDLER( tpi6525_i3_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - if (INTERRUPT_MODE && (state != tpi6525->irq_level[3])) - { - tpi6525->irq_level[3] = state; - - if (((INTERRUPT3_RISING_EDGE && (state == 1)) - || (!INTERRUPT3_RISING_EDGE && (state == 0))) - && !(tpi6525->air & 8) && (tpi6525->ddr_c & 8)) - { - tpi6525->air |= 8; - tpi6525_set_interrupt(device); - } - } -} - - -WRITE_LINE_DEVICE_HANDLER( tpi6525_i4_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - if (INTERRUPT_MODE && (state != tpi6525->irq_level[4]) ) - { - tpi6525->irq_level[4] = state; - - if (((INTERRUPT4_RISING_EDGE && (state == 1)) - ||(!INTERRUPT4_RISING_EDGE&&(state == 0))) - && !(tpi6525->air & 0x10) && (tpi6525->ddr_c & 0x10)) - { - tpi6525->air |= 0x10; - tpi6525_set_interrupt(device); - } - } -} - -WRITE_LINE_MEMBER( tpi6525_device::i0_w ) { tpi6525_i0_w(this, state); } -WRITE_LINE_MEMBER( tpi6525_device::i1_w ) { tpi6525_i1_w(this, state); } -WRITE_LINE_MEMBER( tpi6525_device::i2_w ) { tpi6525_i2_w(this, state); } -WRITE_LINE_MEMBER( tpi6525_device::i3_w ) { tpi6525_i3_w(this, state); } -WRITE_LINE_MEMBER( tpi6525_device::i4_w ) { tpi6525_i4_w(this, state); } - - -READ8_DEVICE_HANDLER( tpi6525_porta_r ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - UINT8 data = tpi6525->in_a; - - if (!tpi6525->in_pa_func.isnull()) - data = tpi6525->in_pa_func(offset); - - data = (data & ~tpi6525->ddr_a) | (tpi6525->ddr_a & tpi6525->port_a); - - return data; -} - - -WRITE8_DEVICE_HANDLER( tpi6525_porta_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - tpi6525->in_a = data; -} - - -READ8_DEVICE_HANDLER( tpi6525_portb_r ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - UINT8 data = tpi6525->in_b; - - if (!tpi6525->in_pb_func.isnull()) - data = tpi6525->in_pb_func(offset); - - data = (data & ~tpi6525->ddr_b) | (tpi6525->ddr_b & tpi6525->port_b); - - return data; -} - - -WRITE8_DEVICE_HANDLER( tpi6525_portb_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - tpi6525->in_b = data; -} - - -READ8_DEVICE_HANDLER( tpi6525_portc_r ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - UINT8 data = tpi6525->in_c; - - if (!tpi6525->in_pc_func.isnull()) - data &= tpi6525->in_pc_func(offset); - - data = (data & ~tpi6525->ddr_c) | (tpi6525->ddr_c & tpi6525->port_c); - - return data; -} - - -WRITE8_DEVICE_HANDLER( tpi6525_portc_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - tpi6525->in_c = data; -} - - -READ8_MEMBER( tpi6525_device::pa_r ) { return tpi6525_porta_r(this, space, 0); } -READ8_MEMBER( tpi6525_device::pb_r ) { return tpi6525_portb_r(this, space, 0); } -READ8_MEMBER( tpi6525_device::pc_r ) { return tpi6525_portc_r(this, space, 0); } - - -READ8_DEVICE_HANDLER( tpi6525_r ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - UINT8 data = 0xff; - - switch (offset & 7) - { - case 0: - data = tpi6525->in_a; - - if (!tpi6525->in_pa_func.isnull()) - data &= tpi6525->in_pa_func(0); - - data = (data & ~tpi6525->ddr_a) | (tpi6525->ddr_a & tpi6525->port_a); - - break; - - case 1: - data = tpi6525->in_b; - - if (!tpi6525->in_pb_func.isnull()) - data &= tpi6525->in_pb_func(0); - - data = (data & ~tpi6525->ddr_b) | (tpi6525->ddr_b & tpi6525->port_b); - - break; - - case 2: - if (INTERRUPT_MODE) - { - data = 0; - - if (tpi6525->irq_level[0]) data |= 0x01; - if (tpi6525->irq_level[1]) data |= 0x02; - if (tpi6525->irq_level[2]) data |= 0x04; - if (tpi6525->irq_level[3]) data |= 0x08; - if (tpi6525->irq_level[4]) data |= 0x10; - if (!tpi6525->interrupt_level) data |= 0x20; - if (tpi6525->ca_level) data |= 0x40; - if (tpi6525->cb_level) data |= 0x80; - } - else - { - data = tpi6525->in_c; - - if (!tpi6525->in_pc_func.isnull()) - data &= tpi6525->in_pc_func(0); - - data = (data & ~tpi6525->ddr_c) | (tpi6525->ddr_c & tpi6525->port_c); - } - - DBG_LOG(device->machine(), 2, "tpi6525", ("%s read %.2x %.2x\n", device->tag(), offset, data)); - break; - - case 3: - data = tpi6525->ddr_a; - break; - - case 4: - data = tpi6525->ddr_b; - break; - - case 5: - data = tpi6525->ddr_c; - break; - - case 6: - data = tpi6525->cr; - break; - - case 7: /* air */ - if (PRIORIZED_INTERRUPTS) - { - if (tpi6525->air & 0x10) - { - data = 0x10; - tpi6525->air &= ~0x10; - } - else if (tpi6525->air & 8) - { - data = 8; - tpi6525->air &= ~8; - } - else if (tpi6525->air & 4) - { - data = 4; - tpi6525->air &= ~4; - } - else if (tpi6525->air & 2) - { - data = 2; - tpi6525->air &= ~2; - } - else if (tpi6525->air & 1) - { - data = 1; - tpi6525->air &= ~1; - } - } - else - { - data = tpi6525->air; - tpi6525->air = 0; - } - - tpi6525_clear_interrupt(device); - break; - - } - - DBG_LOG(device->machine(), 3, "tpi6525", ("%s read %.2x %.2x\n", device->tag(), offset, data)); - - return data; -} - -READ8_MEMBER( tpi6525_device::read ) -{ - return tpi6525_r(this, space, offset); -} - - -WRITE8_DEVICE_HANDLER( tpi6525_w ) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - - DBG_LOG(device->machine(), 2, "tpi6525", ("%s write %.2x %.2x\n", device->tag(), offset, data)); - - switch (offset & 7) - { - case 0: - tpi6525->port_a = data; - tpi6525->out_pa_func(0, (tpi6525->port_a & tpi6525->ddr_a) | (tpi6525->ddr_a ^ 0xff)); - break; - - case 1: - tpi6525->port_b = data; - tpi6525->out_pb_func(0, (tpi6525->port_b & tpi6525->ddr_b) | (tpi6525->ddr_b ^ 0xff)); - break; - - case 2: - tpi6525->port_c = data; - - if (!INTERRUPT_MODE) - tpi6525->out_pc_func(0, (tpi6525->port_c & tpi6525->ddr_c) | (tpi6525->ddr_c ^ 0xff)); - break; - - case 3: - tpi6525->ddr_a = data; - tpi6525->out_pa_func(0, (tpi6525->port_a & tpi6525->ddr_a) | (tpi6525->ddr_a ^ 0xff)); - break; - - case 4: - tpi6525->ddr_b = data; - tpi6525->out_pb_func(0, (tpi6525->port_b & tpi6525->ddr_b) | (tpi6525->ddr_b ^ 0xff)); - break; - - case 5: - tpi6525->ddr_c = data; - - if (!INTERRUPT_MODE) - tpi6525->out_pc_func(0, (tpi6525->port_c & tpi6525->ddr_c) | (tpi6525->ddr_c ^ 0xff)); - break; - - case 6: - tpi6525->cr = data; - - if (INTERRUPT_MODE) - { - if (CA_MANUAL_OUT) - { - if (tpi6525->ca_level != CA_MANUAL_LEVEL) - { - tpi6525->ca_level = CA_MANUAL_LEVEL; - tpi6525->out_ca_func(tpi6525->ca_level); - } - } - if (CB_MANUAL_OUT) - { - if (tpi6525->cb_level != CB_MANUAL_LEVEL) - { - tpi6525->cb_level = CB_MANUAL_LEVEL; - tpi6525->out_cb_func(tpi6525->cb_level); - } - } - } - - break; - - case 7: - /* tpi6525->air = data; */ - break; - } -} - -WRITE8_MEMBER( tpi6525_device::write ) -{ - tpi6525_w(this, space, offset, data); -} - - -/* this should probably be done better, needed for amigacd.c */ - -UINT8 tpi6525_get_ddr_a(device_t *device) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - return tpi6525->ddr_a; -} - -UINT8 tpi6525_get_ddr_b(device_t *device) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - return tpi6525->ddr_b; -} - -UINT8 tpi6525_get_ddr_c(device_t *device) -{ - tpi6525_state *tpi6525 = get_safe_token(device); - return tpi6525->ddr_c; -} - const device_type TPI6525 = &device_creator; tpi6525_device::tpi6525_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) - : device_t(mconfig, TPI6525, "6525 TPI", tag, owner, clock, "tpi6525", __FILE__) + : device_t(mconfig, TPI6525, "6525 TPI", tag, owner, clock, "tpi6525", __FILE__), + m_port_a(0), + m_ddr_a(0), + m_in_a(0), + m_port_b(0), + m_ddr_b(0), + m_in_b(0), + m_port_c(0), + m_ddr_c(0), + m_in_c(0), + m_ca_level(0), + m_cb_level(0), + m_interrupt_level(0), + m_cr(0), + m_air(0) { - m_token = global_alloc_clear(tpi6525_state); + for (int i = 0; i < 5; i++) + { + m_irq_level[i] = 0; + } } //------------------------------------------------- @@ -633,6 +135,24 @@ tpi6525_device::tpi6525_device(const machine_config &mconfig, const char *tag, d void tpi6525_device::device_config_complete() { + // inherit a copy of the static data + const tpi6525_interface *intf = reinterpret_cast(static_config()); + if (intf != NULL) + *static_cast(this) = *intf; + + // or initialize to defaults if none provided + else + { + memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb)); + memset(&m_in_pa_cb, 0, sizeof(m_in_pa_cb)); + memset(&m_out_pa_cb, 0, sizeof(m_out_pa_cb)); + memset(&m_in_pb_cb, 0, sizeof(m_in_pb_cb)); + memset(&m_out_pb_cb, 0, sizeof(m_out_pb_cb)); + memset(&m_in_pc_cb, 0, sizeof(m_in_pc_cb)); + memset(&m_out_pc_cb, 0, sizeof(m_out_pc_cb)); + memset(&m_out_ca_cb, 0, sizeof(m_out_ca_cb)); + memset(&m_out_cb_cb, 0, sizeof(m_out_cb_cb)); + } } //------------------------------------------------- @@ -641,7 +161,33 @@ void tpi6525_device::device_config_complete() void tpi6525_device::device_start() { - DEVICE_START_NAME( tpi6525 )(this); + // resolve callbacks + m_out_irq_func.resolve(m_out_irq_cb, *this); + m_in_pa_func.resolve(m_in_pa_cb, *this); + m_out_pa_func.resolve(m_out_pa_cb, *this); + m_in_pb_func.resolve(m_in_pb_cb, *this); + m_out_pb_func.resolve(m_out_pb_cb, *this); + m_in_pc_func.resolve(m_in_pc_cb, *this); + m_out_pc_func.resolve(m_out_pc_cb, *this); + m_out_ca_func.resolve(m_out_ca_cb, *this); + m_out_cb_func.resolve(m_out_cb_cb, *this); + + /* register for state saving */ + save_item(NAME(m_port_a)); + save_item(NAME(m_ddr_a)); + save_item(NAME(m_in_a)); + save_item(NAME(m_port_b)); + save_item(NAME(m_ddr_b)); + save_item(NAME(m_in_b)); + save_item(NAME(m_port_c)); + save_item(NAME(m_ddr_c)); + save_item(NAME(m_in_c)); + save_item(NAME(m_ca_level)); + save_item(NAME(m_cb_level)); + save_item(NAME(m_interrupt_level)); + save_item(NAME(m_cr)); + save_item(NAME(m_air)); + save_item(NAME(m_irq_level)); } //------------------------------------------------- @@ -650,5 +196,377 @@ void tpi6525_device::device_start() void tpi6525_device::device_reset() { - DEVICE_RESET_NAME( tpi6525 )(this); + /* setup some initial values */ + m_in_a = 0xff; + m_in_b = 0xff; + m_in_c = 0xff; +} + + +/*************************************************************************** + IMPLEMENTATION +***************************************************************************/ + +void tpi6525_device::set_interrupt() +{ + if (!m_interrupt_level && (m_air != 0)) + { + m_interrupt_level = 1; + + DBG_LOG(machine(), 3, "tpi6525", ("%s set interrupt\n", tag())); + + m_out_irq_func(m_interrupt_level); + } +} + + +void tpi6525_device::clear_interrupt() +{ + if (m_interrupt_level && (m_air == 0)) + { + m_interrupt_level = 0; + + DBG_LOG(machine(), 3, "tpi6525", ("%s clear interrupt\n", tag())); + + m_out_irq_func(m_interrupt_level); + } +} + + +WRITE_LINE_MEMBER( tpi6525_device::i0_w ) +{ + if (INTERRUPT_MODE && (state != m_irq_level[0])) + { + m_irq_level[0] = state; + + if ((state == 0) && !(m_air & 1) && (m_ddr_c & 1)) + { + m_air |= 1; + set_interrupt(); + } + } +} + + +WRITE_LINE_MEMBER( tpi6525_device::i1_w ) +{ + if (INTERRUPT_MODE && (state != m_irq_level[1])) + { + m_irq_level[1] = state; + + if ((state == 0) && !(m_air & 2) && (m_ddr_c & 2)) + { + m_air |= 2; + set_interrupt(); + } + } +} + + +WRITE_LINE_MEMBER( tpi6525_device::i2_w ) +{ + if (INTERRUPT_MODE && (state != m_irq_level[2])) + { + m_irq_level[2] = state; + + if ((state == 0) && !(m_air & 4) && (m_ddr_c & 4)) + { + m_air |= 4; + set_interrupt(); + } + } +} + + +WRITE_LINE_MEMBER( tpi6525_device::i3_w ) +{ + if (INTERRUPT_MODE && (state != m_irq_level[3])) + { + m_irq_level[3] = state; + + if (((INTERRUPT3_RISING_EDGE && (state == 1)) + || (!INTERRUPT3_RISING_EDGE && (state == 0))) + && !(m_air & 8) && (m_ddr_c & 8)) + { + m_air |= 8; + set_interrupt(); + } + } +} + + +WRITE_LINE_MEMBER( tpi6525_device::i4_w ) +{ + if (INTERRUPT_MODE && (state != m_irq_level[4]) ) + { + m_irq_level[4] = state; + + if (((INTERRUPT4_RISING_EDGE && (state == 1)) + ||(!INTERRUPT4_RISING_EDGE&&(state == 0))) + && !(m_air & 0x10) && (m_ddr_c & 0x10)) + { + m_air |= 0x10; + set_interrupt(); + } + } +} + +READ8_MEMBER( tpi6525_device::pa_r ) +{ + UINT8 data = m_in_a; + + if (!m_in_pa_func.isnull()) + data = m_in_pa_func(offset); + + data = (data & ~m_ddr_a) | (m_ddr_a & m_port_a); + + return data; +} + + +WRITE8_MEMBER( tpi6525_device::pa_w ) +{ + m_in_a = data; +} + + +READ8_MEMBER( tpi6525_device::pb_r ) +{ + UINT8 data = m_in_b; + + if (!m_in_pb_func.isnull()) + data = m_in_pb_func(offset); + + data = (data & ~m_ddr_b) | (m_ddr_b & m_port_b); + + return data; +} + + +WRITE8_MEMBER( tpi6525_device::pb_w ) +{ + m_in_b = data; +} + + +READ8_MEMBER( tpi6525_device::pc_r ) +{ + UINT8 data = m_in_c; + + if (!m_in_pc_func.isnull()) + data &= m_in_pc_func(offset); + + data = (data & ~m_ddr_c) | (m_ddr_c & m_port_c); + + return data; +} + + +WRITE8_MEMBER( tpi6525_device::pc_w ) +{ + m_in_c = data; +} + + +READ8_MEMBER( tpi6525_device::read ) +{ + UINT8 data = 0xff; + + switch (offset & 7) + { + case 0: + data = m_in_a; + + if (!m_in_pa_func.isnull()) + data &= m_in_pa_func(0); + + data = (data & ~m_ddr_a) | (m_ddr_a & m_port_a); + + break; + + case 1: + data = m_in_b; + + if (!m_in_pb_func.isnull()) + data &= m_in_pb_func(0); + + data = (data & ~m_ddr_b) | (m_ddr_b & m_port_b); + + break; + + case 2: + if (INTERRUPT_MODE) + { + data = 0; + + if (m_irq_level[0]) data |= 0x01; + if (m_irq_level[1]) data |= 0x02; + if (m_irq_level[2]) data |= 0x04; + if (m_irq_level[3]) data |= 0x08; + if (m_irq_level[4]) data |= 0x10; + if (!m_interrupt_level) data |= 0x20; + if (m_ca_level) data |= 0x40; + if (m_cb_level) data |= 0x80; + } + else + { + data = m_in_c; + + if (!m_in_pc_func.isnull()) + data &= m_in_pc_func(0); + + data = (data & ~m_ddr_c) | (m_ddr_c & m_port_c); + } + + DBG_LOG(machine(), 2, "tpi6525", ("%s read %.2x %.2x\n", tag(), offset, data)); + break; + + case 3: + data = m_ddr_a; + break; + + case 4: + data = m_ddr_b; + break; + + case 5: + data = m_ddr_c; + break; + + case 6: + data = m_cr; + break; + + case 7: /* air */ + if (PRIORIZED_INTERRUPTS) + { + if (m_air & 0x10) + { + data = 0x10; + m_air &= ~0x10; + } + else if (m_air & 8) + { + data = 8; + m_air &= ~8; + } + else if (m_air & 4) + { + data = 4; + m_air &= ~4; + } + else if (m_air & 2) + { + data = 2; + m_air &= ~2; + } + else if (m_air & 1) + { + data = 1; + m_air &= ~1; + } + } + else + { + data = m_air; + m_air = 0; + } + + clear_interrupt(); + break; + + } + + DBG_LOG(machine(), 3, "tpi6525", ("%s read %.2x %.2x\n", tag(), offset, data)); + + return data; +} + + +WRITE8_MEMBER( tpi6525_device::write ) +{ + DBG_LOG(machine(), 2, "tpi6525", ("%s write %.2x %.2x\n", tag(), offset, data)); + + switch (offset & 7) + { + case 0: + m_port_a = data; + m_out_pa_func(0, (m_port_a & m_ddr_a) | (m_ddr_a ^ 0xff)); + break; + + case 1: + m_port_b = data; + m_out_pb_func(0, (m_port_b & m_ddr_b) | (m_ddr_b ^ 0xff)); + break; + + case 2: + m_port_c = data; + + if (!INTERRUPT_MODE) + m_out_pc_func(0, (m_port_c & m_ddr_c) | (m_ddr_c ^ 0xff)); + break; + + case 3: + m_ddr_a = data; + m_out_pa_func(0, (m_port_a & m_ddr_a) | (m_ddr_a ^ 0xff)); + break; + + case 4: + m_ddr_b = data; + m_out_pb_func(0, (m_port_b & m_ddr_b) | (m_ddr_b ^ 0xff)); + break; + + case 5: + m_ddr_c = data; + + if (!INTERRUPT_MODE) + m_out_pc_func(0, (m_port_c & m_ddr_c) | (m_ddr_c ^ 0xff)); + break; + + case 6: + m_cr = data; + + if (INTERRUPT_MODE) + { + if (CA_MANUAL_OUT) + { + if (m_ca_level != CA_MANUAL_LEVEL) + { + m_ca_level = CA_MANUAL_LEVEL; + m_out_ca_func(m_ca_level); + } + } + if (CB_MANUAL_OUT) + { + if (m_cb_level != CB_MANUAL_LEVEL) + { + m_cb_level = CB_MANUAL_LEVEL; + m_out_cb_func(m_cb_level); + } + } + } + + break; + + case 7: + /* m_air = data; */ + break; + } +} + +/* this should probably be done better, needed for amigacd.c */ + +UINT8 tpi6525_device::get_ddr_a() +{ + return m_ddr_a; +} + +UINT8 tpi6525_device::get_ddr_b() +{ + return m_ddr_b; +} + +UINT8 tpi6525_device::get_ddr_c() +{ + return m_ddr_c; } diff --git a/src/emu/machine/6525tpi.h b/src/emu/machine/6525tpi.h index 3f3aa35bd91..c0f6d1a484e 100644 --- a/src/emu/machine/6525tpi.h +++ b/src/emu/machine/6525tpi.h @@ -36,19 +36,19 @@ struct tpi6525_interface { - devcb_write_line out_irq_func; + devcb_write_line m_out_irq_cb; - devcb_read8 in_pa_func; - devcb_write8 out_pa_func; + devcb_read8 m_in_pa_cb; + devcb_write8 m_out_pa_cb; - devcb_read8 in_pb_func; - devcb_write8 out_pb_func; + devcb_read8 m_in_pb_cb; + devcb_write8 m_out_pb_cb; - devcb_read8 in_pc_func; - devcb_write8 out_pc_func; + devcb_read8 m_in_pc_cb; + devcb_write8 m_out_pc_cb; - devcb_write_line out_ca_func; - devcb_write_line out_cb_func; + devcb_write_line m_out_ca_cb; + devcb_write_line m_out_cb_cb; }; @@ -56,14 +56,12 @@ struct tpi6525_interface DEVICE CONFIGURATION MACROS ***************************************************************************/ -class tpi6525_device : public device_t +class tpi6525_device : public device_t, + public tpi6525_interface { public: tpi6525_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); - ~tpi6525_device() { global_free(m_token); } - - // access to legacy token - void *token() const { assert(m_token != NULL); return m_token; } + ~tpi6525_device() {} DECLARE_READ8_MEMBER( read ); DECLARE_WRITE8_MEMBER( write ); @@ -77,15 +75,45 @@ public: DECLARE_READ8_MEMBER( pa_r ); DECLARE_READ8_MEMBER( pb_r ); DECLARE_READ8_MEMBER( pc_r ); + DECLARE_WRITE8_MEMBER( pa_w ); + DECLARE_WRITE8_MEMBER( pb_w ); + DECLARE_WRITE8_MEMBER( pc_w ); + + UINT8 get_ddr_a(); + UINT8 get_ddr_b(); + UINT8 get_ddr_c(); protected: // device-level overrides virtual void device_config_complete(); virtual void device_start(); virtual void device_reset(); + private: // internal state - void *m_token; + devcb_resolved_write_line m_out_irq_func; + devcb_resolved_read8 m_in_pa_func; + devcb_resolved_write8 m_out_pa_func; + devcb_resolved_read8 m_in_pb_func; + devcb_resolved_write8 m_out_pb_func; + devcb_resolved_read8 m_in_pc_func; + devcb_resolved_write8 m_out_pc_func; + devcb_resolved_write_line m_out_ca_func; + devcb_resolved_write_line m_out_cb_func; + + UINT8 m_port_a, m_ddr_a, m_in_a; + UINT8 m_port_b, m_ddr_b, m_in_b; + UINT8 m_port_c, m_ddr_c, m_in_c; + + UINT8 m_ca_level, m_cb_level, m_interrupt_level; + + UINT8 m_cr; + UINT8 m_air; + + UINT8 m_irq_level[5]; + + void set_interrupt(); + void clear_interrupt(); }; extern const device_type TPI6525; @@ -96,31 +124,5 @@ extern const device_type TPI6525; MCFG_DEVICE_CONFIG(_intrf) -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ - -DECLARE_READ8_DEVICE_HANDLER( tpi6525_r ); -DECLARE_WRITE8_DEVICE_HANDLER( tpi6525_w ); - -DECLARE_READ8_DEVICE_HANDLER( tpi6525_porta_r ); -DECLARE_WRITE8_DEVICE_HANDLER( tpi6525_porta_w ); - -DECLARE_READ8_DEVICE_HANDLER( tpi6525_portb_r ); -DECLARE_WRITE8_DEVICE_HANDLER( tpi6525_portb_w ); - -DECLARE_READ8_DEVICE_HANDLER( tpi6525_portc_r ); -DECLARE_WRITE8_DEVICE_HANDLER( tpi6525_portc_w ); - -WRITE_LINE_DEVICE_HANDLER( tpi6525_i0_w ); -WRITE_LINE_DEVICE_HANDLER( tpi6525_i1_w ); -WRITE_LINE_DEVICE_HANDLER( tpi6525_i2_w ); -WRITE_LINE_DEVICE_HANDLER( tpi6525_i3_w ); -WRITE_LINE_DEVICE_HANDLER( tpi6525_i4_w ); - -UINT8 tpi6525_get_ddr_a(device_t *device); -UINT8 tpi6525_get_ddr_b(device_t *device); -UINT8 tpi6525_get_ddr_c(device_t *device); - #endif /* __TPI6525_H__ */ diff --git a/src/mess/machine/amigacd.c b/src/mess/machine/amigacd.c index 989426b8523..2785c3a5455 100644 --- a/src/mess/machine/amigacd.c +++ b/src/mess/machine/amigacd.c @@ -216,9 +216,9 @@ static READ16_HANDLER( amiga_dmac_r ) case 0x66: case 0x67: { - device_t *tpi = space.machine().device("tpi6525"); + tpi6525_device *tpi = space.machine().device("tpi6525"); LOG(( "DMAC: PC=%08x - TPI6525 Read(%d)\n", space.device().safe_pc(), (offset - 0x58) )); - return tpi6525_r(tpi, space, offset - 0x58); + return tpi->read(space, offset - 0x58); } break; @@ -343,9 +343,9 @@ static WRITE16_HANDLER( amiga_dmac_w ) case 0x66: case 0x67: { - device_t *tpi = space.machine().device("tpi6525"); + tpi6525_device *tpi = space.machine().device("tpi6525"); LOG(( "DMAC: PC=%08x - TPI6525 Write(%d) - data = %04x\n", space.device().safe_pc(), (offset - 0x58), data )); - tpi6525_w(tpi, space, offset - 0x58, data); + tpi->write(space, offset - 0x58, data); } break; @@ -431,13 +431,15 @@ static const amiga_autoconfig_device dmac_device = READ8_DEVICE_HANDLER( amigacd_tpi6525_portc_r ) { int ret = 0; + + tpi6525_device *tpi = space.machine().device("tpi6525"); - if ( (tpi6525_get_ddr_c(device) & 0x04) == 0 ) /* if pin 2 is set to input */ + if ( (tpi->get_ddr_c() & 0x04) == 0 ) /* if pin 2 is set to input */ { ret |= matsucd_stch_r() ? 0x00 : 0x04; /* read status change signal */ } - if ( (tpi6525_get_ddr_c(device) & 0x08) == 0 ) /* if pin 3 is set to input */ + if ( (tpi->get_ddr_c() & 0x08) == 0 ) /* if pin 3 is set to input */ ret |= matsucd_sten_r() ? 0x08 : 0x00; /* read enable signal */ return ret; @@ -445,10 +447,12 @@ READ8_DEVICE_HANDLER( amigacd_tpi6525_portc_r ) WRITE8_DEVICE_HANDLER( amigacd_tpi6525_portb_w ) { - if ( tpi6525_get_ddr_b(device) & 0x01 ) /* if pin 0 is set to output */ + tpi6525_device *tpi = space.machine().device("tpi6525"); + + if ( tpi->get_ddr_b() & 0x01 ) /* if pin 0 is set to output */ matsucd_cmd_w( data & 1 ); /* write to the /CMD signal */ - if ( tpi6525_get_ddr_b(device) & 0x02 ) /* if pin 1 is set to output */ + if ( tpi->get_ddr_b() & 0x02 ) /* if pin 1 is set to output */ matsucd_enable_w( data & 2 ); /* write to the /ENABLE signal */ } @@ -495,29 +499,29 @@ WRITE_LINE_DEVICE_HANDLER( amigacd_tpi6525_irq ) static void cdrom_status_enabled( running_machine &machine, int level ) { - device_t *tpi = machine.device("tpi6525"); + tpi6525_device *tpi = machine.device("tpi6525"); /* PC3 on the 6525 */ - tpi6525_i3_w(tpi, level); + tpi->i3_w(level); } static void cdrom_status_change( running_machine &machine, int level ) { - device_t *tpi = machine.device("tpi6525"); + tpi6525_device *tpi = machine.device("tpi6525"); /* invert */ level = level ? 0 : 1; /* PC2 on the 6525 */ - tpi6525_i2_w(tpi, level); + tpi->i2_w(level); } static void cdrom_subcode_ready( running_machine &machine, int level ) { - device_t *tpi = machine.device("tpi6525"); + tpi6525_device *tpi = machine.device("tpi6525"); /* PC1 on the 6525 */ - tpi6525_i1_w(tpi, level); + tpi->i1_w(level); } MACHINE_START( amigacd ) diff --git a/src/mess/machine/c64/ieee488.c b/src/mess/machine/c64/ieee488.c index f3bed4c4339..d77f26bb0ce 100644 --- a/src/mess/machine/c64/ieee488.c +++ b/src/mess/machine/c64/ieee488.c @@ -226,7 +226,7 @@ UINT8 c64_ieee488_device::c64_cd_r(address_space &space, offs_t offset, UINT8 da } else if (!io2) { - data = tpi6525_r(m_tpi, space, offset & 0x07); + data = m_tpi->read(space, offset & 0x07); } return data; @@ -241,7 +241,7 @@ void c64_ieee488_device::c64_cd_w(address_space &space, offs_t offset, UINT8 dat { if (!io2) { - tpi6525_w(m_tpi, space, offset & 0x07, data); + m_tpi->write(space, offset & 0x07, data); } m_exp->cd_w(space, offset, data, sphi2, ba, roml, romh, io1, io2);