From 958189731b8e4b0e19c042331901460ef452f601 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Wed, 7 Apr 2021 04:33:43 +1000 Subject: bus/a2bus: Added Orange Micro Grappler printer interface card. --- scripts/src/bus.lua | 4 +- src/devices/bus/a2bus/grappler.cpp | 1057 ++++++++++++++++++++++++++++++++ src/devices/bus/a2bus/grappler.h | 284 +++++++++ src/devices/bus/a2bus/grapplerplus.cpp | 837 ------------------------- src/devices/bus/a2bus/grapplerplus.h | 225 ------- src/mame/drivers/apple2.cpp | 3 +- src/mame/drivers/apple2e.cpp | 3 +- src/mame/drivers/apple2gs.cpp | 3 +- 8 files changed, 1349 insertions(+), 1067 deletions(-) create mode 100644 src/devices/bus/a2bus/grappler.cpp create mode 100644 src/devices/bus/a2bus/grappler.h delete mode 100644 src/devices/bus/a2bus/grapplerplus.cpp delete mode 100644 src/devices/bus/a2bus/grapplerplus.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 74f601e7499..415826bbfb6 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2417,8 +2417,8 @@ if (BUSES["A2BUS"]~=null) then MAME_DIR .. "src/devices/bus/a2bus/corvfdc02.h", MAME_DIR .. "src/devices/bus/a2bus/ezcgi.cpp", MAME_DIR .. "src/devices/bus/a2bus/ezcgi.h", - MAME_DIR .. "src/devices/bus/a2bus/grapplerplus.cpp", - MAME_DIR .. "src/devices/bus/a2bus/grapplerplus.h", + MAME_DIR .. "src/devices/bus/a2bus/grappler.cpp", + MAME_DIR .. "src/devices/bus/a2bus/grappler.h", MAME_DIR .. "src/devices/bus/a2bus/laser128.cpp", MAME_DIR .. "src/devices/bus/a2bus/laser128.h", MAME_DIR .. "src/devices/bus/a2bus/mouse.cpp", diff --git a/src/devices/bus/a2bus/grappler.cpp b/src/devices/bus/a2bus/grappler.cpp new file mode 100644 index 00000000000..3b14db16c48 --- /dev/null +++ b/src/devices/bus/a2bus/grappler.cpp @@ -0,0 +1,1057 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +#include "emu.h" +#include "grappler.h" + +//#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + +namespace { + +ROM_START(grappler) + ROM_REGION(0x0800, "rom", 0) + ROM_LOAD( "eps-1_c1981.u6", 0x0000, 0x0800, CRC(862773cb) SHA1(791ebae64a7fad8f42bdfaec36b9e2d34f12ded8) ) +ROM_END + + +ROM_START(grapplerplus) + // TODO: add other revisions - 3.3 is known to exist + + ROM_DEFAULT_BIOS("v32") + ROM_SYSTEM_BIOS(0, "v30", "ROM 3.0") + ROM_SYSTEM_BIOS(1, "v32", "ROM 3.2") + + ROM_REGION(0x1000, "rom", 0) + ROMX_LOAD( "3.0.u9", 0x0000, 0x1000, CRC(17cf5e02) SHA1(9b01a9b1cf7752987e03f9b0285eb9329d63b777), ROM_BIOS(0) ) + ROMX_LOAD( "3.2.u9", 0x0000, 0x1000, CRC(6f88b70c) SHA1(433ae61a0553ee9c1628ea5b6376dac848c04cad), ROM_BIOS(1) ) +ROM_END + + +ROM_START(bufgrapplerplus) + // TODO: confirm contents + // despite having the same version string, this differs from the Grapper+ 3.2.u9 ROM + + // 9433B-0141 + // 90ROM00002 + // GI8603CEY + // TAIWAN + ROM_REGION(0x1000, "rom", 0) + ROM_LOAD( "90rom00002.u18", 0x0000, 0x1000, CRC(cd07c7ef) SHA1(6c2f1375b5df6bb65dfca1444c064661242fef1a) ) + + // S 8450 + // SCN8048A + // C6N40 B + // 95ROM08048 + ROM_REGION(0x0400, "mcu", 0) + ROM_LOAD( "95rom08048.u10", 0x0000, 0x0400, CRC(55990f67) SHA1(f0907cf02d8c5dbf1bfacb0d626f2231142f0ff7) ) +ROM_END + + +INPUT_PORTS_START(grapplerplus) + PORT_START("S1") + PORT_DIPNAME(0x07, 0x00, "Printer Type") PORT_DIPLOCATION("S1:4,3,2") + PORT_DIPSETTING( 0x00, "Epson Series") + PORT_DIPSETTING( 0x01, "NEC 8023/C. Itoh 8510/DMP 85") + PORT_DIPSETTING( 0x02, "Star Gemini") + PORT_DIPSETTING( 0x03, "Anadex Printers") + PORT_DIPSETTING( 0x04, "Okidata 82A, 83A, 92, 93, 84") + PORT_DIPSETTING( 0x06, "Okidata 84 w/o Step II Graphics") + PORT_DIPSETTING( 0x05, "Apple Dot Matrix") + PORT_DIPSETTING( 0x07, "invalid") + PORT_DIPNAME(0x08, 0x08, "Most Significant Bit") PORT_DIPLOCATION("S1:1") PORT_CHANGED_MEMBER(DEVICE_SELF, a2bus_grapplerplus_device_base, sw_msb, 0) + PORT_DIPSETTING( 0x08, "Software Control") + PORT_DIPSETTING( 0x00, "Not Transmitted") +INPUT_PORTS_END + + +INPUT_PORTS_START(bufgrapplerplus) + PORT_INCLUDE(grapplerplus) + + PORT_START("CNF") + PORT_CONFNAME(0xff, 0x00, "RAM Size") + PORT_CONFSETTING( 0xfc, "16K (2 chips)") + PORT_CONFSETTING( 0xf0, "32K (4 chips)") + PORT_CONFSETTING( 0x00, "64K (8 chips)") +INPUT_PORTS_END + +} // anonymous namespace + + + +DEFINE_DEVICE_TYPE(A2BUS_GRAPPLER, a2bus_grappler_device, "a2grappler", "Orange Micro Grappler Printer Interface") +DEFINE_DEVICE_TYPE(A2BUS_GRAPPLERPLUS, a2bus_grapplerplus_device, "a2grapplerplus", "Orange Micro Grappler+ Printer Interface") +DEFINE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUS, a2bus_buf_grapplerplus_device, "a2bufgrapplerplus", "Orange Micro Buffered Grappler+ Printer Interface") +DEFINE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUSA, a2bus_buf_grapplerplus_reva_device, "a2bufgrapplerplusa", "Orange Micro Buffered Grappler+ (rev A) Printer Interface") + + + +//============================================================== +// Grappler base +//============================================================== + +a2bus_grappler_device_base::a2bus_grappler_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, type, tag, owner, clock), + device_a2bus_card_interface(mconfig, *this), + m_printer_conn(*this, "prn"), + m_printer_out(*this, "prn_out"), + m_rom(*this, "rom"), + m_rom_bank(0x0000U), + m_busy_in(1U), + m_pe_in(1U), + m_slct_in(1U) +{ +} + + + +//-------------------------------------------------- +// device_a2bus_card_interface implementation +//-------------------------------------------------- + +u8 a2bus_grappler_device_base::read_c800(u16 offset) +{ + return m_rom[(offset & 0x07ffU) | m_rom_bank]; +} + + + +//-------------------------------------------------- +// device_t implementation +//-------------------------------------------------- + +void a2bus_grappler_device_base::device_add_mconfig(machine_config &config) +{ + CENTRONICS(config, m_printer_conn, centronics_devices, "printer"); + m_printer_conn->busy_handler().set(FUNC(a2bus_grappler_device_base::busy_w)); + m_printer_conn->perror_handler().set(FUNC(a2bus_grappler_device_base::pe_w)); + m_printer_conn->select_handler().set(FUNC(a2bus_grappler_device_base::slct_w)); + + OUTPUT_LATCH(config, m_printer_out); + m_printer_conn->set_output_latch(*m_printer_out); +} + + +void a2bus_grappler_device_base::device_start() +{ + save_item(NAME(m_rom_bank)); + save_item(NAME(m_busy_in)); + save_item(NAME(m_pe_in)); + save_item(NAME(m_slct_in)); +} + + + +//-------------------------------------------------- +// printer status inputs +//-------------------------------------------------- + +void a2bus_grappler_device_base::set_rom_bank(u16 rom_bank) +{ + if (m_rom_bank != rom_bank) + LOG("Select ROM bank %04X\n", rom_bank); + m_rom_bank = rom_bank; +} + + + +//-------------------------------------------------- +// printer status inputs +//-------------------------------------------------- + +WRITE_LINE_MEMBER(a2bus_grappler_device_base::busy_w) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device_base::set_busy_in), this), state ? 1 : 0); +} + + +WRITE_LINE_MEMBER(a2bus_grappler_device_base::pe_w) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device_base::set_pe_in), this), state ? 1 : 0); +} + + +WRITE_LINE_MEMBER(a2bus_grappler_device_base::slct_w) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device_base::set_slct_in), this), state ? 1 : 0); +} + + + +//-------------------------------------------------- +// synchronised printer status inputs +//-------------------------------------------------- + +void a2bus_grappler_device_base::set_busy_in(void *ptr, s32 param) +{ + if (u32(param) != m_busy_in) + { + LOG("BUSY=%d\n", param); + m_busy_in = u8(u32(param)); + } +} + + +void a2bus_grappler_device_base::set_pe_in(void *ptr, s32 param) +{ + if (u32(param) != m_pe_in) + { + LOG("PAPER EMPTY=%d\n", param); + m_pe_in = u8(u32(param)); + } +} + + +void a2bus_grappler_device_base::set_slct_in(void *ptr, s32 param) +{ + if (u32(param) != m_slct_in) + { + LOG("SELECT=%d\n", param); + m_slct_in = u8(u32(param)); + } +} + + + +//============================================================== +// Grappler implementation +//============================================================== + +a2bus_grappler_device::a2bus_grappler_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + a2bus_grappler_device_base(mconfig, A2BUS_GRAPPLER, tag, owner, clock), + m_strobe(1U), + m_ack_latch(1U), + m_ack_in(1U) +{ +} + + + +//-------------------------------------------------- +// device_a2bus_card_interface implementation +//-------------------------------------------------- + +u8 a2bus_grappler_device::read_c0nx(u8 offset) +{ + LOG("Read C0n%01X\n", offset); + + if (BIT(offset, 1)) // A1 - assert strobe + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 0); + else if (BIT(offset, 2)) // A2 - release strobe + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 1); + + if (BIT(offset, 0)) // A0 - printer status + { + return + 0xf0U | // TODO: actually open bus + (busy_in() << 3) | + (pe_in() << 2) | + (slct_in() << 1) | + m_ack_latch; + } + else + { + return 0xffU; // TODO: actually open bus + } +} + + +void a2bus_grappler_device::write_c0nx(u8 offset, u8 data) +{ + LOG("Write C0n%01X=%02X\n", offset, data); + + if (BIT(offset, 0)) // A0 - write data + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_data), this), int(unsigned(data))); + + if (BIT(offset, 1)) // A1 - assert strobe + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 0); + else if (BIT(offset, 2)) // A2 - release strobe + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 1); +} + + +u8 a2bus_grappler_device::read_cnxx(u8 offset) +{ + return m_rom[offset | (slotno() << 8)]; +} + + +void a2bus_grappler_device::write_cnxx(u8 offset, u8 data) +{ + LOG("Write Cn%02X=%02X (bus conflict)\n", offset, data); +} + + + +//-------------------------------------------------- +// device_t implementation +//-------------------------------------------------- + +tiny_rom_entry const *a2bus_grappler_device::device_rom_region() const +{ + return ROM_NAME(grappler); +} + + +void a2bus_grappler_device::device_add_mconfig(machine_config &config) +{ + a2bus_grappler_device_base::device_add_mconfig(config); + + m_printer_conn->ack_handler().set(FUNC(a2bus_grappler_device::ack_w)); +} + + +void a2bus_grappler_device::device_start() +{ + a2bus_grappler_device_base::device_start(); + + save_item(NAME(m_strobe)); + save_item(NAME(m_ack_latch)); + save_item(NAME(m_ack_in)); +} + + +void a2bus_grappler_device::device_reset() +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_strobe), this), 1); +} + + + +//-------------------------------------------------- +// printer status inputs +//-------------------------------------------------- + +WRITE_LINE_MEMBER(a2bus_grappler_device::ack_w) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grappler_device::set_ack_in), this), state ? 1 : 0); +} + + + +//-------------------------------------------------- +// synchronised signals +//-------------------------------------------------- + +void a2bus_grappler_device::set_data(void *ptr, s32 param) +{ + LOG("Output data %02X\n", u8(u32(param))); + m_printer_out->write(u8(u32(param))); +} + + +void a2bus_grappler_device::set_strobe(void *ptr, s32 param) +{ + LOG("Output /STROBE=%d\n", param); + m_printer_conn->write_strobe(param); + if (m_strobe && !param) + { + if (m_ack_in) + { + if (!m_ack_latch) + LOG("Clearing acknowledge latch\n"); + else + LOG("Previous data not acknowledged\n"); + m_ack_latch = 1U; + } + else + { + LOG("/ACK asserted, not clearing acknowledge latch\n"); + } + } + m_strobe = u8(u32(param)); +} + + +void a2bus_grappler_device::set_ack_in(void *ptr, s32 param) +{ + if (u32(param) != m_ack_in) + { + LOG("/ACK=%d\n", param); + m_ack_in = u8(u32(param)); + if (!param) + { + if (m_ack_latch) + LOG("Set acknowledge latch\n"); + else + LOG("No data written since previous acknowledge\n"); + m_ack_latch = 0U; + } + else if (!m_strobe) + { + LOG("Clearing acknowledge latch\n"); + m_ack_latch = 1U; + } + } +} + + + +//============================================================== +// Grappler+ base +//============================================================== + +a2bus_grapplerplus_device_base::a2bus_grapplerplus_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : + a2bus_grappler_device_base(mconfig, type, tag, owner, clock), + m_s1(*this, "S1"), + m_ack_latch(1U), + m_ack_in(1U) +{ +} + + + +//-------------------------------------------------- +// device_t implementation +//-------------------------------------------------- + +ioport_constructor a2bus_grapplerplus_device_base::device_input_ports() const +{ + return INPUT_PORTS_NAME(grapplerplus); +} + + +void a2bus_grapplerplus_device_base::device_start() +{ + a2bus_grappler_device_base::device_start(); + + save_item(NAME(m_ack_latch)); + save_item(NAME(m_ack_in)); +} + + +void a2bus_grapplerplus_device_base::device_reset() +{ + m_ack_latch = 1U; +} + + + +//-------------------------------------------------- +// device_a2bus_card_interface implementation +//-------------------------------------------------- + +void a2bus_grapplerplus_device_base::write_c0nx(u8 offset, u8 data) +{ + LOG("Write C0n%01X=%02X\n", offset, data); + + if (!(offset & 0x03U)) // !A0 && !A1 - write data + { + // latch output data + LOG("Latch data %02X\n", data); + data_latched(data); + + // clearing the ACK latch will acknowledge an interrupt + if (m_ack_in) + { + if (m_ack_latch) + LOG("Clearing acknowledge latch\n"); + else + LOG("Previous data not acknowledged\n"); + m_ack_latch = 0U; + ack_latch_cleared(); + } + else + { + LOG("/ACK asserted, not clearing acknowledge latch\n"); + } + } + + if (BIT(offset, 0)) // A0 - select high ROM bank + set_rom_bank(0x0800U); +} + + +u8 a2bus_grapplerplus_device_base::read_cnxx(u8 offset) +{ + if (!machine().side_effects_disabled()) + set_rom_bank(0x0000U); + return m_rom[(!m_ack_latch && BIT(offset, 7)) ? (offset & 0xbfU) : offset]; +} + + +void a2bus_grapplerplus_device_base::write_cnxx(u8 offset, u8 data) +{ + LOG("Write Cn%02X=%02X (bus conflict)\n", offset, data); + + set_rom_bank(0x0000U); +} + + + +//-------------------------------------------------- +// ACK latch set input +//-------------------------------------------------- + +WRITE_LINE_MEMBER(a2bus_grapplerplus_device_base::ack_w) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grapplerplus_device_base::set_ack_in), this), state ? 1 : 0); +} + + + +//-------------------------------------------------- +// synchronised printer status inputs +//-------------------------------------------------- + +void a2bus_grapplerplus_device_base::set_ack_in(void *ptr, s32 param) +{ + if (u32(param) != m_ack_in) + { + LOG("/ACK=%d\n", param); + m_ack_in = u8(u32(param)); + if (!param) + { + if (!m_ack_latch) + LOG("Set acknowledge latch\n"); + else + LOG("No data written since previous acknowledge\n"); + m_ack_latch = 1U; + ack_latch_set(); + } + } +} + + + +//============================================================== +// Grappler+ implementation +//============================================================== + +a2bus_grapplerplus_device::a2bus_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + a2bus_grapplerplus_device_base(mconfig, A2BUS_GRAPPLERPLUS, tag, owner, clock), + m_strobe_timer(nullptr), + m_data_latch(0xffU), + m_irq_disable(1U), + m_irq(0x00U), + m_next_strobe(1U) +{ +} + + + +//-------------------------------------------------- +// DIP switch handlers +//-------------------------------------------------- + +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)); +} + + + +//-------------------------------------------------- +// device_a2bus_card_interface implementation +//-------------------------------------------------- + +u8 a2bus_grapplerplus_device::read_c0nx(u8 offset) +{ + return + m_irq | + ((m_s1->read() & 0x07U) << 4) | + (busy_in() << 3) | + (pe_in() << 2) | + (slct_in() << 1) | + ack_latch(); +} + + +void a2bus_grapplerplus_device::write_c0nx(u8 offset, u8 data) +{ + a2bus_grapplerplus_device_base::write_c0nx(offset, data); + + if (BIT(offset, 1)) // A1 - disable interrupt + { + if (!m_irq_disable) + LOG("Disable interrupt request\n"); + else + LOG("Interrupt request already disabled\n"); + m_irq_disable = 1U; + if (m_irq) + { + assert(ack_latch()); + LOG("Releasing slot IRQ\n"); + m_irq = 0x00U; + lower_slot_irq(); + } + } + else if (BIT(offset, 2)) // A2 - enable interrupt + { + if (m_irq_disable) + LOG("Enable interrupt request\n"); + else + LOG("Interrupt request already enabled\n"); + m_irq_disable = 0U; + if (ack_latch() && !m_irq) + { + LOG("Asserting slot IRQ\n"); + m_irq = 0x80U; + raise_slot_irq(); + } + } +} + + + +//-------------------------------------------------- +// device_t implementation +//-------------------------------------------------- + +tiny_rom_entry const *a2bus_grapplerplus_device::device_rom_region() const +{ + return ROM_NAME(grapplerplus); +} + + +void a2bus_grapplerplus_device::device_add_mconfig(machine_config &config) +{ + a2bus_grapplerplus_device_base::device_add_mconfig(config); + + m_printer_conn->ack_handler().set(FUNC(a2bus_grapplerplus_device::ack_w)); +} + + +void a2bus_grapplerplus_device::device_start() +{ + a2bus_grapplerplus_device_base::device_start(); + + m_strobe_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(a2bus_grapplerplus_device::update_strobe), this)); + + m_next_strobe = 1U; + + save_item(NAME(m_data_latch)); + save_item(NAME(m_irq_disable)); + save_item(NAME(m_irq)); + save_item(NAME(m_next_strobe)); + + m_strobe_timer->adjust(attotime::from_ticks(7, clock())); +} + + +void a2bus_grapplerplus_device::device_reset() +{ + a2bus_grapplerplus_device_base::device_reset(); + + m_irq_disable = 1U; + if (m_irq) + { + m_irq = 0x00U; + lower_slot_irq(); + } +} + + + +//-------------------------------------------------- +// a2bus_grapplerplus_device_base implementation +//-------------------------------------------------- + +void a2bus_grapplerplus_device::data_latched(u8 data) +{ + // remember MSB can be forced low by DIP switch + m_data_latch = data; + m_printer_out->write(m_data_latch & (BIT(m_s1->read(), 3) ? 0xffU : 0x7fU)); + + // generate strobe pulse after one clock cycle + m_next_strobe = 0U; + if (!m_strobe_timer->enabled()) + { + LOG("Start strobe timer\n"); + m_strobe_timer->adjust(attotime::from_ticks(7, clock())); + } +} + + +void a2bus_grapplerplus_device::ack_latch_set() +{ + if (!m_irq_disable && !m_irq) + { + LOG("Asserting slot IRQ\n"); + m_irq = 0x80U; + raise_slot_irq(); + } +} + + +void a2bus_grapplerplus_device::ack_latch_cleared() +{ + if (m_irq) + { + assert(!m_irq_disable); + LOG("Releasing slot IRQ\n"); + m_irq = 0x00U; + lower_slot_irq(); + } +} + + + +//-------------------------------------------------- +// timer handlers +//-------------------------------------------------- + +TIMER_CALLBACK_MEMBER(a2bus_grapplerplus_device::update_strobe) +{ + LOG("Output /STROBE=%u\n", m_next_strobe); + m_printer_conn->write_strobe(m_next_strobe); + if (!m_next_strobe) + { + LOG("Start strobe timer\n"); + m_next_strobe = 1U; + m_strobe_timer->adjust(attotime::from_ticks(7, clock())); + } +} + + + +//============================================================== +// Buffered Grappler+ implementation +//============================================================== + +a2bus_buf_grapplerplus_device::a2bus_buf_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + a2bus_buf_grapplerplus_device(mconfig, A2BUS_BUFGRAPPLERPLUS, tag, owner, clock) +{ +} + + +a2bus_buf_grapplerplus_device::a2bus_buf_grapplerplus_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : + a2bus_grapplerplus_device_base(mconfig, type, tag, owner, clock), + m_mcu(*this, "mcu"), + m_ram(), + m_ram_row(0xff00), + m_ram_mask(0x00U), + m_mcu_p2(0xffU), + m_data_latch(0xffU), + m_ibusy(1U), + m_buf_ack_latch(1U), + m_buf_ack_in(1U) +{ +} + + + +//-------------------------------------------------- +// device_a2bus_card_interface implementation +//-------------------------------------------------- + +u8 a2bus_buf_grapplerplus_device::read_c0nx(u8 offset) +{ + return + ((m_s1->read() & 0x0fU) << 4) | + (m_ibusy << 3) | + (pe_in() << 2) | + (slct_in() << 1) | + ack_latch(); +} + + + +//-------------------------------------------------- +// device_t implementation +//-------------------------------------------------- + +tiny_rom_entry const *a2bus_buf_grapplerplus_device::device_rom_region() const +{ + return ROM_NAME(bufgrapplerplus); +} + + +void a2bus_buf_grapplerplus_device::device_add_mconfig(machine_config &config) +{ + // 1982 schematics show MCU driven by 7M clock + device_add_mconfig(config, DERIVED_CLOCK(1, 1)); +} + + +ioport_constructor a2bus_buf_grapplerplus_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(bufgrapplerplus); +} + + +void a2bus_buf_grapplerplus_device::device_start() +{ + a2bus_grapplerplus_device_base::device_start(); + + m_ram = std::make_unique(0x10000); + + save_pointer(NAME(m_ram), 0x10000); + save_item(NAME(m_ram_row)); + save_item(NAME(m_ram_mask)); + save_item(NAME(m_mcu_p2)); + save_item(NAME(m_data_latch)); + save_item(NAME(m_ibusy)); + save_item(NAME(m_buf_ack_latch)); + save_item(NAME(m_buf_ack_in)); +} + + +void a2bus_buf_grapplerplus_device::device_reset() +{ + // The MCU is not reset when /RST is asserted. Instead, /RST is + // connected to P27. Pressing the reset key(s) momentarily will not + // clear the print buffer - the host Apple II can be reset without + // interrupting a long print job. Holding the reset key(s) for two + // seconds clears the buffer. Holding the reset key(s) on initial + // boot enters the RAM test (results are printed). MAME doesn't + // currently cater for devices that don't reset their children on + // reset, and Apple II slots don't currently expose the /RST signal + // directly. + + a2bus_grapplerplus_device_base::device_reset(); + + // should only do this on initial reset, but we get away with it here because the MCU is automatically reset even if it shouldn't be + m_ram_mask = ioport("CNF")->read(); +} + + + +//-------------------------------------------------- +// helpers +//-------------------------------------------------- + +template +void a2bus_buf_grapplerplus_device::device_add_mconfig(machine_config &config, T &&mcu_clock) +{ + a2bus_grapplerplus_device_base::device_add_mconfig(config); + + m_printer_conn->ack_handler().set(FUNC(a2bus_buf_grapplerplus_device::buf_ack_w)); + + // P22 is tied high, pulling it low is used for some factory test mode + I8048(config, m_mcu, std::forward(mcu_clock)); + m_mcu->set_addrmap(AS_IO, &a2bus_buf_grapplerplus_device::mcu_io); + m_mcu->p2_out_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_p2_w)); + m_mcu->t0_in_cb().set([this] () { return busy_in(); }); + m_mcu->t1_in_cb().set([this] () { return m_buf_ack_latch; }); + m_mcu->bus_in_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_bus_r)); + m_mcu->bus_out_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_bus_w)); +} + + + +//-------------------------------------------------- +// a2bus_grapplerplus_device_base implementation +//-------------------------------------------------- + +void a2bus_buf_grapplerplus_device::data_latched(u8 data) +{ + // IBUSY is exposed on C0nX + if (!m_ibusy) + LOG("Setting IBUSY\n"); + else + LOG("IBUSY already set\n"); + m_ibusy = 1U; + + // these signals cross executable device domains + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::set_buf_data), this), int(unsigned(data))); + m_mcu->set_input_line(MCS48_INPUT_IRQ, ASSERT_LINE); +} + + + +//-------------------------------------------------- +// printer status inputs +//-------------------------------------------------- + +DECLARE_WRITE_LINE_MEMBER(a2bus_buf_grapplerplus_device::buf_ack_w) +{ + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::set_buf_ack_in), this), state ? 1 : 0); +} + + + +//-------------------------------------------------- +// MCU I/O handlers +//-------------------------------------------------- + +void a2bus_buf_grapplerplus_device::mcu_io(address_map &map) +{ + map(0x00, 0xff).nopr(); // read to put the BUS lines in high-impedance state before a real read using INS +} + + +void a2bus_buf_grapplerplus_device::mcu_p2_w(u8 data) +{ + // check for changed bits + u8 const diff(data ^ m_mcu_p2); + m_mcu_p2 = data; + + // P20 enables /CAS on /RD or /WR + if (BIT(diff, 0)) + LOG("RAM EN=%u\n", BIT(data, 0)); + + // row address strobe + if (BIT(diff, 1)) + { + if (!BIT(data, 1)) + { + LOG("Row address %02X\n", m_mcu->p1_r()); + m_ram_row = u16(m_mcu->p1_r()) << 8; + } + else + { + LOG("Released /RAS\n"); + } + } + + // P23 is the /IOEN signal + if (BIT(diff, 3)) + LOG("/IOEN=%u\n", BIT(data, 3)); + + // P24 allows fast DRAM refresh using ALE for /RAS + if (BIT(diff, 4)) + LOG(BIT(data, 4) ? "Start DRAM refresh\n" : "End DRAM refresh\n"); + + // P25 is the strobe output and clears the acknowledge latch + if (BIT(diff, 5)) + { + if (BIT(data, 5)) + { + if (m_buf_ack_in) + { + if (m_buf_ack_latch) + LOG("T1 already set\n"); + else + LOG("Setting T1\n"); + m_buf_ack_latch = 1U; + } + else + { + LOG("/ACK asserted, not setting T1\n"); + } + } + LOG("Output /STROBE=%u\n", BIT(data, 5)); + m_printer_conn->write_strobe(BIT(data, 5)); + } +} + + +u8 a2bus_buf_grapplerplus_device::mcu_bus_r() +{ + u8 result(0xffU); + + // RAM EN enables RAM + if (BIT(m_mcu_p2, 0)) + { + if (!BIT(m_mcu_p2, 1)) + { + u16 const addr(m_ram_row | u16(m_mcu->p1_r())); + LOG("Read RAM @%04X=%02X\n", addr, m_ram[addr]); + result &= m_ram[addr] | m_ram_mask; + } + else + { + LOG("/RD asserted /CAS while /RAS not asserted\n"); + } + } + + // /IOEN enables the data latch, pulses /IACK and clears IBUSY on /RD + if (!BIT(m_mcu_p2, 3)) + { + LOG("Read data latch %02X\n", m_data_latch); + result &= m_data_latch; + machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::clear_ibusy), this)); + m_mcu->set_input_line(MCS48_INPUT_IRQ, CLEAR_LINE); + ack_w(0); + ack_w(1); + } + + return result; +} + + +void a2bus_buf_grapplerplus_device::mcu_bus_w(u8 data) +{ + // RAM EN enables RAM + if (BIT(m_mcu_p2, 0)) + { + if (!BIT(m_mcu_p2, 1)) + { + u16 const addr(m_ram_row | u16(m_mcu->p1_r())); + LOG("Wrote RAM @%04X=%02X\n", addr, data); + m_ram[addr] = data | m_ram_mask; + } + else + { + LOG("/WR asserted /CAS while /RAS not asserted\n"); + } + } + + // /IOEN enables output latch + if (!BIT(m_mcu_p2, 3)) + { + LOG("Output data %02X\n", data); + m_printer_out->write(data); + } +} + + + +//-------------------------------------------------- +// synchronised signals +//-------------------------------------------------- + +void a2bus_buf_grapplerplus_device::set_buf_data(void *ptr, s32 param) +{ + m_data_latch = u8(u32(param)); +} + + +void a2bus_buf_grapplerplus_device::set_buf_ack_in(void *ptr, s32 param) +{ + if (u32(param) != m_buf_ack_in) + { + LOG("/ACK=%d\n", param); + m_buf_ack_in = u8(u32(param)); + if (!param) + { + if (m_buf_ack_latch) + LOG("Clearing T1\n"); + else + LOG("No data output since previous acknowledge\n"); + m_buf_ack_latch = 0U; + } + } +} + + +void a2bus_buf_grapplerplus_device::clear_ibusy(void *ptr, s32 param) +{ + if (m_ibusy) + { + LOG("Clearing IBUSY\n"); + m_ibusy = 0U; + } + else + { + LOG("IBUSY already clear\n"); + } +} + + + +//============================================================== +// Buffered Grappler+ rev A implementation +//============================================================== + +a2bus_buf_grapplerplus_reva_device::a2bus_buf_grapplerplus_reva_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + a2bus_buf_grapplerplus_device(mconfig, A2BUS_BUFGRAPPLERPLUSA, tag, owner, clock) +{ +} + + + +//-------------------------------------------------- +// device_t implementation +//-------------------------------------------------- + +void a2bus_buf_grapplerplus_reva_device::device_add_mconfig(machine_config &config) +{ + // boards with 6 MHz clock crystal for MCU have been seen with both UVEPROM and mask ROM parts + // ORANGE MICRO INC., 1983 + // ASSY NO, 72 BGP 00001 REV A + // PART NO. 95PCB00003 + a2bus_buf_grapplerplus_device::device_add_mconfig(config, 6_MHz_XTAL); +} diff --git a/src/devices/bus/a2bus/grappler.h b/src/devices/bus/a2bus/grappler.h new file mode 100644 index 00000000000..8e3857414da --- /dev/null +++ b/src/devices/bus/a2bus/grappler.h @@ -0,0 +1,284 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*********************************************************************** + + Orange Micro Grappler/Grappler+ Printer Interface + + With references to schematics from The Grappler™ Interface + Operators Manual (Copyright 1982 Orance Micro, Inc.) and + Grappler™+ Printer Interface Series Operators Manual (© Orange + Micro, Inc. 1982). This uses the IC locations on the "long" + version of the Grappler+ card - the newer "short" version of the + card has slightly different circuitry and completely different IC + locations. + + 26-pin two-row header to printer: + + STB 1 2 GND + D0 3 4 GND + D1 5 6 GND + D2 7 8 GND + D3 9 10 GND + D4 11 12 GND + D5 23 14 GND + D6 15 16 GND + D7 17 18 GND + ACK 19 20 GND + BUSY 21 22 GND + P.E. 23 24 GND + SLCT 25 26 GND + + Orange Micro Buffered Grappler+ Printer Interface + + 26-pin two-row header to printer: + + STB 1 2 GND + D0 3 4 GND + D1 5 6 GND + D2 7 8 GND + D3 9 10 GND + D4 11 12 GND + D5 23 14 GND + D6 15 16 GND + D7 17 18 GND + ACK 19 20 GND + BUSY 21 22 GND + P.E. 23 24 GND + SLCT 25 26 N/C + +***********************************************************************/ +#ifndef MAME_BUS_A2BUS_GRAPPLERPLUS_H +#define MAME_BUS_A2BUS_GRAPPLERPLUS_H + +#pragma once + +#include "a2bus.h" + +#include "bus/centronics/ctronics.h" +#include "cpu/mcs48/mcs48.h" + + +class a2bus_grappler_device_base : public device_t, public device_a2bus_card_interface +{ +public: + // device_a2bus_card_interface implementation + virtual u8 read_c800(u16 offset) override; + +protected: + a2bus_grappler_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock); + + // signal state + u8 busy_in() const { return m_busy_in; } + u8 pe_in() const { return m_pe_in; } + u8 slct_in() const { return m_slct_in; } + + required_device m_printer_conn; + required_device m_printer_out; + required_region_ptr m_rom; + +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + + // helpers + void set_rom_bank(u16 rom_bank); + +private: + // printer status inputs + DECLARE_WRITE_LINE_MEMBER(busy_w); + DECLARE_WRITE_LINE_MEMBER(pe_w); + DECLARE_WRITE_LINE_MEMBER(slct_w); + + // synchronised printer status inputs + void set_busy_in(void *ptr, s32 param); + void set_pe_in(void *ptr, s32 param); + void set_slct_in(void *ptr, s32 param); + + u16 m_rom_bank; // U2D (pin 13) + u8 m_busy_in; // printer connector pin 21 (synchronised) + u8 m_pe_in; // printer connector pin 23 (synchronised) + u8 m_slct_in; // printer connector pin 25 (synchronised) +}; + + +class a2bus_grappler_device : public a2bus_grappler_device_base +{ +public: + a2bus_grappler_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + // 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: + // device_t implementation + virtual tiny_rom_entry const *device_rom_region() const override; + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + +private: + // printer status inputs + DECLARE_WRITE_LINE_MEMBER(ack_w); + + // synchronised signals + void set_data(void *ptr, s32 param); + void set_strobe(void *ptr, s32 param); + void set_ack_in(void *ptr, s32 param); + + u8 m_strobe; // U3 (pin 4) + u8 m_ack_latch; // U3 (pin 13) + u8 m_ack_in; // printer connector pin 19 (synchronised) +}; + + +class a2bus_grapplerplus_device_base : public a2bus_grappler_device_base +{ +public: + // DIP switch handlers + virtual DECLARE_INPUT_CHANGED_MEMBER(sw_msb) { } + + // device_a2bus_card_interface implementation + 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_grapplerplus_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock); + + // device_t implementation + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + virtual void device_reset() override; + + // ACK latch set input + DECLARE_WRITE_LINE_MEMBER(ack_w); + + // signal state + u8 ack_latch() const { return m_ack_latch; } + + required_ioport m_s1; + +private: + // synchronised printer status inputs + void set_ack_in(void *ptr, s32 param); + + // for derived devices to implement + virtual void data_latched(u8 data) = 0; + virtual void ack_latch_set() { } + virtual void ack_latch_cleared() { } + + u8 m_ack_latch; // U2C (pin 9) + u8 m_ack_in; // printer connector pin 19 (synchronised) +}; + + +class a2bus_grapplerplus_device : public a2bus_grapplerplus_device_base +{ +public: + a2bus_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + // DIP switch handlers + virtual DECLARE_INPUT_CHANGED_MEMBER(sw_msb) override; + + // device_a2bus_card_interface implementation + virtual u8 read_c0nx(u8 offset) override; + virtual void write_c0nx(u8 offset, u8 data) override; + +protected: + // device_t implementation + virtual tiny_rom_entry const *device_rom_region() const override; + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + +private: + // a2bus_grapplerplus_device_base implementation + virtual void data_latched(u8 data) override; + virtual void ack_latch_set() override; + virtual void ack_latch_cleared() override; + + // timer handlers + TIMER_CALLBACK_MEMBER(update_strobe); + + emu_timer * m_strobe_timer; + + u8 m_data_latch; // U10 + u8 m_irq_disable; // U2A (pin 4) + u8 m_irq; // U3D (pin 13) + u8 m_next_strobe; // U5A (pin 5) +}; + + +class a2bus_buf_grapplerplus_device : public a2bus_grapplerplus_device_base +{ +public: + a2bus_buf_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + // device_a2bus_card_interface implementation + virtual u8 read_c0nx(u8 offset) override; + +protected: + a2bus_buf_grapplerplus_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock); + + // device_t implementation + virtual tiny_rom_entry const *device_rom_region() const override; + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + virtual void device_reset() override; + + // helpers + template void device_add_mconfig(machine_config &config, T &&mcu_clock); + +private: + // a2bus_grapplerplus_device_base implementation + virtual void data_latched(u8 data) override; + + // printer status inputs + DECLARE_WRITE_LINE_MEMBER(buf_ack_w); + + // MCU I/O handlers + void mcu_io(address_map &map); + void mcu_p2_w(u8 data); + u8 mcu_bus_r(); + void mcu_bus_w(u8 data); + + // synchronised signals + void set_buf_data(void *ptr, s32 param); + void set_buf_ack_in(void *ptr, s32 param); + void clear_ibusy(void *ptr, s32 param); + + required_device m_mcu; + std::unique_ptr m_ram; + + u16 m_ram_row; // U1-U8 + u8 m_ram_mask; // mask out chips that are not installed + u8 m_mcu_p2; // U10 + u8 m_data_latch; // U14 (synchronised) + u8 m_ibusy; // U12 + u8 m_buf_ack_latch; // U12 + u8 m_buf_ack_in; // printer connector pin 19 (synchronised) +}; + + +class a2bus_buf_grapplerplus_reva_device : public a2bus_buf_grapplerplus_device +{ +public: + a2bus_buf_grapplerplus_reva_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + +protected: + // device_t implementation + virtual void device_add_mconfig(machine_config &config) override; +}; + + +DECLARE_DEVICE_TYPE(A2BUS_GRAPPLER, a2bus_grappler_device) +DECLARE_DEVICE_TYPE(A2BUS_GRAPPLERPLUS, a2bus_grapplerplus_device) +DECLARE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUS, a2bus_buf_grapplerplus_device) +DECLARE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUSA, a2bus_buf_grapplerplus_reva_device) + +#endif // MAME_BUS_A2BUS_GRAPPLERPLUS_H diff --git a/src/devices/bus/a2bus/grapplerplus.cpp b/src/devices/bus/a2bus/grapplerplus.cpp deleted file mode 100644 index f4e95e92b42..00000000000 --- a/src/devices/bus/a2bus/grapplerplus.cpp +++ /dev/null @@ -1,837 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Vas Crabb -#include "emu.h" -#include "grapplerplus.h" - -//#define VERBOSE 1 -//#define LOG_OUTPUT_FUNC osd_printf_info -#include "logmacro.h" - -namespace { - -ROM_START(grapplerplus) - // TODO: add other revisions - 3.3 is known to exist - - ROM_DEFAULT_BIOS("v32") - ROM_SYSTEM_BIOS(0, "v30", "ROM 3.0") - ROM_SYSTEM_BIOS(1, "v32", "ROM 3.2") - - ROM_REGION(0x1000, "rom", 0) - ROMX_LOAD( "3.0.u9", 0x0000, 0x1000, CRC(17cf5e02) SHA1(9b01a9b1cf7752987e03f9b0285eb9329d63b777), ROM_BIOS(0) ) - ROMX_LOAD( "3.2.u9", 0x0000, 0x1000, CRC(6f88b70c) SHA1(433ae61a0553ee9c1628ea5b6376dac848c04cad), ROM_BIOS(1) ) -ROM_END - - -ROM_START(bufgrapplerplus) - // TODO: confirm contents - // despite having the same version string, this differs from the Grapper+ 3.2.u9 ROM - - // 9433B-0141 - // 90ROM00002 - // GI8603CEY - // TAIWAN - ROM_REGION(0x1000, "rom", 0) - ROM_LOAD( "90rom00002.u18", 0x0000, 0x1000, CRC(cd07c7ef) SHA1(6c2f1375b5df6bb65dfca1444c064661242fef1a) ) - - // S 8450 - // SCN8048A - // C6N40 B - // 95ROM08048 - ROM_REGION(0x0400, "mcu", 0) - ROM_LOAD( "95rom08048.u10", 0x0000, 0x0400, CRC(55990f67) SHA1(f0907cf02d8c5dbf1bfacb0d626f2231142f0ff7) ) -ROM_END - - -INPUT_PORTS_START(grapplerplus) - PORT_START("S1") - PORT_DIPNAME(0x07, 0x00, "Printer Type") PORT_DIPLOCATION("S1:4,3,2") - PORT_DIPSETTING( 0x00, "Epson Series") - PORT_DIPSETTING( 0x01, "NEC 8023/C. Itoh 8510/DMP 85") - PORT_DIPSETTING( 0x02, "Star Gemini") - PORT_DIPSETTING( 0x03, "Anadex Printers") - PORT_DIPSETTING( 0x04, "Okidata 82A, 83A, 92, 93, 84") - PORT_DIPSETTING( 0x06, "Okidata 84 w/o Step II Graphics") - PORT_DIPSETTING( 0x05, "Apple Dot Matrix") - PORT_DIPSETTING( 0x07, "invalid") - PORT_DIPNAME(0x08, 0x08, "Most Significant Bit") PORT_DIPLOCATION("S1:1") PORT_CHANGED_MEMBER(DEVICE_SELF, a2bus_grapplerplus_device_base, sw_msb, 0) - PORT_DIPSETTING( 0x08, "Software Control") - PORT_DIPSETTING( 0x00, "Not Transmitted") -INPUT_PORTS_END - - -INPUT_PORTS_START(bufgrapplerplus) - PORT_INCLUDE(grapplerplus) - - PORT_START("CNF") - PORT_CONFNAME(0xff, 0x00, "RAM Size") - PORT_CONFSETTING( 0xfc, "16K (2 chips)") - PORT_CONFSETTING( 0xf0, "32K (4 chips)") - PORT_CONFSETTING( 0x00, "64K (8 chips)") -INPUT_PORTS_END - -} // anonymous namespace - - - -DEFINE_DEVICE_TYPE(A2BUS_GRAPPLERPLUS, a2bus_grapplerplus_device, "a2grapplerplus", "Orange Micro Grappler+ Printer Interface") -DEFINE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUS, a2bus_buf_grapplerplus_device, "a2bufgrapplerplus", "Orange Micro Buffered Grappler+ Printer Interface") -DEFINE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUSA, a2bus_buf_grapplerplus_reva_device, "a2bufgrapplerplusa", "Orange Micro Buffered Grappler+ (rev A) Printer Interface") - - - -//============================================================== -// Grappler+ base -//============================================================== - -a2bus_grapplerplus_device_base::a2bus_grapplerplus_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : - device_t(mconfig, type, tag, owner, clock), - device_a2bus_card_interface(mconfig, *this), - m_printer_conn(*this, "prn"), - m_printer_out(*this, "prn_out"), - m_s1(*this, "S1"), - m_rom(*this, "rom"), - m_rom_bank(0x0000U), - m_ack_latch(1U), - m_ack_in(1U), - m_busy_in(1U), - m_pe_in(1U), - m_slct_in(1U) -{ -} - - - -//-------------------------------------------------- -// device_t implementation -//-------------------------------------------------- - -void a2bus_grapplerplus_device_base::device_add_mconfig(machine_config &config) -{ - CENTRONICS(config, m_printer_conn, centronics_devices, "printer"); - m_printer_conn->busy_handler().set(FUNC(a2bus_grapplerplus_device_base::busy_w)); - m_printer_conn->perror_handler().set(FUNC(a2bus_grapplerplus_device_base::pe_w)); - m_printer_conn->select_handler().set(FUNC(a2bus_grapplerplus_device_base::slct_w)); - - OUTPUT_LATCH(config, m_printer_out); - m_printer_conn->set_output_latch(*m_printer_out); -} - - -ioport_constructor a2bus_grapplerplus_device_base::device_input_ports() const -{ - return INPUT_PORTS_NAME(grapplerplus); -} - - -void a2bus_grapplerplus_device_base::device_start() -{ - save_item(NAME(m_rom_bank)); - save_item(NAME(m_ack_latch)); - save_item(NAME(m_ack_in)); - save_item(NAME(m_busy_in)); - save_item(NAME(m_pe_in)); - save_item(NAME(m_slct_in)); -} - - -void a2bus_grapplerplus_device_base::device_reset() -{ - m_ack_latch = 1U; -} - - - -//-------------------------------------------------- -// device_a2bus_card_interface implementation -//-------------------------------------------------- - -void a2bus_grapplerplus_device_base::write_c0nx(u8 offset, u8 data) -{ - LOG("Write C0n%01X=%02X\n", offset, data); - - if (!(offset & 0x03U)) // !A0 && !A1 - write data - { - // latch output data - LOG("Latch data %02X\n", data); - data_latched(data); - - // clearing the ACK latch will acknowledge an interrupt - if (m_ack_in) - { - if (m_ack_latch) - LOG("Clearing acknowledge latch\n"); - else - LOG("Previous data not acknowledged\n"); - m_ack_latch = 0U; - ack_latch_cleared(); - } - else - { - LOG("/ACK asserted, not clearing acknowledge latch\n"); - } - } - - if (BIT(offset, 0)) // A0 - select high ROM bank - { - if (!m_rom_bank) - LOG("Select high ROM bank\n"); - else - LOG("High ROM bank already selected\n"); - m_rom_bank = 0x0800U; - } -} - - -u8 a2bus_grapplerplus_device_base::read_cnxx(u8 offset) -{ - if (!machine().side_effects_disabled()) - { - if (m_rom_bank) - LOG("Select low ROM bank\n"); - m_rom_bank = 0x0000U; - } - return m_rom[(!m_ack_latch && BIT(offset, 7)) ? (offset & 0xbfU) : offset]; -} - - -void a2bus_grapplerplus_device_base::write_cnxx(u8 offset, u8 data) -{ - LOG("Write Cn%02X=%02X (bus conflict)\n", offset, data); - - if (m_rom_bank) - LOG("Select low ROM bank\n"); - m_rom_bank = 0x0000U; -} - - -u8 a2bus_grapplerplus_device_base::read_c800(u16 offset) -{ - return m_rom[(offset & 0x07ffU) | m_rom_bank]; -} - - - -//-------------------------------------------------- -// printer status inputs -//-------------------------------------------------- - -WRITE_LINE_MEMBER(a2bus_grapplerplus_device_base::ack_w) -{ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grapplerplus_device_base::set_ack_in), this), state ? 1 : 0); -} - - -WRITE_LINE_MEMBER(a2bus_grapplerplus_device_base::busy_w) -{ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grapplerplus_device_base::set_busy_in), this), state ? 1 : 0); -} - - -WRITE_LINE_MEMBER(a2bus_grapplerplus_device_base::pe_w) -{ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grapplerplus_device_base::set_pe_in), this), state ? 1 : 0); -} - - -WRITE_LINE_MEMBER(a2bus_grapplerplus_device_base::slct_w) -{ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_grapplerplus_device_base::set_slct_in), this), state ? 1 : 0); -} - - - -//-------------------------------------------------- -// synchronised printer status inputs -//-------------------------------------------------- - -void a2bus_grapplerplus_device_base::set_ack_in(void *ptr, s32 param) -{ - if (u32(param) != m_ack_in) - { - LOG("/ACK=%d\n", param); - m_ack_in = u8(u32(param)); - if (!param) - { - if (!m_ack_latch) - LOG("Set acknowledge latch\n"); - else - LOG("No data written since previous acknowledge\n"); - m_ack_latch = 1U; - ack_latch_set(); - } - } -} - - -void a2bus_grapplerplus_device_base::set_busy_in(void *ptr, s32 param) -{ - if (u32(param) != m_busy_in) - { - LOG("BUSY=%d\n", param); - m_busy_in = u8(u32(param)); - } -} - - -void a2bus_grapplerplus_device_base::set_pe_in(void *ptr, s32 param) -{ - if (u32(param) != m_pe_in) - { - LOG("PAPER EMPTY=%d\n", param); - m_pe_in = u8(u32(param)); - } -} - - -void a2bus_grapplerplus_device_base::set_slct_in(void *ptr, s32 param) -{ - if (u32(param) != m_slct_in) - { - LOG("SELECT=%d\n", param); - m_slct_in = u8(u32(param)); - } -} - - - -//============================================================== -// Grappler+ implementation -//============================================================== - -a2bus_grapplerplus_device::a2bus_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : - a2bus_grapplerplus_device_base(mconfig, A2BUS_GRAPPLERPLUS, tag, owner, clock), - m_strobe_timer(nullptr), - m_data_latch(0xffU), - m_irq_disable(1U), - m_irq(0x00U), - m_next_strobe(1U) -{ -} - - - -//-------------------------------------------------- -// DIP switch handlers -//-------------------------------------------------- - -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)); -} - - - -//-------------------------------------------------- -// device_a2bus_card_interface implementation -//-------------------------------------------------- - -u8 a2bus_grapplerplus_device::read_c0nx(u8 offset) -{ - return - m_irq | - ((m_s1->read() & 0x07U) << 4) | - (busy_in() << 3) | - (pe_in() << 2) | - (slct_in() << 1) | - ack_latch(); -} - - -void a2bus_grapplerplus_device::write_c0nx(u8 offset, u8 data) -{ - a2bus_grapplerplus_device_base::write_c0nx(offset, data); - - if (BIT(offset, 1)) // A1 - disable interrupt - { - if (!m_irq_disable) - LOG("Disable interrupt request\n"); - else - LOG("Interrupt request already disabled\n"); - m_irq_disable = 1U; - if (m_irq) - { - assert(ack_latch()); - LOG("Releasing slot IRQ\n"); - m_irq = 0x00U; - lower_slot_irq(); - } - } - else if (BIT(offset, 2)) // A2 - enable interrupt - { - if (m_irq_disable) - LOG("Enable interrupt request\n"); - else - LOG("Interrupt request already enabled\n"); - m_irq_disable = 0U; - if (ack_latch() && !m_irq) - { - LOG("Asserting slot IRQ\n"); - m_irq = 0x80U; - raise_slot_irq(); - } - } -} - - - -//-------------------------------------------------- -// device_t implementation -//-------------------------------------------------- - -tiny_rom_entry const *a2bus_grapplerplus_device::device_rom_region() const -{ - return ROM_NAME(grapplerplus); -} - - -void a2bus_grapplerplus_device::device_add_mconfig(machine_config &config) -{ - a2bus_grapplerplus_device_base::device_add_mconfig(config); - - m_printer_conn->ack_handler().set(FUNC(a2bus_grapplerplus_device::ack_w)); -} - - -void a2bus_grapplerplus_device::device_start() -{ - a2bus_grapplerplus_device_base::device_start(); - - m_strobe_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(a2bus_grapplerplus_device::update_strobe), this)); - - m_next_strobe = 1U; - - save_item(NAME(m_data_latch)); - save_item(NAME(m_irq_disable)); - save_item(NAME(m_irq)); - save_item(NAME(m_next_strobe)); - - m_strobe_timer->adjust(attotime::from_ticks(7, clock())); -} - - -void a2bus_grapplerplus_device::device_reset() -{ - a2bus_grapplerplus_device_base::device_reset(); - - m_irq_disable = 1U; - if (m_irq) - { - m_irq = 0x00U; - lower_slot_irq(); - } -} - - - -//-------------------------------------------------- -// a2bus_grapplerplus_device_base implementation -//-------------------------------------------------- - -void a2bus_grapplerplus_device::data_latched(u8 data) -{ - // remember MSB can be forced low by DIP switch - m_data_latch = data; - m_printer_out->write(m_data_latch & (BIT(m_s1->read(), 3) ? 0xffU : 0x7fU)); - - // generate strobe pulse after one clock cycle - m_next_strobe = 0U; - if (!m_strobe_timer->enabled()) - { - LOG("Start strobe timer\n"); - m_strobe_timer->adjust(attotime::from_ticks(7, clock())); - } -} - - -void a2bus_grapplerplus_device::ack_latch_set() -{ - if (!m_irq_disable && !m_irq) - { - LOG("Asserting slot IRQ\n"); - m_irq = 0x80U; - raise_slot_irq(); - } -} - - -void a2bus_grapplerplus_device::ack_latch_cleared() -{ - if (m_irq) - { - assert(!m_irq_disable); - LOG("Releasing slot IRQ\n"); - m_irq = 0x00U; - lower_slot_irq(); - } -} - - - -//-------------------------------------------------- -// timer handlers -//-------------------------------------------------- - -TIMER_CALLBACK_MEMBER(a2bus_grapplerplus_device::update_strobe) -{ - LOG("Output /STROBE=%u\n", m_next_strobe); - m_printer_conn->write_strobe(m_next_strobe); - if (!m_next_strobe) - { - LOG("Start strobe timer\n"); - m_next_strobe = 1U; - m_strobe_timer->adjust(attotime::from_ticks(7, clock())); - } -} - - - -//============================================================== -// Buffered Grappler+ implementation -//============================================================== - -a2bus_buf_grapplerplus_device::a2bus_buf_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : - a2bus_buf_grapplerplus_device(mconfig, A2BUS_BUFGRAPPLERPLUS, tag, owner, clock) -{ -} - - -a2bus_buf_grapplerplus_device::a2bus_buf_grapplerplus_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock) : - a2bus_grapplerplus_device_base(mconfig, type, tag, owner, clock), - m_mcu(*this, "mcu"), - m_ram(), - m_ram_row(0xff00), - m_ram_mask(0x00U), - m_mcu_p2(0xffU), - m_data_latch(0xffU), - m_ibusy(1U), - m_buf_ack_latch(1U), - m_buf_ack_in(1U) -{ -} - - - -//-------------------------------------------------- -// device_a2bus_card_interface implementation -//-------------------------------------------------- - -u8 a2bus_buf_grapplerplus_device::read_c0nx(u8 offset) -{ - return - ((m_s1->read() & 0x0fU) << 4) | - (m_ibusy << 3) | - (pe_in() << 2) | - (slct_in() << 1) | - ack_latch(); -} - - - -//-------------------------------------------------- -// device_t implementation -//-------------------------------------------------- - -tiny_rom_entry const *a2bus_buf_grapplerplus_device::device_rom_region() const -{ - return ROM_NAME(bufgrapplerplus); -} - - -void a2bus_buf_grapplerplus_device::device_add_mconfig(machine_config &config) -{ - // 1982 schematics show MCU driven by 7M clock - device_add_mconfig(config, DERIVED_CLOCK(1, 1)); -} - - -ioport_constructor a2bus_buf_grapplerplus_device::device_input_ports() const -{ - return INPUT_PORTS_NAME(bufgrapplerplus); -} - - -void a2bus_buf_grapplerplus_device::device_start() -{ - a2bus_grapplerplus_device_base::device_start(); - - m_ram = std::make_unique(0x10000); - - save_pointer(NAME(m_ram), 0x10000); - save_item(NAME(m_ram_row)); - save_item(NAME(m_ram_mask)); - save_item(NAME(m_mcu_p2)); - save_item(NAME(m_data_latch)); - save_item(NAME(m_ibusy)); - save_item(NAME(m_buf_ack_latch)); - save_item(NAME(m_buf_ack_in)); -} - - -void a2bus_buf_grapplerplus_device::device_reset() -{ - // The MCU is not reset when /RST is asserted. Instead, /RST is - // connected to P27. Pressing the reset key(s) momentarily will not - // clear the print buffer - the host Apple II can be reset without - // interrupting a long print job. Holding the reset key(s) for two - // seconds clears the buffer. Holding the reset key(s) on initial - // boot enters the RAM test (results are printed). MAME doesn't - // currently cater for devices that don't reset their children on - // reset, and Apple II slots don't currently expose the /RST signal - // directly. - - a2bus_grapplerplus_device_base::device_reset(); - - // should only do this on initial reset, but we get away with it here because the MCU is automatically reset even if it shouldn't be - m_ram_mask = ioport("CNF")->read(); -} - - - -//-------------------------------------------------- -// helpers -//-------------------------------------------------- - -template -void a2bus_buf_grapplerplus_device::device_add_mconfig(machine_config &config, T &&mcu_clock) -{ - a2bus_grapplerplus_device_base::device_add_mconfig(config); - - m_printer_conn->ack_handler().set(FUNC(a2bus_buf_grapplerplus_device::buf_ack_w)); - - // P22 is tied high, pulling it low is used for some factory test mode - I8048(config, m_mcu, std::forward(mcu_clock)); - m_mcu->set_addrmap(AS_IO, &a2bus_buf_grapplerplus_device::mcu_io); - m_mcu->p2_out_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_p2_w)); - m_mcu->t0_in_cb().set([this] () { return busy_in(); }); - m_mcu->t1_in_cb().set([this] () { return m_buf_ack_latch; }); - m_mcu->bus_in_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_bus_r)); - m_mcu->bus_out_cb().set(FUNC(a2bus_buf_grapplerplus_device::mcu_bus_w)); -} - - - -//-------------------------------------------------- -// a2bus_grapplerplus_device_base implementation -//-------------------------------------------------- - -void a2bus_buf_grapplerplus_device::data_latched(u8 data) -{ - // IBUSY is exposed on C0nX - if (!m_ibusy) - LOG("Setting IBUSY\n"); - else - LOG("IBUSY already set\n"); - m_ibusy = 1U; - - // these signals cross executable device domains - machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::set_buf_data), this), int(unsigned(data))); - m_mcu->set_input_line(MCS48_INPUT_IRQ, ASSERT_LINE); -} - - - -//-------------------------------------------------- -// printer status inputs -//-------------------------------------------------- - -DECLARE_WRITE_LINE_MEMBER(a2bus_buf_grapplerplus_device::buf_ack_w) -{ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::set_buf_ack_in), this), state ? 1 : 0); -} - - - -//-------------------------------------------------- -// MCU I/O handlers -//-------------------------------------------------- - -void a2bus_buf_grapplerplus_device::mcu_io(address_map &map) -{ - map(0x00, 0xff).nopr(); // read to put the BUS lines in high-impedance state before a real read using INS -} - - -void a2bus_buf_grapplerplus_device::mcu_p2_w(u8 data) -{ - // check for changed bits - u8 const diff(data ^ m_mcu_p2); - m_mcu_p2 = data; - - // P20 enables /CAS on /RD or /WR - if (BIT(diff, 0)) - LOG("RAM EN=%u\n", BIT(data, 0)); - - // row address strobe - if (BIT(diff, 1)) - { - if (!BIT(data, 1)) - { - LOG("Row address %02X\n", m_mcu->p1_r()); - m_ram_row = u16(m_mcu->p1_r()) << 8; - } - else - { - LOG("Released /RAS\n"); - } - } - - // P23 is the /IOEN signal - if (BIT(diff, 3)) - LOG("/IOEN=%u\n", BIT(data, 3)); - - // P24 allows fast DRAM refresh using ALE for /RAS - if (BIT(diff, 4)) - LOG(BIT(data, 4) ? "Start DRAM refresh\n" : "End DRAM refresh\n"); - - // P25 is the strobe output and clears the acknowledge latch - if (BIT(diff, 5)) - { - if (BIT(data, 5)) - { - if (m_buf_ack_in) - { - if (m_buf_ack_latch) - LOG("T1 already set\n"); - else - LOG("Setting T1\n"); - m_buf_ack_latch = 1U; - } - else - { - LOG("/ACK asserted, not setting T1\n"); - } - } - LOG("Output /STROBE=%u\n", BIT(data, 5)); - m_printer_conn->write_strobe(BIT(data, 5)); - } -} - - -u8 a2bus_buf_grapplerplus_device::mcu_bus_r() -{ - u8 result(0xffU); - - // RAM EN enables RAM - if (BIT(m_mcu_p2, 0)) - { - if (!BIT(m_mcu_p2, 1)) - { - u16 const addr(m_ram_row | u16(m_mcu->p1_r())); - LOG("Read RAM @%04X=%02X\n", addr, m_ram[addr]); - result &= m_ram[addr] | m_ram_mask; - } - else - { - LOG("/RD asserted /CAS while /RAS not asserted\n"); - } - } - - // /IOEN enables the data latch, pulses /IACK and clears IBUSY on /RD - if (!BIT(m_mcu_p2, 3)) - { - LOG("Read data latch %02X\n", m_data_latch); - result &= m_data_latch; - machine().scheduler().synchronize(timer_expired_delegate(FUNC(a2bus_buf_grapplerplus_device::clear_ibusy), this)); - m_mcu->set_input_line(MCS48_INPUT_IRQ, CLEAR_LINE); - ack_w(0); - ack_w(1); - } - - return result; -} - - -void a2bus_buf_grapplerplus_device::mcu_bus_w(u8 data) -{ - // RAM EN enables RAM - if (BIT(m_mcu_p2, 0)) - { - if (!BIT(m_mcu_p2, 1)) - { - u16 const addr(m_ram_row | u16(m_mcu->p1_r())); - LOG("Wrote RAM @%04X=%02X\n", addr, data); - m_ram[addr] = data | m_ram_mask; - } - else - { - LOG("/WR asserted /CAS while /RAS not asserted\n"); - } - } - - // /IOEN enables output latch - if (!BIT(m_mcu_p2, 3)) - { - LOG("Output data %02X\n", data); - m_printer_out->write(data); - } -} - - - -//-------------------------------------------------- -// synchronised signals -//-------------------------------------------------- - -void a2bus_buf_grapplerplus_device::set_buf_data(void *ptr, s32 param) -{ - m_data_latch = u8(u32(param)); -} - - -void a2bus_buf_grapplerplus_device::set_buf_ack_in(void *ptr, s32 param) -{ - if (u32(param) != m_buf_ack_in) - { - LOG("/ACK=%d\n", param); - m_buf_ack_in = u8(u32(param)); - if (!param) - { - if (m_buf_ack_latch) - LOG("Clearing T1\n"); - else - LOG("No data output since previous acknowledge\n"); - m_buf_ack_latch = 0U; - } - } -} - - -void a2bus_buf_grapplerplus_device::clear_ibusy(void *ptr, s32 param) -{ - if (m_ibusy) - { - LOG("Clearing IBUSY\n"); - m_ibusy = 0U; - } - else - { - LOG("IBUSY already clear\n"); - } -} - - - -//============================================================== -// Buffered Grappler+ rev A implementation -//============================================================== - -a2bus_buf_grapplerplus_reva_device::a2bus_buf_grapplerplus_reva_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : - a2bus_buf_grapplerplus_device(mconfig, A2BUS_BUFGRAPPLERPLUSA, tag, owner, clock) -{ -} - - - -//-------------------------------------------------- -// device_t implementation -//-------------------------------------------------- - -void a2bus_buf_grapplerplus_reva_device::device_add_mconfig(machine_config &config) -{ - // boards with 6 MHz clock crystal for MCU have been seen with both UVEPROM and mask ROM parts - // ORANGE MICRO INC., 1983 - // ASSY NO, 72 BGP 00001 REV A - // PART NO. 95PCB00003 - a2bus_buf_grapplerplus_device::device_add_mconfig(config, 6_MHz_XTAL); -} diff --git a/src/devices/bus/a2bus/grapplerplus.h b/src/devices/bus/a2bus/grapplerplus.h deleted file mode 100644 index d2bb09ab3cc..00000000000 --- a/src/devices/bus/a2bus/grapplerplus.h +++ /dev/null @@ -1,225 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Vas Crabb -/*********************************************************************** - - Orange Micro Grappler+ Printer Interface - - With references to schematic from Grappler™+ Printer Interface - Series Operators Manual (© Orange Micro, Inc. 1982). This uses - the IC locations on the "long" version of the card. The newer - "short" version of the card has slightly different circuitry - and completely different IC locations. - - 26-pin two-row header to printer: - - STB 1 2 GND - D0 3 4 GND - D1 5 6 GND - D2 7 8 GND - D3 9 10 GND - D4 11 12 GND - D5 23 14 GND - D6 15 16 GND - D7 17 18 GND - ACK 19 20 GND - BUSY 21 22 GND - P.E. 23 24 GND - SLCT 25 26 GND - - Orange Micro Buffered Grappler+ Printer Interface - - 26-pin two-row header to printer: - - STB 1 2 GND - D0 3 4 GND - D1 5 6 GND - D2 7 8 GND - D3 9 10 GND - D4 11 12 GND - D5 23 14 GND - D6 15 16 GND - D7 17 18 GND - ACK 19 20 GND - BUSY 21 22 GND - P.E. 23 24 GND - SLCT 25 26 N/C - -***********************************************************************/ -#ifndef MAME_BUS_A2BUS_GRAPPLERPLUS_H -#define MAME_BUS_A2BUS_GRAPPLERPLUS_H - -#pragma once - -#include "a2bus.h" - -#include "bus/centronics/ctronics.h" -#include "cpu/mcs48/mcs48.h" - - -class a2bus_grapplerplus_device_base : public device_t, public device_a2bus_card_interface -{ -public: - // DIP switch handlers - virtual DECLARE_INPUT_CHANGED_MEMBER(sw_msb) { } - - // device_a2bus_card_interface implementation - 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; - virtual u8 read_c800(u16 offset) override; - -protected: - a2bus_grapplerplus_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock); - - // device_t implementation - virtual void device_add_mconfig(machine_config &config) override; - virtual ioport_constructor device_input_ports() const override; - virtual void device_start() override; - virtual void device_reset() override; - - // ACK latch set input - DECLARE_WRITE_LINE_MEMBER(ack_w); - - // signal state - u8 ack_latch() const { return m_ack_latch; } - u8 busy_in() const { return m_busy_in; } - u8 pe_in() const { return m_pe_in; } - u8 slct_in() const { return m_slct_in; } - - required_device m_printer_conn; - required_device m_printer_out; - required_ioport m_s1; - -private: - // printer status inputs - DECLARE_WRITE_LINE_MEMBER(busy_w); - DECLARE_WRITE_LINE_MEMBER(pe_w); - DECLARE_WRITE_LINE_MEMBER(slct_w); - - // synchronised printer status inputs - void set_ack_in(void *ptr, s32 param); - void set_busy_in(void *ptr, s32 param); - void set_pe_in(void *ptr, s32 param); - void set_slct_in(void *ptr, s32 param); - - // for derived devices to implement - virtual void data_latched(u8 data) = 0; - virtual void ack_latch_set() { } - virtual void ack_latch_cleared() { } - - required_region_ptr m_rom; - - u16 m_rom_bank; // U2D (pin 13) - u8 m_ack_latch; // U2C (pin 9) - u8 m_ack_in; // printer connector pin 19 (synchronised) - u8 m_busy_in; // printer connector pin 21 (synchronised) - u8 m_pe_in; // printer connector pin 23 (synchronised) - u8 m_slct_in; // printer connector pin 25 (synchronised) -}; - - -class a2bus_grapplerplus_device : public a2bus_grapplerplus_device_base -{ -public: - a2bus_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); - - // DIP switch handlers - virtual DECLARE_INPUT_CHANGED_MEMBER(sw_msb) override; - - // device_a2bus_card_interface implementation - virtual u8 read_c0nx(u8 offset) override; - virtual void write_c0nx(u8 offset, u8 data) override; - -protected: - // device_t implementation - virtual tiny_rom_entry const *device_rom_region() const override; - virtual void device_add_mconfig(machine_config &config) override; - virtual void device_start() override; - virtual void device_reset() override; - -private: - // a2bus_grapplerplus_device_base implementation - virtual void data_latched(u8 data) override; - virtual void ack_latch_set() override; - virtual void ack_latch_cleared() override; - - // timer handlers - TIMER_CALLBACK_MEMBER(update_strobe); - - emu_timer * m_strobe_timer; - - u8 m_data_latch; // U10 - u8 m_irq_disable; // U2A (pin 4) - u8 m_irq; // U3D (pin 13) - u8 m_next_strobe; // U5A (pin 5) -}; - - -class a2bus_buf_grapplerplus_device : public a2bus_grapplerplus_device_base -{ -public: - a2bus_buf_grapplerplus_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); - - // device_a2bus_card_interface implementation - virtual u8 read_c0nx(u8 offset) override; - -protected: - a2bus_buf_grapplerplus_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock); - - // device_t implementation - virtual tiny_rom_entry const *device_rom_region() const override; - virtual void device_add_mconfig(machine_config &config) override; - virtual ioport_constructor device_input_ports() const override; - virtual void device_start() override; - virtual void device_reset() override; - - // helpers - template void device_add_mconfig(machine_config &config, T &&mcu_clock); - -private: - // a2bus_grapplerplus_device_base implementation - virtual void data_latched(u8 data) override; - - // printer status inputs - DECLARE_WRITE_LINE_MEMBER(buf_ack_w); - - // MCU I/O handlers - void mcu_io(address_map &map); - void mcu_p2_w(u8 data); - u8 mcu_bus_r(); - void mcu_bus_w(u8 data); - - // synchronised signals - void set_buf_data(void *ptr, s32 param); - void set_buf_ack_in(void *ptr, s32 param); - void clear_ibusy(void *ptr, s32 param); - - required_device m_mcu; - std::unique_ptr m_ram; - - u16 m_ram_row; // U1-U8 - u8 m_ram_mask; // mask out chips that are not installed - u8 m_mcu_p2; // U10 - u8 m_data_latch; // U14 (synchronised) - u8 m_ibusy; // U12 - u8 m_buf_ack_latch; // U12 - u8 m_buf_ack_in; // printer connector pin 19 (synchronised) -}; - - -class a2bus_buf_grapplerplus_reva_device : public a2bus_buf_grapplerplus_device -{ -public: - a2bus_buf_grapplerplus_reva_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); - -protected: - // device_t implementation - virtual void device_add_mconfig(machine_config &config) override; -}; - - -DECLARE_DEVICE_TYPE(A2BUS_GRAPPLERPLUS, a2bus_grapplerplus_device) -DECLARE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUS, a2bus_buf_grapplerplus_device) -DECLARE_DEVICE_TYPE(A2BUS_BUFGRAPPLERPLUSA, a2bus_buf_grapplerplus_reva_device) - -#endif // MAME_BUS_A2BUS_GRAPPLERPLUS_H diff --git a/src/mame/drivers/apple2.cpp b/src/mame/drivers/apple2.cpp index ead0452a302..fe68a98e554 100644 --- a/src/mame/drivers/apple2.cpp +++ b/src/mame/drivers/apple2.cpp @@ -85,7 +85,7 @@ II Plus: RAM options reduced to 16/32/48 KB. #include "bus/a2bus/computereyes2.h" #include "bus/a2bus/ccs7710.h" #include "bus/a2bus/ezcgi.h" -#include "bus/a2bus/grapplerplus.h" +#include "bus/a2bus/grappler.h" #include "bus/a2bus/laser128.h" #include "bus/a2bus/mouse.h" #include "bus/a2bus/ramcard128k.h" @@ -1314,6 +1314,7 @@ static void apple2_cards(device_slot_interface &device) device.option_add("aevm80", A2BUS_AEVIEWMASTER80); /* Applied Engineering ViewMaster 80 */ device.option_add("parprn", A2BUS_PARPRN); /* Apple II Parallel Printer Interface Card */ device.option_add("parallel", A2BUS_PIC); /* Apple II Parallel Interface Card */ + device.option_add("grappler", A2BUS_GRAPPLER); /* Orange Micro Grappler Printer Interface card */ device.option_add("grapplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */ device.option_add("bufgrapplus", A2BUS_BUFGRAPPLERPLUS); /* Orange Micro Buffered Grappler+ Printer Interface card */ device.option_add("bufgrapplusa", A2BUS_BUFGRAPPLERPLUSA); /* Orange Micro Buffered Grappler+ (rev A) Printer Interface card */ diff --git a/src/mame/drivers/apple2e.cpp b/src/mame/drivers/apple2e.cpp index c3a81895bbd..3a8dfa7a8f4 100644 --- a/src/mame/drivers/apple2e.cpp +++ b/src/mame/drivers/apple2e.cpp @@ -173,7 +173,7 @@ MIG RAM page 2 $CE02 is the speaker/slot bitfield and $CE03 is the paddle/accele #include "bus/a2bus/computereyes2.h" #include "bus/a2bus/ccs7710.h" #include "bus/a2bus/ezcgi.h" -#include "bus/a2bus/grapplerplus.h" +#include "bus/a2bus/grappler.h" #include "bus/a2bus/laser128.h" #include "bus/a2bus/mouse.h" #include "bus/a2bus/pc_xporter.h" @@ -4665,6 +4665,7 @@ static void apple2_cards(device_slot_interface &device) device.option_add("aevm80", A2BUS_AEVIEWMASTER80); /* Applied Engineering ViewMaster 80 */ device.option_add("parprn", A2BUS_PARPRN); /* Apple II Parallel Printer Interface Card */ device.option_add("parallel", A2BUS_PIC); /* Apple II Parallel Interface Card */ + device.option_add("grappler", A2BUS_GRAPPLER); /* Orange Micro Grappler Printer Interface card */ device.option_add("grapplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */ device.option_add("bufgrapplus", A2BUS_BUFGRAPPLERPLUS); /* Orange Micro Buffered Grappler+ Printer Interface card */ device.option_add("bufgrapplusa", A2BUS_BUFGRAPPLERPLUSA); /* Orange Micro Buffered Grappler+ (rev A) Printer Interface card */ diff --git a/src/mame/drivers/apple2gs.cpp b/src/mame/drivers/apple2gs.cpp index ff81f3f6d78..46bf3640bad 100644 --- a/src/mame/drivers/apple2gs.cpp +++ b/src/mame/drivers/apple2gs.cpp @@ -113,7 +113,7 @@ #include "bus/a2bus/ccs7710.h" #include "bus/a2bus/cmsscsi.h" #include "bus/a2bus/ezcgi.h" -#include "bus/a2bus/grapplerplus.h" +#include "bus/a2bus/grappler.h" //#include "bus/a2bus/hostram.h" #include "bus/a2bus/laser128.h" #include "bus/a2bus/mouse.h" @@ -4763,6 +4763,7 @@ static void apple2_cards(device_slot_interface &device) device.option_add("aevm80", A2BUS_AEVIEWMASTER80); /* Applied Engineering ViewMaster 80 */ device.option_add("parprn", A2BUS_PARPRN); /* Apple II Parallel Printer Interface Card */ device.option_add("parallel", A2BUS_PIC); /* Apple Parallel Interface Card */ + device.option_add("grappler", A2BUS_GRAPPLER); /* Orange Micro Grappler Printer Interface card */ device.option_add("grapplus", A2BUS_GRAPPLERPLUS); /* Orange Micro Grappler+ Printer Interface card */ device.option_add("bufgrapplus", A2BUS_BUFGRAPPLERPLUS); /* Orange Micro Buffered Grappler+ Printer Interface card */ device.option_add("bufgrapplusa", A2BUS_BUFGRAPPLERPLUSA); /* Orange Micro Buffered Grappler+ (rev A) Printer Interface card */ -- cgit v1.2.3