From 3677f57a4ab0b713f7d50b153ebafc8517524c4b Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sun, 25 Oct 2020 04:28:35 +1100 Subject: bus/a2bus: Re-wrote Apple II Parallel Interface Card emulation. --- src/devices/bus/a2bus/a2pic.cpp | 580 ++++++++++++++++++++++----------- src/devices/bus/a2bus/a2pic.h | 128 +++++--- src/devices/bus/a2bus/grapplerplus.cpp | 4 +- 3 files changed, 478 insertions(+), 234 deletions(-) diff --git a/src/devices/bus/a2bus/a2pic.cpp b/src/devices/bus/a2bus/a2pic.cpp index 21c749eb50c..c0232ea74dd 100644 --- a/src/devices/bus/a2bus/a2pic.cpp +++ b/src/devices/bus/a2bus/a2pic.cpp @@ -1,292 +1,492 @@ // license:BSD-3-Clause -// copyright-holders:R. Belmont -/********************************************************************* +// copyright-holders:Vas Crabb +#include "emu.h" +#include "a2pic.h" - a2pic.c +//#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" - Apple II Parallel Interface Card (670-0021) +namespace { -*********************************************************************/ +ROM_START(pic) + ROM_REGION(0x0200, "prom", 0) + ROM_LOAD( "341-0057.7b", 0x0000, 0x0200, CRC(0a6b084b) SHA1(de8aa285dcac88b1cc80ec9128b092833f5174b6) ) +ROM_END -#include "emu.h" -#include "a2pic.h" -/*************************************************************************** - PARAMETERS -***************************************************************************/ +INPUT_PORTS_START(pic) + PORT_START("SW1") + PORT_DIPNAME(0x07, 0x07, "Strobe Length") PORT_DIPLOCATION("SW1:1,2,3") + PORT_DIPSETTING( 0x07, "1 microsecond") + PORT_DIPSETTING( 0x06, "3 microseconds") + PORT_DIPSETTING( 0x05, "5 microseconds") + PORT_DIPSETTING( 0x04, "7 microseconds") + PORT_DIPSETTING( 0x03, "9 microseconds") + PORT_DIPSETTING( 0x02, "11 microseconds") + PORT_DIPSETTING( 0x01, "13 microseconds") + PORT_DIPSETTING( 0x00, "15 microseconds") + PORT_DIPNAME(0x08, 0x00, "Strobe Output Polarity") PORT_DIPLOCATION("SW1:4") PORT_CHANGED_MEMBER(DEVICE_SELF, a2bus_pic_device, sw1_strobe, 0) + PORT_DIPSETTING( 0x08, "Positive") + PORT_DIPSETTING( 0x00, "Negative") + PORT_DIPNAME(0x10, 0x00, "Acknowledge Input Polarity") PORT_DIPLOCATION("SW1:5") PORT_CHANGED_MEMBER(DEVICE_SELF, a2bus_pic_device, sw1_ack, 0) + PORT_DIPSETTING( 0x10, "Positive") + PORT_DIPSETTING( 0x00, "Negative") + PORT_DIPNAME(0x20, 0x20, "Firmware") PORT_DIPLOCATION("SW1:6") PORT_CHANGED_MEMBER(DEVICE_SELF, a2bus_pic_device, sw1_firmware, 0) + PORT_DIPSETTING( 0x20, "Parallel Printer") // ROM #341-0005 - auto LF after CR + PORT_DIPSETTING( 0x00, "Centronics") // ROM #341-0019 - no auto LF after CR + PORT_DIPNAME(0x40, 0x40, "Interrupt") PORT_DIPLOCATION("SW1:7") PORT_CHANGED_MEMBER(DEVICE_SELF, a2bus_pic_device, sw1_irq, 0) + PORT_DIPSETTING( 0x40, "Disabled") + PORT_DIPSETTING( 0x00, "Enabled") + + PORT_START("X") + PORT_CONFNAME(0x01, 0x01, "PROM Addressing") + PORT_CONFSETTING( 0x00, "Flat (X1)") + PORT_CONFSETTING( 0x01, "Standard (X2)") + PORT_CONFNAME(0x02, 0x02, "Data Output") PORT_CHANGED_MEMBER(DEVICE_SELF, a2bus_pic_device, x_data_out, 0) + PORT_CONFSETTING( 0x00, "Disabled (X3)") + PORT_CONFSETTING( 0x02, "Enabled (X4)") + PORT_CONFNAME(0x04, 0x04, "Character Width") PORT_CHANGED_MEMBER(DEVICE_SELF, a2bus_pic_device, x_char_width, 0) + PORT_CONFSETTING( 0x00, "7-bit (X5)") + PORT_CONFSETTING( 0x04, "8-bit (X6)") +INPUT_PORTS_END -//************************************************************************** -// GLOBAL VARIABLES -//************************************************************************** +} // anonymous namespace -DEFINE_DEVICE_TYPE(A2BUS_PIC, a2bus_pic_device, "a2pic", "Apple Parallel Interface Card") -#define PIC_ROM_REGION "pic_rom" -#define PIC_CENTRONICS_TAG "pic_ctx" -ROM_START( pic ) - ROM_REGION(0x000200, PIC_ROM_REGION, 0) - ROM_LOAD( "341-0057.bin", 0x000000, 0x000200, CRC(0d2d84ee) SHA1(bfc5b863d37e59875a6159528eb0f2b6082063b5) ) -ROM_END +DEFINE_DEVICE_TYPE(A2BUS_PIC, a2bus_pic_device, "a2pic", "Apple II Parallel Interface Card") -static INPUT_PORTS_START( pic ) - PORT_START("DSW1") - PORT_DIPNAME( 0x07, 0x00, "Strobe length (SW1-3)" ) - PORT_DIPSETTING( 0x00, "1 microsecond" ) - PORT_DIPSETTING( 0x01, "3 microseconds" ) - PORT_DIPSETTING( 0x02, "5 microseconds" ) - PORT_DIPSETTING( 0x03, "7 microseconds" ) - PORT_DIPSETTING( 0x04, "9 microseconds" ) - PORT_DIPSETTING( 0x05, "11 microseconds" ) - PORT_DIPSETTING( 0x06, "13 microseconds" ) - PORT_DIPSETTING( 0x07, "15 microseconds" ) - - PORT_DIPNAME( 0x08, 0x08, "Strobe polarity (SW4)" ) - PORT_DIPSETTING( 0x00, "Positive" ) - PORT_DIPSETTING( 0x08, "Negative" ) - - PORT_DIPNAME( 0x10, 0x10, "Acknowledge polarity (SW5)" ) - PORT_DIPSETTING( 0x00, "Positive" ) - PORT_DIPSETTING( 0x10, "Negative" ) - - PORT_DIPNAME( 0x20, 0x20, "Firmware (SW6)" ) - PORT_DIPSETTING( 0x00, "Parallel Printer (341-0005)" ) - PORT_DIPSETTING( 0x20, "Centronics (341-0019)" ) - - PORT_DIPNAME( 0x40, 0x00, "Use interrupts (SW7)" ) - PORT_DIPSETTING( 0x00, "Off" ) - PORT_DIPSETTING( 0x40, "On" ) -INPUT_PORTS_END -//------------------------------------------------- -// input_ports - device-specific input ports -//------------------------------------------------- -ioport_constructor a2bus_pic_device::device_input_ports() const +a2bus_pic_device::a2bus_pic_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, A2BUS_PIC, tag, owner, clock), + device_a2bus_card_interface(mconfig, *this), + m_printer_conn(*this, "prn"), + m_printer_out(*this, "prn_out"), + m_input_sw1(*this, "SW1"), + m_input_x(*this, "X"), + m_prom(*this, "prom"), + m_strobe_timer(nullptr), + m_firmware_base(0x0000U), + m_data_latch(0x00U), + m_autostrobe_disable(0U), + m_ack_latch(0U), + m_irq_enable(0U), + m_ack_in(1U), + m_perror_in(1U), + m_select_in(1U), + m_fault_in(1U) { - return INPUT_PORTS_NAME( pic ); } -//------------------------------------------------- -// device_add_mconfig - add device configuration -//------------------------------------------------- -void a2bus_pic_device::device_add_mconfig(machine_config &config) -{ - CENTRONICS(config, m_ctx, centronics_devices, "printer"); - m_ctx->set_data_input_buffer(m_ctx_data_in); - m_ctx->ack_handler().set(FUNC(a2bus_pic_device::ack_w)); - - INPUT_BUFFER(config, m_ctx_data_in); - OUTPUT_LATCH(config, m_ctx_data_out); - m_ctx->set_output_latch(*m_ctx_data_out); -} -//------------------------------------------------- -// rom_region - device-specific ROM region -//------------------------------------------------- +//---------------------------------------------- +// DIP switch/jumper handlers +//---------------------------------------------- -const tiny_rom_entry *a2bus_pic_device::device_rom_region() const +INPUT_CHANGED_MEMBER(a2bus_pic_device::sw1_strobe) { - return ROM_NAME( pic ); + m_printer_conn->write_strobe(BIT(m_input_sw1->read(), 3) ^ (m_strobe_timer->enabled() ? 0U : 1U)); } -//************************************************************************** -// LIVE DEVICE -//************************************************************************** -a2bus_pic_device::a2bus_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - a2bus_pic_device(mconfig, A2BUS_PIC, tag, owner, clock) +INPUT_CHANGED_MEMBER(a2bus_pic_device::sw1_ack) { + if (m_ack_in != BIT(m_input_sw1->read(), 4)) + set_ack_latch(); } -a2bus_pic_device::a2bus_pic_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, type, tag, owner, clock), - device_a2bus_card_interface(mconfig, *this), - m_dsw1(*this, "DSW1"), - m_ctx(*this, PIC_CENTRONICS_TAG), - m_ctx_data_in(*this, "ctx_data_in"), - m_ctx_data_out(*this, "ctx_data_out"), m_rom(nullptr), - m_started(false), m_ack(0), m_irqenable(false), m_autostrobe(false), m_timer(nullptr) + +INPUT_CHANGED_MEMBER(a2bus_pic_device::sw1_firmware) { + m_firmware_base = BIT(m_input_sw1->read(), 5) << 8; } -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- -void a2bus_pic_device::device_start() +INPUT_CHANGED_MEMBER(a2bus_pic_device::sw1_irq) { - m_rom = device().machine().root_device().memregion(this->subtag(PIC_ROM_REGION).c_str())->base(); + if (m_ack_latch && m_irq_enable) + { + if (BIT(m_input_sw1->read(), 6)) + lower_slot_irq(); + else + raise_slot_irq(); + } +} - m_timer = timer_alloc(0, nullptr); - m_timer->adjust(attotime::never); - save_item(NAME(m_ack)); - save_item(NAME(m_irqenable)); - save_item(NAME(m_autostrobe)); +INPUT_CHANGED_MEMBER(a2bus_pic_device::x_data_out) +{ + if (m_data_latch && !BIT(m_input_x->read(), 1)) + { + m_data_latch = 0x00U; + m_printer_out->write(0x00U); + } } -void a2bus_pic_device::device_reset() + +INPUT_CHANGED_MEMBER(a2bus_pic_device::x_char_width) { - m_started = true; - m_ack = 0; - m_irqenable = false; - m_autostrobe = false; - lower_slot_irq(); - m_timer->adjust(attotime::never); - - // set initial state of the strobe line depending on the dipswitch - clear_strobe(); + if (BIT(m_data_latch, 7)) + m_printer_out->write(m_data_latch & (BIT(m_input_x->read(), 2) ? 0xffU : 0x7fU)); } -void a2bus_pic_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr) -{ - clear_strobe(); - m_timer->adjust(attotime::never); -} -/*------------------------------------------------- - read_cnxx - called for reads from this card's cnxx space --------------------------------------------------*/ +//---------------------------------------------- +// device_a2bus_card_interface implementation +//---------------------------------------------- -uint8_t a2bus_pic_device::read_cnxx(uint8_t offset) +u8 a2bus_pic_device::read_c0nx(u8 offset) { - m_autostrobe = true; + LOG("Read C0n%01X\n", offset); - if (m_dsw1->read() & 0x20) + switch (offset & 0x07U) { - return m_rom[(offset&0xff) | 0x100]; + case 3U: + return 0x97U | (m_perror_in << 5) | (m_select_in << 6) | (m_fault_in << 3); + + case 4U: + return (m_ack_latch << 7) | (m_ack_in ^ BIT(m_input_sw1->read(), 4)); + + case 5U: + logerror("500ns negative strobe not implemented\n"); + break; + + case 6U: + enable_irq(); + break; + + case 7U: + reset_mode(); + break; } - return m_rom[(offset&0xff)]; + return 0x00U; } -/*------------------------------------------------- - read_c0nx - called for reads from this card's c0nx space --------------------------------------------------*/ - -uint8_t a2bus_pic_device::read_c0nx(uint8_t offset) +void a2bus_pic_device::write_c0nx(u8 offset, u8 data) { - uint8_t rv = 0; + LOG("Write C0n%01X=%02X\n", offset, data); - switch (offset) + switch (offset & 0x07U) { - case 3: - return m_ctx_data_in->read(); - - case 4: - rv = m_ack; + case 0U: + { + ioport_value const x(m_input_x->read()); - // clear flip-flop - if (m_dsw1->read() & 0x10) // negative polarity + // latch output data - remember MSB can be forced low by jumper + if (BIT(x, 1)) { - m_ack |= 0x80; + LOG("Latch data %02X\n", data); + m_data_latch = data; + m_printer_out->write(data & (BIT(x, 2) ? 0xffU : 0x7fU)); } else { - m_ack &= ~0x80; + LOG("Output disabled, not latching data\n"); } - return rv; + // start strobe if autostrobe is enabled + if (!m_autostrobe_disable) + start_strobe(); + } + break; - case 6: // does reading this really work? - m_irqenable = true; - break; + case 2U: + start_strobe(); + break; - case 7: - m_irqenable = false; - m_autostrobe = false; - lower_slot_irq(); - break; + case 5U: + logerror("500ns negative strobe not implemented\n"); + break; - } + case 6U: + enable_irq(); + break; - return 0; + case 7U: + reset_mode(); + break; + } } -/*------------------------------------------------- - write_c0nx - called for writes to this card's c0nx space --------------------------------------------------*/ -void a2bus_pic_device::write_c0nx(uint8_t offset, uint8_t data) +u8 a2bus_pic_device::read_cnxx(u8 offset) { - switch (offset) + if (BIT(m_input_x->read(), 0)) { - case 0: // set data out and send a strobe - m_ctx_data_out->write(data); + if (!BIT(offset, 6) || (BIT(offset, 7) && !m_ack_latch)) + offset |= 0x40U; + else + offset &= 0xbfU; + } - if (m_autostrobe) - { - start_strobe(); - } - break; + if (!machine().side_effects_disabled()) + { + if (m_autostrobe_disable) + LOG("Enabling autostrobe\n"); + m_autostrobe_disable = 0U; + } - case 2: // send a strobe - start_strobe(); - break; + return m_prom[m_firmware_base | offset]; +} - case 6: // enable interrupt on ACK - m_irqenable = true; - break; - case 7: // disable and acknowledge IRQ, reset ACK flip-flop, disable autostrobe - m_irqenable = false; - m_autostrobe = false; - lower_slot_irq(); - break; - } +void a2bus_pic_device::write_cnxx(u8 offset, u8 data) +{ + LOG("Write Cn%02X=%02X (bus conflict)\n", offset, data); + + if (m_autostrobe_disable) + LOG("Enabling autostrobe\n"); + m_autostrobe_disable = 0U; +} + + + +//---------------------------------------------- +// device_t implementation +//---------------------------------------------- + +tiny_rom_entry const *a2bus_pic_device::device_rom_region() const +{ + return ROM_NAME(pic); +} + + +void a2bus_pic_device::device_add_mconfig(machine_config &config) +{ + CENTRONICS(config, m_printer_conn, centronics_devices, "printer"); + m_printer_conn->ack_handler().set(FUNC(a2bus_pic_device::ack_w)); + m_printer_conn->perror_handler().set(FUNC(a2bus_pic_device::perror_w)); + m_printer_conn->select_handler().set(FUNC(a2bus_pic_device::select_w)); + m_printer_conn->fault_handler().set(FUNC(a2bus_pic_device::fault_w)); + + OUTPUT_LATCH(config, m_printer_out); + m_printer_conn->set_output_latch(*m_printer_out); +} + + +ioport_constructor a2bus_pic_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(pic); +} + + +void a2bus_pic_device::device_start() +{ + m_strobe_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(a2bus_pic_device::release_strobe), this)); + + m_firmware_base = 0x0100U; + m_data_latch = 0xffU; + + save_item(NAME(m_data_latch)); + save_item(NAME(m_autostrobe_disable)); + save_item(NAME(m_ack_latch)); + save_item(NAME(m_irq_enable)); + save_item(NAME(m_ack_in)); + save_item(NAME(m_perror_in)); + save_item(NAME(m_select_in)); + save_item(NAME(m_fault_in)); } -WRITE_LINE_MEMBER( a2bus_pic_device::ack_w ) + +void a2bus_pic_device::device_reset() { - if (m_started) + ioport_value const sw1(m_input_sw1->read()); + ioport_value const x(m_input_x->read()); + + m_firmware_base = BIT(sw1, 5) << 8; + m_autostrobe_disable = 1U; + + if (!BIT(x, 1)) { - uint8_t dsw1 = m_dsw1->read(); + m_data_latch = 0x00U; + m_printer_out->write(0x00U); + } - if (dsw1 & 0x10) // negative polarity - { - m_ack = (state == ASSERT_LINE) ? 0x00 : 0x80; - } - else + m_printer_conn->write_strobe(BIT(sw1, 3) ^ (m_strobe_timer->enabled() ? 0U : 1U)); + + reset_mode(); +} + + + +//---------------------------------------------- +// printer status inputs +//---------------------------------------------- + +WRITE_LINE_MEMBER(a2bus_pic_device::ack_w) +{ + if (bool(state) != bool(m_ack_in)) + { + m_ack_in = state ? 1U : 0U; + LOG("/ACK=%u\n", m_ack_in); + if (started() && (m_ack_in != BIT(m_input_sw1->read(), 4))) { - m_ack = (state == ASSERT_LINE) ? 0x80 : 0x00; + LOG("Active /ACK edge\n"); + set_ack_latch(); } + } +} + + +WRITE_LINE_MEMBER(a2bus_pic_device::perror_w) +{ + if (bool(state) != bool(m_perror_in)) + { + m_perror_in = state ? 1U : 0U; + LOG("PAPER EMPTY=%u\n", m_perror_in); + } +} - m_ack |= 0x40; // set ACK flip-flop - if ((dsw1 & 0x40) && (m_irqenable)) +WRITE_LINE_MEMBER(a2bus_pic_device::select_w) +{ + if (bool(state) != bool(m_select_in)) + { + m_select_in = state ? 1U : 0U; + LOG("SELECT=%u\n", m_select_in); + } +} + + +WRITE_LINE_MEMBER(a2bus_pic_device::fault_w) +{ + if (bool(state) != bool(m_fault_in)) + { + m_fault_in = state ? 1U : 0U; + LOG("/FAULT=%u\n", m_fault_in); + } +} + + + +//---------------------------------------------- +// timer handlers +//---------------------------------------------- + +TIMER_CALLBACK_MEMBER(a2bus_pic_device::release_strobe) +{ + int const state(BIT(~m_input_sw1->read(), 3)); + LOG("Output /STROBE=%d\n", state); + m_printer_conn->write_strobe(state); +} + + + +//---------------------------------------------- +// helpers +//---------------------------------------------- + +void a2bus_pic_device::reset_mode() +{ + if (!m_autostrobe_disable) + LOG("Disabling autostrobe\n"); + else + LOG("Autostrobe already disabled\n"); + m_autostrobe_disable = 1U; + disable_irq(); + set_ack_latch(); +} + + +void a2bus_pic_device::start_strobe() +{ + ioport_value const sw1(m_input_sw1->read()); + unsigned const cycles(15U - ((sw1 & 0x07U) << 1)); + int const state(BIT(sw1, 3)); + if (!m_strobe_timer->enabled()) + { + LOG("Output /STROBE=%d for %u cycles\n", state, cycles); + clear_ack_latch(); + m_printer_conn->write_strobe(state); + } + else + { + LOG("Adjust /STROBE=%d remaining to %u cycles\n", state, cycles); + } + m_strobe_timer->adjust(attotime::from_ticks(cycles, clock())); +} + + +void a2bus_pic_device::set_ack_latch() +{ + if (m_strobe_timer->enabled()) + { + LOG("Active strobe prevents acknowledge latch from being set\n"); + } + else if (!m_ack_latch) + { + LOG("Setting acknowledge latch\n"); + m_ack_latch = 1U; + if (m_irq_enable && !BIT(m_input_sw1->read(), 6)) { + LOG("Asserting slot IRQ\n"); raise_slot_irq(); } } + else + { + LOG("Acknowledge latch already set\n"); + } } -void a2bus_pic_device::start_strobe() -{ - int usec = ((m_dsw1->read() & 7) * 2) + 1; // strobe length in microseconds - if (m_dsw1->read() & 0x8) // negative polarity +void a2bus_pic_device::clear_ack_latch() +{ + if (m_ack_latch) { - m_ctx->write_strobe(CLEAR_LINE); + LOG("Clearing acknowledge latch\n"); + m_ack_latch = 0U; + if (m_irq_enable && !BIT(m_input_sw1->read(), 6)) + { + LOG("Releasing slot IRQ\n"); + lower_slot_irq(); + } } else { - m_ctx->write_strobe(ASSERT_LINE); + LOG("Acknowledge latch already clear\n"); } +} + - m_timer->adjust(attotime::from_usec(usec), 0, attotime::never); +void a2bus_pic_device::enable_irq() +{ + if (!m_irq_enable) + { + LOG("Enabling IRQ\n"); + m_irq_enable = 1U; + if (m_ack_latch && !BIT(m_input_sw1->read(), 6)) + { + LOG("Asserting slot IRQ\n"); + raise_slot_irq(); + } + } + else + { + LOG("IRQ already enabled\n"); + } } -void a2bus_pic_device::clear_strobe() + +void a2bus_pic_device::disable_irq() { - if (m_dsw1->read() & 0x8) // negative polarity + if (m_irq_enable) { - m_ctx->write_strobe(ASSERT_LINE); + LOG("Disabling IRQ\n"); + m_irq_enable = 0U; + if (m_ack_latch && !BIT(m_input_sw1->read(), 6)) + { + LOG("Releasing slot IRQ\n"); + lower_slot_irq(); + } } else { - m_ctx->write_strobe(CLEAR_LINE); + LOG("IRQ already disabled\n"); } } diff --git a/src/devices/bus/a2bus/a2pic.h b/src/devices/bus/a2bus/a2pic.h index 755700ef0b0..283dd537e7c 100644 --- a/src/devices/bus/a2bus/a2pic.h +++ b/src/devices/bus/a2bus/a2pic.h @@ -1,13 +1,40 @@ // license:BSD-3-Clause -// copyright-holders:R. Belmont +// copyright-holders:Vas Crabb /********************************************************************* - a2pic.h - - Apple II Parallel Interface Card + Apple II Parallel Interface Card (670-0021) + + DB25 connector, with Centronics assignments: + + Data In, Bit 0 1 + Signal Ground 2 19 GND + Data In, Bit 2 3 + Signal Ground 4 + Data Out, Bit 0 5 2 D0 + Data Out, Bit 1 6 3 D1 + (blocked)* 7 + Data Out, Bit 2 8 4 D2 + -- 9 + -- 10 + Data Out, Bit 5 11 7 D5 + Data Out, Bit 6 12 8 D6 + Data Out, Bit 7 13 9 D7 + Data In, Bit 4 14 + Strobe Out 15 1 /STROBE + Acknowledge In 16 10 /ACK + Data In, Bit 1 17 + Data In, Bit 7 18 18 +5V PULLUP + Data In, Bit 5 19 12 POUT + Signal Ground 20 + Data In, Bit 6 21 13 SEL + Data Out, Bit 3 22 5 D3 + Data Out, Bit 4 23 6 D4 + Signal Ground 24 16 0V + Data In, Bit 3 25 32 /FAULT + + *wired to 500ns strobe but connector hole is blocked *********************************************************************/ - #ifndef MAME_BUS_A2BUS_A2PIC_H #define MAME_BUS_A2BUS_A2PIC_H @@ -16,53 +43,70 @@ #include "a2bus.h" #include "bus/centronics/ctronics.h" -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -class a2bus_pic_device: - public device_t, - public device_a2bus_card_interface +class a2bus_pic_device : public device_t, public device_a2bus_card_interface { public: - // construction/destruction - a2bus_pic_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + a2bus_pic_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + // DIP switch/jumper handlers + DECLARE_INPUT_CHANGED_MEMBER(sw1_strobe); + DECLARE_INPUT_CHANGED_MEMBER(sw1_ack); + DECLARE_INPUT_CHANGED_MEMBER(sw1_firmware); + DECLARE_INPUT_CHANGED_MEMBER(sw1_irq); + DECLARE_INPUT_CHANGED_MEMBER(x_data_out); + DECLARE_INPUT_CHANGED_MEMBER(x_char_width); + + // device_a2bus_card_interface implementation + virtual u8 read_c0nx(u8 offset) override; + virtual void write_c0nx(u8 offset, u8 data) override; + virtual u8 read_cnxx(u8 offset) override; + virtual void write_cnxx(u8 offset, u8 data) override; protected: - a2bus_pic_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - virtual void device_start() override; - virtual void device_reset() override; - virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + // device_t implementation + virtual tiny_rom_entry const *device_rom_region() const override; virtual void device_add_mconfig(machine_config &config) override; - virtual const tiny_rom_entry *device_rom_region() const override; virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + virtual void device_reset() override; - virtual uint8_t read_c0nx(uint8_t offset) override; - virtual void write_c0nx(uint8_t offset, uint8_t data) override; - virtual uint8_t read_cnxx(uint8_t offset) override; - - void start_strobe(); - void clear_strobe(); - - required_ioport m_dsw1; +private: + // printer status inputs + DECLARE_WRITE_LINE_MEMBER(ack_w); + DECLARE_WRITE_LINE_MEMBER(perror_w); + DECLARE_WRITE_LINE_MEMBER(select_w); + DECLARE_WRITE_LINE_MEMBER(fault_w); - required_device m_ctx; - required_device m_ctx_data_in; - required_device m_ctx_data_out; + // timer handlers + TIMER_CALLBACK_MEMBER(release_strobe); -private: - DECLARE_WRITE_LINE_MEMBER( ack_w ); - - uint8_t *m_rom; - bool m_started; - uint8_t m_ack; - bool m_irqenable; - bool m_autostrobe; - emu_timer *m_timer; + // helpers + void reset_mode(); + void start_strobe(); + void set_ack_latch(); + void clear_ack_latch(); + void enable_irq(); + void disable_irq(); + + required_device m_printer_conn; + required_device m_printer_out; + required_ioport m_input_sw1; + required_ioport m_input_x; + required_region_ptr m_prom; + emu_timer * m_strobe_timer; + + u16 m_firmware_base; // controlled by SW6 + u8 m_data_latch; // 9B + u8 m_autostrobe_disable; // 2A pin 8 + u8 m_ack_latch; // 2A pin 6 + u8 m_irq_enable; // 2B pin 9 + u8 m_ack_in; + u8 m_perror_in; // DI5 + u8 m_select_in; // DI6 + u8 m_fault_in; // DI3 }; -// device type definition + DECLARE_DEVICE_TYPE(A2BUS_PIC, a2bus_pic_device) -#endif // MAME_BUS_A2BUS_A2PIC_H +#endif // MAME_BUS_A2BUS_A2PIC_H diff --git a/src/devices/bus/a2bus/grapplerplus.cpp b/src/devices/bus/a2bus/grapplerplus.cpp index 99e0f69f78f..480cfa1c8f9 100644 --- a/src/devices/bus/a2bus/grapplerplus.cpp +++ b/src/devices/bus/a2bus/grapplerplus.cpp @@ -76,7 +76,7 @@ a2bus_grapplerplus_device::a2bus_grapplerplus_device(machine_config const &mconf INPUT_CHANGED_MEMBER(a2bus_grapplerplus_device::sw_msb) { if (BIT(m_data_latch, 7)) - m_printer_out->write(m_data_latch & ((BIT(m_s1->read(), 3) ? 0xffU : 0x7fU))); + m_printer_out->write(m_data_latch & (BIT(m_s1->read(), 3) ? 0xffU : 0x7fU)); } @@ -106,7 +106,7 @@ void a2bus_grapplerplus_device::write_c0nx(u8 offset, u8 data) // latch output data - remember MSB can be forced low by DIP switch LOG("Latch data %02X\n", data); m_data_latch = data; - m_printer_out->write(data & ((BIT(m_s1->read(), 3) ? 0xffU : 0x7fU))); + m_printer_out->write(data & (BIT(m_s1->read(), 3) ? 0xffU : 0x7fU)); // clearing the ACK latch will acknowledge an interrupt if (m_ack_in) -- cgit v1.2.3