diff options
21 files changed, 1961 insertions, 398 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index dabbbd82731..d87a995fdfc 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -5739,3 +5739,29 @@ if (BUSES["PLG1X0"]~=null) then MAME_DIR .. "src/devices/bus/plg1x0/plg150-ap.h", } end + +--------------------------------------------------- +-- +--@src/devices/bus/h89/h89bus.h,BUSES["H89BUS"] = true +--------------------------------------------------- + +if (BUSES["H89BUS"]~=null) then + files { + MAME_DIR .. "src/devices/bus/heathzenith/h89/cards.cpp", + MAME_DIR .. "src/devices/bus/heathzenith/h89/cards.h", + MAME_DIR .. "src/devices/bus/heathzenith/h89/h89bus.cpp", + MAME_DIR .. "src/devices/bus/heathzenith/h89/h89bus.h", + MAME_DIR .. "src/devices/bus/heathzenith/h89/h_88_3.cpp", + MAME_DIR .. "src/devices/bus/heathzenith/h89/h_88_3.h", + MAME_DIR .. "src/devices/bus/heathzenith/h89/h_88_5.cpp", + MAME_DIR .. "src/devices/bus/heathzenith/h89/h_88_5.h", + MAME_DIR .. "src/devices/bus/heathzenith/h89/mms77316_fdc.cpp", + MAME_DIR .. "src/devices/bus/heathzenith/h89/mms77316_fdc.h", + MAME_DIR .. "src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp", + MAME_DIR .. "src/devices/bus/heathzenith/h89/sigmasoft_sound.h", + MAME_DIR .. "src/devices/bus/heathzenith/h89/we_pullup.cpp", + MAME_DIR .. "src/devices/bus/heathzenith/h89/we_pullup.h", + MAME_DIR .. "src/devices/bus/heathzenith/h89/z37_fdc.cpp", + MAME_DIR .. "src/devices/bus/heathzenith/h89/z37_fdc.h", + } +end diff --git a/src/devices/bus/heathzenith/h89/cards.cpp b/src/devices/bus/heathzenith/h89/cards.cpp new file mode 100644 index 00000000000..22f379601b1 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/cards.cpp @@ -0,0 +1,44 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + H-89 and Z-90 slot cards + +***************************************************************************/ + +#include "emu.h" +#include "cards.h" + +#include "h_88_3.h" +#include "h_88_5.h" +#include "mms77316_fdc.h" +#include "sigmasoft_sound.h" +#include "we_pullup.h" +#include "z37_fdc.h" + +void h89_left_cards(device_slot_interface &device) +{ +} + +void h89_right_cards(device_slot_interface &device) +{ + device.option_add("h_88_3", H89BUS_H_88_3); + device.option_add("ha_88_3", H89BUS_HA_88_3); + device.option_add("h_88_5", H89BUS_H_88_5); + device.option_add("ss_snd", H89BUS_SIGMASOFT_SND); + device.option_add("z37fdc", H89BUS_Z37); +} + +void h89_right_cards_mms(device_slot_interface &device) +{ + h89_right_cards(device); + device.option_add("mms77316", H89BUS_MMS77316); +} + +void h89_right_p506_cards(device_slot_interface &device) +{ + device.option_add("h_88_3", H89BUS_H_88_3); + device.option_add("ha_88_3", H89BUS_HA_88_3); + device.option_add("ss_snd", H89BUS_SIGMASOFT_SND); + device.option_add("we_pullup", H89BUS_WE_PULLUP); +} diff --git a/src/devices/bus/heathzenith/h89/cards.h b/src/devices/bus/heathzenith/h89/cards.h new file mode 100644 index 00000000000..53899ccb2f9 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/cards.h @@ -0,0 +1,19 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + Heath/Zenith H-89 and Z-90 cards + +***************************************************************************/ + +#ifndef MAME_BUS_HEATHZENITH_H89_CARDS_H +#define MAME_BUS_HEATHZENITH_H89_CARDS_H + +#pragma once + +void h89_left_cards(device_slot_interface &device) ATTR_COLD; +void h89_right_cards(device_slot_interface &device) ATTR_COLD; +void h89_right_cards_mms(device_slot_interface &device) ATTR_COLD; +void h89_right_p506_cards(device_slot_interface &device) ATTR_COLD; + +#endif // MAME_BUS_HEATHZENITH_H89_CARDS_H diff --git a/src/devices/bus/heathzenith/h89/h89bus.cpp b/src/devices/bus/heathzenith/h89/h89bus.cpp new file mode 100644 index 00000000000..5d1382d98cd --- /dev/null +++ b/src/devices/bus/heathzenith/h89/h89bus.cpp @@ -0,0 +1,406 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + h89bus.cpp - Heath/Zenith H-89/Z-90 bus + + by R. Belmont + + This system is weird. There are 3 left-hand slots. These are intended + for RAM expansion and map into the Z80's memory space. They get A0-A12 + and some select signals decoded by a pair of PROMs at U516 and U517. + Notably, these slots don't get the Z80's /RD or /WR signals so actual + working boards for these slots always run a cable or jumper(s) to pick + signals from the motherboard. These slots also have no way to signal + an interrupt. + + There are also 3 right-hand slots. These connect to the Z80's I/O address + space and are addressed by a 3-bit offset A0/A1/A2 plus select lines /SER0, + /SER1, /LP1 and /CASS (on P504/P510 and P505/P511), or /FLPY (on P506/P512). + P506/P512 replaces the /LP1 select line with the /FMWE signal which write-enables + the "floppy RAM" at 0x1400. These slots have 3 standard interrupt outputs + /INT3, /INT4, and /INT5. + + Notable real-world use cases that we support: + - The Sigmasoft parallel card plugs into a left slot but picks the I/O space + select signal off the motherboard. This plus the left slots' nearly full + set of address lines let it decode the I/O space arbitrarily without + having to change the I/O decoder PROM. + + - The MMS 77316 floppy controller has jumpers to replace U553 so that it can + intercept the GPP select line output by the PROM and further decode it. + This decode appears to check if A0/A1/A2 = b010. The partial schematic for + the card doesn't include that logic, but based on what signals it has access + to and the fact that the card doesn't respond to A0/A1/A2 = b010 that seems + to be a reasonable guess. + +***************************************************************************/ + +#include "emu.h" +#include "h89bus.h" + +#include <algorithm> +#include <cctype> + +DEFINE_DEVICE_TYPE(H89BUS_LEFT_SLOT, h89bus_left_slot_device, "h89bus_lslot", "H-89 left (memory) slot") + +h89bus_left_slot_device::h89bus_left_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + h89bus_left_slot_device(mconfig, H89BUS_LEFT_SLOT, tag, owner, clock) +{ +} + +h89bus_left_slot_device::h89bus_left_slot_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_single_card_slot_interface(mconfig, *this), + m_h89bus(*this, finder_base::DUMMY_TAG), + m_h89bus_slottag(nullptr) +{ +} + +void h89bus_left_slot_device::device_start() +{ +} + +void h89bus_left_slot_device::device_resolve_objects() +{ + device_h89bus_left_card_interface *dev = get_card_device(); + + if (dev) + { + dev->set_h89bus_tag(m_h89bus.target(), m_h89bus_slottag); + m_h89bus->add_h89bus_left_card(*dev); + } +} + +DEFINE_DEVICE_TYPE(H89BUS_RIGHT_SLOT, h89bus_right_slot_device, "h89bus_rslot", "H-89 right (I/O) slot") + +h89bus_right_slot_device::h89bus_right_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + h89bus_right_slot_device(mconfig, H89BUS_RIGHT_SLOT, tag, owner, clock) +{ +} + +h89bus_right_slot_device::h89bus_right_slot_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_single_card_slot_interface(mconfig, *this), + m_h89bus(*this, finder_base::DUMMY_TAG), + m_h89bus_slottag(nullptr), + m_p506_signals(false) +{ +} + +void h89bus_right_slot_device::device_start() +{ +} + +void h89bus_right_slot_device::device_resolve_objects() +{ + device_h89bus_right_card_interface *dev = get_card_device(); + + if (dev) + { + dev->set_h89bus_tag(m_h89bus.target(), m_h89bus_slottag); + dev->set_p506_signalling(m_p506_signals); + m_h89bus->add_h89bus_right_card(*dev); + } +} + +//************************************************************************** +// GLOBAL VARIABLES +//************************************************************************** + +DEFINE_DEVICE_TYPE(H89BUS, h89bus_device, "h89bus", "H-89/Z-90 bus") + +ROM_START(h89bus) + ROM_REGION(0x100, "iodecode", 0) + // H88 I/O decoding + ROM_SYSTEM_BIOS(0, "444-43", "Heath/Zenith stock decoding (444-43)") + ROMX_LOAD("444-43.bin", 0x000000, 0x000100, CRC(3e0315f4) SHA1(11da9a9145de07f1f3bf1270a10e059dff30c693), ROM_BIOS(0)) + + // H89 I/O decoding + ROM_SYSTEM_BIOS(1, "444-61", "Z-37 decoding (444-61)") + ROMX_LOAD("444-61.bin", 0x000000, 0x000100, CRC(0b3c129f) SHA1(92da6484d1339160400d6bc75578a977c5e4d23e), ROM_BIOS(1)) + + // MMS (Magnolia Micro Systems) I/O decoding + ROM_SYSTEM_BIOS(2, "444-61c", "MMS decoding (444-61c)") + ROMX_LOAD( "444-61c.bin", 0x000000, 0x000100, CRC(e7122061) SHA1(33c124f44c0f9cb99c9b17ad15411b4bc6407eae), ROM_BIOS(2)) +ROM_END + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// h89bus_device - constructor +//------------------------------------------------- + +h89bus_device::h89bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + h89bus_device(mconfig, H89BUS, tag, owner, clock) +{ +} + +h89bus_device::h89bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + m_program_space(*this, finder_base::DUMMY_TAG, -1), + m_io_space(*this, finder_base::DUMMY_TAG, -1), + m_decode_prom(*this, "iodecode"), + m_out_int3_cb(*this), + m_out_int4_cb(*this), + m_out_int5_cb(*this), + m_out_fdcirq_cb(*this), + m_out_fdcdrq_cb(*this), + m_out_blockirq_cb(*this), + m_out_fmwe_cb(*this), + m_out_wait_cb(*this), + m_in_tlb_cb(*this, 0), + m_in_nmi_cb(*this, 0), + m_in_gpp_cb(*this, 0), + m_out_tlb_cb(*this), + m_out_nmi_cb(*this), + m_out_gpp_cb(*this) +{ +} + +h89bus_device::~h89bus_device() +{ +} + +const tiny_rom_entry *h89bus_device::device_rom_region() const +{ + return ROM_NAME(h89bus); +} + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void h89bus_device::device_start() +{ + // don't claim I/O below 0x10 for now + m_io_space->install_readwrite_handler(0x0010, 0x00ff, emu::rw_delegate(*this, FUNC(h89bus_device::io_dispatch_r)), emu::rw_delegate(*this, FUNC(h89bus_device::io_dispatch_w))); +} + +void h89bus_device::add_h89bus_left_card(device_h89bus_left_card_interface &card) +{ + m_left_device_list.emplace_back(card); +} + +void h89bus_device::add_h89bus_right_card(device_h89bus_right_card_interface &card) +{ + m_right_device_list.emplace_back(card); +} + +void h89bus_device::set_io0(int state) +{ + m_io0 = state; +} + +void h89bus_device::set_io1(int state) +{ + m_io1 = state; +} + +void h89bus_device::set_mem0(int state) +{ + m_mem0 = state; +} + +void h89bus_device::set_mem1(int state) +{ + m_mem1 = state; +} + +int h89bus_device::get_io0() +{ + return m_io0; +} + +int h89bus_device::get_io1() +{ + return m_io1; +} + +int h89bus_device::get_mem0() +{ + return m_mem0; +} + +int h89bus_device::get_mem1() +{ + return m_mem1; +} + +u8 h89bus_device::read_gpp() +{ + return m_in_gpp_cb(0); +} +void h89bus_device::write_gpp(u8 data) +{ + m_out_gpp_cb(0, data); +} + +u8 h89bus_device::io_dispatch_r(offs_t offset) +{ + u8 retval = 0; + + offset += 0x10; + if (m_decode_prom[offset] != 0xff) + { + u16 decode = m_decode_prom[offset] ^ 0xff; + + if ((decode & H89_GPP) && ((offset & 7) == 2)) return m_in_gpp_cb(offset); + if (decode & H89_NMI) return m_in_nmi_cb(offset); + if (decode & H89_TERM) return m_in_tlb_cb(offset & 7); + + if (decode) + { + for (device_h89bus_right_card_interface &entry : m_right_device_list) + { + if (entry.m_p506_signals) + { + // p506 has FLPY but not CASS or LP + retval |= entry.read(decode & ~(H89_CASS | H89_LP), offset & 7); + } + else + { + // p504/p505 have CASS and LP but not FLPY + retval |= entry.read(decode & ~H89_FLPY , offset & 7); + } + } + } + + // service left-slot cards that have a motherboard connection to snoop the I/O space + for (device_h89bus_left_card_interface &entry : m_left_device_list) + { + retval |= entry.read(H89_IO, offset); + } + } + + return retval; +} + +void h89bus_device::io_dispatch_w(offs_t offset, u8 data) +{ + offset += 0x10; + if (m_decode_prom[offset] != 0xff) + { + u16 decode = m_decode_prom[offset] ^ 0xff; + + if (decode & H89_GPP) m_out_gpp_cb(offset, data); + if (decode & H89_NMI) { m_out_nmi_cb(offset, data); return; } + if (decode & H89_TERM) { m_out_tlb_cb(offset & 7, data); return; } + + if (decode) + { + for (device_h89bus_right_card_interface &entry : m_right_device_list) + { + if (entry.m_p506_signals) + { + // p506 has FLPY but not CASS or LP1 + entry.write(decode & ~H89_CASS, offset & 7, data); + } + else + { + // p504/p505 have LP1 and CASS but not FLPY + entry.write(decode & ~H89_FLPY, offset & 7, data); + } + } + } + + // service left-slot cards that have a motherboard connection to snoop the I/O space + for (device_h89bus_left_card_interface &entry : m_left_device_list) + { + entry.write(H89_IO, offset, data); + } + } +} + +void h89bus_device::set_int3_line(int state) +{ + m_out_int3_cb(state); +} + +void h89bus_device::set_int4_line(int state) +{ + m_out_int4_cb(state); +} + +void h89bus_device::set_int5_line(int state) +{ + m_out_int5_cb(state); +} + +void h89bus_device::set_fdcirq_line(int state) +{ + m_out_fdcirq_cb(state); +} + +void h89bus_device::set_fdcdrq_line(int state) +{ + m_out_fdcdrq_cb(state); +} + +void h89bus_device::set_blockirq_line(int state) +{ + m_out_blockirq_cb(state); +} + +void h89bus_device::set_fmwe_line(int state) +{ + m_out_fmwe_cb(state); +} + +void h89bus_device::set_wait_line(int state) +{ + m_out_wait_cb(state); +} + +//************************************************************************** +// DEVICE H89BUS CARD INTERFACE +//************************************************************************** + +//------------------------------------------------- +// device_h89bus_card_interface - constructor +//------------------------------------------------- + +device_h89bus_card_interface::device_h89bus_card_interface(const machine_config &mconfig, device_t &device) : + device_interface(device, "h89bus"), + m_h89bus(nullptr) +{ +} + + +//------------------------------------------------- +// ~device_h89bus_card_interface - destructor +//------------------------------------------------- + +device_h89bus_card_interface::~device_h89bus_card_interface() +{ +} + +void device_h89bus_card_interface::interface_pre_start() +{ + if (!m_h89bus) + { + fatalerror("Can't find H-89 bus device\n"); + } +} + +device_h89bus_left_card_interface::device_h89bus_left_card_interface(const machine_config &mconfig, device_t &device) : + device_h89bus_card_interface(mconfig, device) +{ +} + +device_h89bus_left_card_interface::~device_h89bus_left_card_interface() +{ +} + +device_h89bus_right_card_interface::device_h89bus_right_card_interface(const machine_config &mconfig, device_t &device) : + device_h89bus_card_interface(mconfig, device), + m_p506_signals(false) +{ +} + +device_h89bus_right_card_interface::~device_h89bus_right_card_interface() +{ +} + diff --git a/src/devices/bus/heathzenith/h89/h89bus.h b/src/devices/bus/heathzenith/h89/h89bus.h new file mode 100644 index 00000000000..8befec480bb --- /dev/null +++ b/src/devices/bus/heathzenith/h89/h89bus.h @@ -0,0 +1,424 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + h89.h - Heath/Zenith H-89/Z-90 bus + by R. Belmont + + Left-side slots of the H89 Right-side slots of the H89 + + pin P501 P502 P503 P504 P505 P506 pin + + 1 GND----------GND----------GND-------------GND----------GND----------GND 1 + 2 D0-----------D0-----------D0--------------D0-----------D0-----------D0 2 + 3 D1-----------D1-----------D1--------------D1-----------D1-----------D1 3 + 4 D2-----------D2-----------D2--------------D2-----------D2-----------D2 4 + 5 D3-----------D3-----------D3--------------D3-----------D3-----------D3 5 + 6 D4-----------D4-----------D4--------------D4-----------D4-----------D4 6 + 7 D5-----------D5-----------D5--------------D5-----------D5-----------D5 7 + 8 D6-----------D6-----------D6--------------D6-----------D6-----------D6 8 + 9 D7-----------D7-----------D7--------------D7-----------D7-----------D7 9 + 10 GND----------GND----------GND-------------GND----------GND----------GND 10 + + P507 P508 P509 P510 P511 P512 + + 1 VCC----------VCC----------VCC-------------VCC----------VCC----------VCC 1 + 2 GND----------GND----------GND-------------GND----------GND----------GND 2 + 3 A0-----------A0-----------A0--------------A0-----------A0-----------A0 3 + 4 A1-----------A1-----------A1--------------A1-----------A1-----------A1 4 + 5 A2-----------A2-----------A2--------------A2-----------A2-----------A2 5 + 6 A3-----------A3-----------A3 /BRD---------/BRD---------/BRD 6 + 7 A4-----------A4-----------A4 /BWR---------/BWR---------/BWR 7 + 8 A5-----------A5-----------A5 /WAIT--------/WAIT--------/WAIT 8 + 9 A6-----------A6-----------A6 /SER0--------/SER0--------/SER0 9 + 10 A7-----------A7-----------A7 /SER1--------/SER1--------/SER1 10 + 11 A8-----------A8-----------A8 /LP1---------/LP1 /FLPY 11 + 12 A9-----------A9-----------A9 /CASS--------/CASS /FMWE 12 + 13 A10----------A10----------A10 2MHz---------2MHz---------2MHz 13 + 14 A11----------A11----------A11 1.8Mhz-------1.8MHz-------1.8MHz 14 + 15 A12----------A12----------A12 /RST---------/RST---------/RST 15 + 16 MEM 0--------MEM 0--------MEM 0 IO 0---------IO 0---------IO 0 16 + 17 MEM 1--------MEM 1--------MEM 1 IO 1---------IO 1---------IO 1 17 + 18 RD5----------RD5----------RD5 /INT3--------/INT3--------/INT3 18 + 19 RD6----------RD6----------RD6 /INT4--------/INT4--------/INT4 19 + 20 RD7----------RD7----------RD7 /INT5--------/INT5--------/INT5 20 + 21 (+12V)-------(+12V)-------(+12V)-----------(+12V)-------(+12V)-------(+12V) 21 + 22 (-12V)-------(-12V)-------(-12V)-----------(-12V)-------(-12V)-------(-12V) 22 + 23 (-5V)--------(-5V)--------(-5V)------------(-5V)--------(-5V)--------(-5V) 23 + 24 (+12V)-------(+12V)-------(+12V)-----------(+12V)-------(+12V)-------(+12V) 24 + 25 GND----------GND----------GND--------------GND----------GND----------GND 25 + + + Signal Description + ------------------------------------------ + MEM 0 H Controlled by the GPP port + MEM 1 H Controlled by the GPP port + RD5 Tied to +5V when CPU jumpers configured as recommended by Heath's configuration + guide. Could be jumpered to RAS2 (bank select 2: address 32k-48k) (active low) + RD6 Selects the 16k Expansion memory (active low) + RD7 Reserved for future use, 444-66 PROM nevers sets this low. (active low) + BRD L Board Read (active low) + BWR L Board Write (active low) + WAIT L Wait state (active low) + SER0 L Select line for one of the serial ports on the HA-88-3 (active low) + SER1 L Select line for one of the serial ports on the HA-88-3 (active low) + LP 1 L Select line for one of the serial ports on the HA-88-3 (active low) + CASS L Select line originally for the Cassette Interface board, but when used with later PROM it + selected Floppy controllers/interfaces – Z-89-37, Z-89-47, Z-89-67 (active low) + 2 MHz CPU Clock, actual speed 2.048 MHz + 1.8 MHz Serial Port Clock, actual speed 1.8432 MHz + RST L Reset line (active low) + IO 0 H Controlled by the GPP port + IO 1 H Controlled by the GPP port + INT3 L Interrupt level 3 (active low) + INT4 L Interrupt level 4 (active low) + INT5 L Interrupt level 5 (active low) + FLPY L Select line originally for the H-88-1 hard-sectored controller, but also used for the later + Z-89-47 and Z-89-67 when installed in slot P506/P512 (active low) + FMWE H Floppy Memory Write Enable + +***************************************************************************/ + +#ifndef MAME_BUS_HEATHZENITH_H89_H89BUS_H +#define MAME_BUS_HEATHZENITH_H89_H89BUS_H + +#pragma once +#include "emu.h" +#include <functional> +#include <utility> +#include <vector> +#include <string.h> + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class h89bus_device; + +// ======================> device_h89bus_card_interface + +// class representing interface-specific live H-89/Z-89 bus card +class device_h89bus_card_interface : public device_interface +{ + friend class h89bus_device; +public: + // construction/destruction + virtual ~device_h89bus_card_interface(); + + // inline configuration + void set_h89bus_tag(h89bus_device *h89bus, const char *slottag) { m_h89bus = h89bus; m_h89bus_slottag = slottag; } + +protected: + device_h89bus_card_interface(const machine_config &mconfig, device_t &device); + virtual void interface_pre_start() override; + + h89bus_device &h89bus() { assert(m_h89bus); return *m_h89bus; } + + const char *m_h89bus_slottag; + +private: + h89bus_device *m_h89bus; +}; + +class device_h89bus_left_card_interface : public device_h89bus_card_interface +{ +public: + // construction/destruction + virtual ~device_h89bus_left_card_interface(); + + int get_mem0(); + int get_mem1(); + + virtual u8 read(u8 select_lines, u16 offset) { return 0; }; + virtual void write(u8 select_lines, u16 offset, u8 data) {}; + +protected: + device_h89bus_left_card_interface(const machine_config &mconfig, device_t &device); + +private: +}; + +class device_h89bus_right_card_interface : public device_h89bus_card_interface +{ + friend class h89bus_device; + +public: + // construction/destruction + virtual ~device_h89bus_right_card_interface(); + + void set_slot_int3(int state); + void set_slot_int4(int state); + void set_slot_int5(int state); + void set_slot_fdcirq(int state); + void set_slot_fdcdrq(int state); + void set_slot_blockirq(int state); + void set_slot_fmwe(int state); + void set_slot_wait(int state); + int get_io0(); + int get_io1(); + + virtual u8 read(u8 select_lines, u8 offset) { return 0; }; + virtual void write(u8 select_lines, u8 offset, u8 data) {}; + + void set_p506_signalling(bool val) + { + m_p506_signals = val; + } + +protected: + device_h89bus_right_card_interface(const machine_config &mconfig, device_t &device); + bool m_p506_signals; + +private: +}; + +class h89bus_left_slot_device : public device_t, public device_single_card_slot_interface<device_h89bus_left_card_interface> +{ +public: + // construction/destruction + template <typename T, typename U> + h89bus_left_slot_device(const machine_config &mconfig, T &&tag, device_t *owner, const char *sltag, U &&opts, const char *dflt) + : h89bus_left_slot_device(mconfig, tag, owner, (uint32_t)0) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_h89bus_slot(std::forward<T>(sltag), tag); + } + + h89bus_left_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // inline configuration + template <typename T> + void set_h89bus_slot(T &&tag, const char *slottag) + { + m_h89bus.set_tag(std::forward<T>(tag)); + m_h89bus_slottag = slottag; + } + +protected: + h89bus_left_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device_t implementation + virtual void device_resolve_objects() override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + + // configuration + required_device<h89bus_device> m_h89bus; + const char *m_h89bus_slottag; +}; + +// device type definition +DECLARE_DEVICE_TYPE(H89BUS_LEFT_SLOT, h89bus_left_slot_device) + +class h89bus_right_slot_device : public device_t, public device_single_card_slot_interface<device_h89bus_right_card_interface> +{ +public: + // construction/destruction + template <typename T, typename U> + h89bus_right_slot_device(const machine_config &mconfig, T &&tag, device_t *owner, const char *sltag, U &&opts, const char *dflt) + : h89bus_right_slot_device(mconfig, tag, owner, (uint32_t)0) + { + option_reset(); + opts(*this); + set_default_option(dflt); + set_h89bus_slot(std::forward<T>(sltag), tag); + } + + h89bus_right_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // inline configuration + template <typename T> + void set_h89bus_slot(T &&tag, const char *slottag) + { + m_h89bus.set_tag(std::forward<T>(tag)); + m_h89bus_slottag = slottag; + } + + void set_p506_signalling(bool val) + { + m_p506_signals = val; + } + +protected: + h89bus_right_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device_t implementation + virtual void device_resolve_objects() override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + + // configuration + required_device<h89bus_device> m_h89bus; + const char *m_h89bus_slottag; + bool m_p506_signals; +}; + +// device type definition +DECLARE_DEVICE_TYPE(H89BUS_RIGHT_SLOT, h89bus_right_slot_device) + +// ======================> h89bus_device +class h89bus_device : public device_t +{ + friend class h89bus_left_slot_device; + friend class h89bus_right_slot_device; + friend class device_h89bus_left_card_interface; + friend class device_h89bus_right_card_interface; + +public: + // left card select lines + static constexpr u8 H89_RD5 = 0x01; + static constexpr u8 H89_RD6 = 0x02; + static constexpr u8 H89_RD7 = 0x04; + // The Sigmasoft parallel card plugs into the left slot and has a jumper to + // get the memory / I/O select signal from the motherboard. This plus the left + // slots' A0-A13 lines means it can claim arbitrary I/O ranges that the PROM doesn't + // select anything at. + static constexpr u8 H89_IO = 0x80; + + // right card and on-board I/O space select lines + static constexpr u8 H89_GPP = 0x01; + static constexpr u8 H89_NMI = 0x02; + static constexpr u8 H89_TERM = 0x04; + static constexpr u8 H89_SER1 = 0x08; + static constexpr u8 H89_SER0 = 0x10; + static constexpr u8 H89_LP = 0x20; + static constexpr u8 H89_CASS = 0x40; + static constexpr u8 H89_FLPY = 0x80; + + // construction/destruction + h89bus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + ~h89bus_device(); + + void set_io0(int state); + void set_io1(int state); + void set_mem0(int state); + void set_mem1(int state); + int get_io0(); + int get_io1(); + int get_mem0(); + int get_mem1(); + + // inline configuration + template <typename T> void set_program_space(T &&tag, int spacenum) { m_program_space.set_tag(std::forward<T>(tag), spacenum); } + template <typename T> void set_io_space(T &&tag, int spacenum) { m_io_space.set_tag(std::forward<T>(tag), spacenum); } + auto out_int3_callback() { return m_out_int3_cb.bind(); } + auto out_int4_callback() { return m_out_int4_cb.bind(); } + auto out_int5_callback() { return m_out_int5_cb.bind(); } + auto out_fdcirq_callback() { return m_out_fdcirq_cb.bind(); } + auto out_fdcdrq_callback() { return m_out_fdcdrq_cb.bind(); } + auto out_blockirq_callback() { return m_out_blockirq_cb.bind(); } + auto out_fmwe_callback() { return m_out_fmwe_cb.bind(); } + auto out_wait_callback() { return m_out_wait_cb.bind(); } + auto in_tlb_callback() { return m_in_tlb_cb.bind(); } + auto in_nmi_callback() { return m_in_nmi_cb.bind(); } + auto in_gpp_callback() { return m_in_gpp_cb.bind(); } + auto out_tlb_callback() { return m_out_tlb_cb.bind(); } + auto out_nmi_callback() { return m_out_nmi_cb.bind(); } + auto out_gpp_callback() { return m_out_gpp_cb.bind(); } + +protected: + h89bus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device_t implementation + virtual void device_start() override ATTR_COLD; + virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD; + + // bus-internal handlers + void add_h89bus_left_card(device_h89bus_left_card_interface &card); + void add_h89bus_right_card(device_h89bus_right_card_interface &card); + void set_int3_line(int state); + void set_int4_line(int state); + void set_int5_line(int state); + void set_fdcirq_line(int state); + void set_fdcdrq_line(int state); + void set_blockirq_line(int state); + void set_fmwe_line(int state); + void set_wait_line(int state); + u8 read_gpp(); + void write_gpp(u8 data); + + // internal state + required_address_space m_program_space, m_io_space; + required_region_ptr<uint8_t> m_decode_prom; + int m_io0, m_io1, m_mem0, m_mem1; + +private: + devcb_write_line m_out_int3_cb, m_out_int4_cb, m_out_int5_cb, m_out_fdcirq_cb, m_out_fdcdrq_cb, m_out_blockirq_cb; + devcb_write_line m_out_fmwe_cb, m_out_wait_cb; + devcb_read8 m_in_tlb_cb, m_in_nmi_cb, m_in_gpp_cb; + devcb_write8 m_out_tlb_cb, m_out_nmi_cb, m_out_gpp_cb; + + std::vector<std::reference_wrapper<device_h89bus_left_card_interface>> m_left_device_list; + std::vector<std::reference_wrapper<device_h89bus_right_card_interface>> m_right_device_list; + + u8 io_dispatch_r(offs_t offset); + void io_dispatch_w(offs_t offset, u8 data); +}; + +inline int device_h89bus_left_card_interface::get_mem0() +{ + return h89bus().get_mem0(); +} + +inline int device_h89bus_left_card_interface::get_mem1() +{ + return h89bus().get_mem1(); +} + +inline int device_h89bus_right_card_interface::get_io0() +{ + return h89bus().get_io0(); +} + +inline int device_h89bus_right_card_interface::get_io1() +{ + return h89bus().get_io1(); +} + +inline void device_h89bus_right_card_interface::set_slot_int3(int state) +{ + h89bus().set_int3_line(state); +} + +inline void device_h89bus_right_card_interface::set_slot_int4(int state) +{ + h89bus().set_int4_line(state); +} + +inline void device_h89bus_right_card_interface::set_slot_int5(int state) +{ + h89bus().set_int5_line(state); +} + +inline void device_h89bus_right_card_interface::set_slot_fdcirq(int state) +{ + h89bus().set_fdcirq_line(state); +} + +inline void device_h89bus_right_card_interface::set_slot_fdcdrq(int state) +{ + h89bus().set_fdcdrq_line(state); +} + +inline void device_h89bus_right_card_interface::set_slot_blockirq(int state) +{ + h89bus().set_blockirq_line(state); +} + +inline void device_h89bus_right_card_interface::set_slot_fmwe(int state) +{ + if (m_p506_signals) + { + h89bus().set_fmwe_line(state); + } +} + +inline void device_h89bus_right_card_interface::set_slot_wait(int state) +{ + h89bus().set_wait_line(state); +} + +// device type definition +DECLARE_DEVICE_TYPE(H89BUS, h89bus_device) + +#endif // MAME_BUS_HEATHZENITH_H89_H89BUS_H diff --git a/src/devices/bus/heathzenith/h89/h_88_3.cpp b/src/devices/bus/heathzenith/h89/h_88_3.cpp new file mode 100644 index 00000000000..95c73115d51 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/h_88_3.cpp @@ -0,0 +1,323 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger, R. Belmont +/*************************************************************************** + + Heath H-88-3 3-port serial port card + Came with 2 serial ports and space to add an additional serial port. + + Heath HA-88-3 3-port serial port card + Came standard with 3 serial ports. + +****************************************************************************/ + +#include "emu.h" + +#include "h_88_3.h" + +#include "bus/rs232/rs232.h" +#include "machine/ins8250.h" + +namespace { + +class h_88_3_device : public device_t, public device_h89bus_right_card_interface +{ +public: + h_88_3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = XTAL(1'843'200).value()); + + virtual void write(u8 select_lines, u8 offset, u8 data) override; + virtual u8 read(u8 select_lines, u8 offset) override; + +protected: + h_88_3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); + + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual ioport_constructor device_input_ports() const override ATTR_COLD; + + devcb_write_line::array<4> m_int_cb; + + required_device<ins8250_device> m_lp; + required_device<ins8250_device> m_aux; + required_device<ins8250_device> m_modem; + required_ioport m_cfg_lp; + required_ioport m_cfg_aux; + required_ioport m_cfg_modem; + + bool m_lp_enabled; + bool m_aux_enabled; + bool m_modem_enabled; + + u8 m_lp_int_idx; + u8 m_aux_int_idx; + u8 m_modem_int_idx; +private: + void lp_w(offs_t reg, u8 val); + u8 lp_r(offs_t reg); + + void aux_w(offs_t reg, u8 val); + u8 aux_r(offs_t reg); + + void modem_w(offs_t reg, u8 val); + u8 modem_r(offs_t reg); + + void lp_int(int data); + void aux_int(int data); + void modem_int(int data); +}; + +class ha_88_3_device : public h_88_3_device +{ +public: + ha_88_3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = XTAL(1'843'200).value()); + +protected: + virtual ioport_constructor device_input_ports() const override; +}; + +h_88_3_device::h_88_3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + h_88_3_device(mconfig, H89BUS_H_88_3, tag, owner, clock) +{ +} + +h_88_3_device::h_88_3_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, type, tag, owner, clock), + device_h89bus_right_card_interface(mconfig, *this), + m_int_cb(*this), + m_lp(*this, "lp"), + m_aux(*this, "aux"), + m_modem(*this, "modem"), + m_cfg_lp(*this, "CFG_LP"), + m_cfg_aux(*this, "CFG_AUX"), + m_cfg_modem(*this, "CFG_MODEM") +{ +} + +u8 h_88_3_device::read(u8 select_lines, u8 offset) +{ + if ((select_lines & h89bus_device::H89_SER0) && (m_aux_enabled)) + { + return aux_r(offset); + } + + if ((select_lines & h89bus_device::H89_SER1) && (m_modem_enabled)) + { + return modem_r(offset); + } + + if ((select_lines & h89bus_device::H89_LP) && (m_lp_enabled)) + { + return lp_r(offset); + } + + return 0; +} + +void h_88_3_device::write(u8 select_lines, u8 offset, u8 data) +{ + if ((select_lines & h89bus_device::H89_SER0) && (m_aux_enabled)) + { + aux_w(offset, data); + return; + } + + if ((select_lines & h89bus_device::H89_SER1) && (m_modem_enabled)) + { + modem_w(offset, data); + return; + } + + if ((select_lines & h89bus_device::H89_LP) && (m_lp_enabled)) + { + lp_w(offset, data); + return; + } +} + +u8 h_88_3_device::lp_r(offs_t reg) +{ + return m_lp->ins8250_r(reg); +} + +void h_88_3_device::lp_w(offs_t reg, u8 val) +{ + m_lp->ins8250_w(reg, val); +} + +u8 h_88_3_device::aux_r(offs_t reg) +{ + return m_aux->ins8250_r(reg); +} + +void h_88_3_device::aux_w(offs_t reg, u8 val) +{ + m_aux->ins8250_w(reg, val); +} + +u8 h_88_3_device::modem_r(offs_t reg) +{ + return m_modem->ins8250_r(reg); +} + +void h_88_3_device::modem_w(offs_t reg, u8 val) +{ + m_modem->ins8250_w(reg, val); +} + +void h_88_3_device::device_start() +{ + save_item(NAME(m_lp_enabled)); + save_item(NAME(m_lp_int_idx)); + save_item(NAME(m_aux_enabled)); + save_item(NAME(m_aux_int_idx)); + save_item(NAME(m_modem_enabled)); + save_item(NAME(m_modem_int_idx)); +} + +void h_88_3_device::device_reset() +{ + ioport_value const cfg_lp(m_cfg_lp->read()); + ioport_value const cfg_aux(m_cfg_aux->read()); + ioport_value const cfg_modem(m_cfg_modem->read()); + + m_lp_enabled = bool(BIT(cfg_lp, 0)); + m_aux_enabled = bool(BIT(cfg_aux, 0)); + m_modem_enabled = bool(BIT(cfg_modem, 0)); + + // LP Interrupt level + m_lp_int_idx = BIT(cfg_lp, 1, 2); + + // AUX Interrupt level + m_aux_int_idx = BIT(cfg_aux, 1, 2); + + // MODEM Interrupt level + m_modem_int_idx = BIT(cfg_modem, 1, 2); +} + +void h_88_3_device::lp_int(int data) +{ + m_int_cb[m_lp_int_idx](data); +} + +void h_88_3_device::aux_int(int data) +{ + m_int_cb[m_aux_int_idx](data); +} + +void h_88_3_device::modem_int(int data) +{ + m_int_cb[m_modem_int_idx](data); +} + +void h_88_3_device::device_add_mconfig(machine_config &config) +{ + // LP DCE 0xE0-0xE7 (340 - 347 octal) + INS8250(config, m_lp, m_clock); + m_lp->out_tx_callback().set("dce1", FUNC(rs232_port_device::write_txd)); + m_lp->out_dtr_callback().set("dce1", FUNC(rs232_port_device::write_dtr)); + m_lp->out_rts_callback().set("dce1", FUNC(rs232_port_device::write_rts)); + m_lp->out_int_callback().set(FUNC(h_88_3_device::lp_int)); + + rs232_port_device &dce1(RS232_PORT(config, "dce1", default_rs232_devices, "printer")); + dce1.rxd_handler().set(m_lp, FUNC(ins8250_device::rx_w)); + dce1.dcd_handler().set(m_lp, FUNC(ins8250_device::dcd_w)); + dce1.dsr_handler().set(m_lp, FUNC(ins8250_device::dsr_w)); + dce1.cts_handler().set(m_lp, FUNC(ins8250_device::cts_w)); + dce1.ri_handler().set(m_lp, FUNC(ins8250_device::ri_w)); + + + // AUX DCE 0xD0-0xD7 (320 - 327 octal) + INS8250(config, m_aux, m_clock); + m_aux->out_tx_callback().set("dce2", FUNC(rs232_port_device::write_txd)); + m_aux->out_dtr_callback().set("dce2", FUNC(rs232_port_device::write_dtr)); + m_aux->out_rts_callback().set("dce2", FUNC(rs232_port_device::write_rts)); + m_aux->out_int_callback().set(FUNC(h_88_3_device::aux_int)); + + rs232_port_device &dce2(RS232_PORT(config, "dce2", default_rs232_devices, "loopback")); + dce2.rxd_handler().set(m_aux, FUNC(ins8250_device::rx_w)); + dce2.dcd_handler().set(m_aux, FUNC(ins8250_device::dcd_w)); + dce2.dsr_handler().set(m_aux, FUNC(ins8250_device::dsr_w)); + dce2.cts_handler().set(m_aux, FUNC(ins8250_device::cts_w)); + dce2.ri_handler().set(m_aux, FUNC(ins8250_device::ri_w)); + + + // Modem DTE 0xD7-0xDF (330 - 337 octal) + INS8250(config, m_modem, m_clock); + m_modem->out_tx_callback().set("dte", FUNC(rs232_port_device::write_txd)); + m_modem->out_dtr_callback().set("dte", FUNC(rs232_port_device::write_dtr)); + m_modem->out_rts_callback().set("dte", FUNC(rs232_port_device::write_rts)); + m_modem->out_int_callback().set(FUNC(h_88_3_device::modem_int)); + + rs232_port_device &dte(RS232_PORT(config, "dte", default_rs232_devices, "loopback")); + dte.rxd_handler().set(m_modem, FUNC(ins8250_device::rx_w)); + dte.dcd_handler().set(m_modem, FUNC(ins8250_device::dcd_w)); + dte.dsr_handler().set(m_modem, FUNC(ins8250_device::dsr_w)); + dte.cts_handler().set(m_modem, FUNC(ins8250_device::cts_w)); + dte.ri_handler().set(m_modem, FUNC(ins8250_device::ri_w)); +} + + +static INPUT_PORTS_START( h_88_3_device ) + + PORT_START("CFG_LP") + PORT_CONFNAME(0x01, 0x01, "LP - DCE (340 octal) Enabled" ) + PORT_CONFSETTING( 0x00, DEF_STR( No )) + PORT_CONFSETTING( 0x01, DEF_STR( Yes )) + PORT_CONFNAME(0x06, 0x00, "LP - DCE (340 octal) Interrupt level") + PORT_CONFSETTING( 0x00, DEF_STR( None )) + PORT_CONFSETTING( 0x02, "3") + PORT_CONFSETTING( 0x04, "4") + PORT_CONFSETTING( 0x06, "5") + + PORT_START("CFG_AUX") + PORT_CONFNAME(0x01, 0x00, "AUX - DCE (320 octal) Enabled" ) + PORT_CONFSETTING( 0x00, DEF_STR( No )) + PORT_CONFSETTING( 0x01, DEF_STR( Yes )) + PORT_CONFNAME(0x06, 0x00, "AUX - DCE (320 octal) Interrupt level") + PORT_CONFSETTING( 0x00, DEF_STR( None )) + PORT_CONFSETTING( 0x02, "3") + PORT_CONFSETTING( 0x04, "4") + PORT_CONFSETTING( 0x06, "5") + + PORT_START("CFG_MODEM") + PORT_CONFNAME(0x01, 0x01, "MODEM - DTE (330 octal) Enabled" ) + PORT_CONFSETTING( 0x00, DEF_STR( No )) + PORT_CONFSETTING( 0x01, DEF_STR( Yes )) + PORT_CONFNAME(0x06, 0x00, "MODEM - DTE (330 octal) Interrupt level") + PORT_CONFSETTING( 0x00, DEF_STR( None )) + PORT_CONFSETTING( 0x02, "3") + PORT_CONFSETTING( 0x04, "4") + PORT_CONFSETTING( 0x06, "5") + +INPUT_PORTS_END + +static INPUT_PORTS_START( ha_88_3_device ) + PORT_INCLUDE( h_88_3_device ) + + PORT_MODIFY("CFG_AUX") + PORT_CONFNAME(0x01, 0x01, "AUX - DCE (320 octal) Enabled" ) + PORT_CONFSETTING( 0x00, DEF_STR( No )) + PORT_CONFSETTING( 0x01, DEF_STR( Yes )) + +INPUT_PORTS_END + + +ioport_constructor h_88_3_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(h_88_3_device); +} + +ioport_constructor ha_88_3_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(ha_88_3_device); +} + +ha_88_3_device::ha_88_3_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : + h_88_3_device(mconfig, H89BUS_HA_88_3, tag, owner, clock) +{ +} + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_H_88_3, device_h89bus_right_card_interface, h_88_3_device, "h89h_88_3", "Heath H-88-3 3-port Serial Board"); +DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_HA_88_3, device_h89bus_right_card_interface, ha_88_3_device, "h89ha_88_3", "Heath HA-88-3 3-port Serial Board"); diff --git a/src/devices/bus/heathzenith/h89/h_88_3.h b/src/devices/bus/heathzenith/h89/h_88_3.h new file mode 100644 index 00000000000..dbaaf7c2cd4 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/h_88_3.h @@ -0,0 +1,13 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#ifndef MAME_BUS_HEATHZENITH_H89_H_88_3_H +#define MAME_BUS_HEATHZENITH_H89_H_88_3_H + +#pragma once + +#include "h89bus.h" + +DECLARE_DEVICE_TYPE(H89BUS_H_88_3, device_h89bus_right_card_interface) +DECLARE_DEVICE_TYPE(H89BUS_HA_88_3, device_h89bus_right_card_interface) + +#endif // MAME_BUS_HEATHZENITH_H89_H_88_3_H diff --git a/src/mame/heathzenith/h_88_cass.cpp b/src/devices/bus/heathzenith/h89/h_88_5.cpp index e67b72a4a7b..0b833947835 100644..100755 --- a/src/mame/heathzenith/h_88_cass.cpp +++ b/src/devices/bus/heathzenith/h89/h_88_5.cpp @@ -11,17 +11,22 @@ #include "emu.h" -#include "h_88_cass.h" +#include "h_88_5.h" +#include "formats/h8_cas.h" +#include "imagedev/cassette.h" #include "machine/clock.h" +#include "machine/i8251.h" +#include "machine/timer.h" +#include "softlist_dev.h" #include "speaker.h" #define LOG_REG (1U << 1) #define LOG_LINES (1U << 2) #define LOG_CASS (1U << 3) #define LOG_FUNC (1U << 4) -//#define VERBOSE (0xff) +#define VERBOSE (0xff) #include "logmacro.h" @@ -36,33 +41,70 @@ #define FUNCNAME __PRETTY_FUNCTION__ #endif -DEFINE_DEVICE_TYPE(HEATH_H88_CASS, heath_h_88_cass_device, "heath_h_88_cass_device", "Heath H-88-5 Cassette Interface"); +namespace { -heath_h_88_cass_device::heath_h_88_cass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - device_t(mconfig, HEATH_H88_CASS, tag, owner, 0), +class h_88_5_device : public device_t, public device_h89bus_right_card_interface +{ +public: + h_88_5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + virtual void write(u8 select_lines, u8 offset, u8 data) override; + virtual u8 read(u8 select_lines, u8 offset) override; + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + + void uart_rts(u8 data); + void uart_tx_empty(u8 data); + + TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); + TIMER_DEVICE_CALLBACK_MEMBER(kansas_w); + + required_device<i8251_device> m_uart; + required_device<cassette_image_device> m_cass_player; + required_device<cassette_image_device> m_cass_recorder; + + u8 m_cass_data[4]; + bool m_cassbit; + bool m_cassold; +}; + +h_88_5_device::h_88_5_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, H89BUS_H_88_5, tag, owner, 0), + device_h89bus_right_card_interface(mconfig, *this), m_uart(*this, "uart"), m_cass_player(*this, "cassette_player"), m_cass_recorder(*this, "cassette_recorder") { } -void heath_h_88_cass_device::write(offs_t reg, u8 val) +void h_88_5_device::write(u8 select_lines, u8 reg, u8 val) { - LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + if (select_lines & h89bus_device::H89_CASS) + { + LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); - m_uart->write(reg, val); + m_uart->write(reg, val); + } } -u8 heath_h_88_cass_device::read(offs_t reg) +u8 h_88_5_device::read(u8 select_lines, u8 reg) { - u8 val = m_uart->read(reg); + if (select_lines & h89bus_device::H89_CASS) + { + u8 val = m_uart->read(reg); - LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + + return val; + } - return val; + return 0; } -TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_w) +TIMER_DEVICE_CALLBACK_MEMBER(h_88_5_device::kansas_w) { m_cass_data[3]++; @@ -81,7 +123,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_w) m_cass_recorder->output(BIT(m_cass_data[3], bit_pos) ? -1.0 : +1.0); } -TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_r) +TIMER_DEVICE_CALLBACK_MEMBER(h_88_5_device::kansas_r) { // cassette - turn 1200/2400Hz to a bit m_cass_data[1]++; @@ -98,28 +140,28 @@ TIMER_DEVICE_CALLBACK_MEMBER(heath_h_88_cass_device::kansas_r) } } -void heath_h_88_cass_device::uart_rts(u8 data) +void h_88_5_device::uart_rts(u8 data) { LOGLINES("%s: data: %d\n", FUNCNAME, data); m_cass_player->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_PLAY, CASSETTE_MASK_UISTATE); } -void heath_h_88_cass_device::uart_tx_empty(u8 data) +void h_88_5_device::uart_tx_empty(u8 data) { LOGLINES("%s: data: %d\n", FUNCNAME, data); m_cass_recorder->change_state(bool(data) ? CASSETTE_STOPPED : CASSETTE_RECORD, CASSETTE_MASK_UISTATE); } -void heath_h_88_cass_device::device_start() +void h_88_5_device::device_start() { save_item(NAME(m_cass_data)); save_item(NAME(m_cassbit)); save_item(NAME(m_cassold)); } -void heath_h_88_cass_device::device_reset() +void h_88_5_device::device_reset() { LOGFUNC("%s\n", FUNCNAME); @@ -136,12 +178,12 @@ void heath_h_88_cass_device::device_reset() m_uart->write_rxd(0); } -void heath_h_88_cass_device::device_add_mconfig(machine_config &config) +void h_88_5_device::device_add_mconfig(machine_config &config) { I8251(config, m_uart, 0); m_uart->txd_handler().set([this] (bool state) { m_cassbit = state; }); - m_uart->rts_handler().set(FUNC(heath_h_88_cass_device::uart_rts)); - m_uart->txempty_handler().set(FUNC(heath_h_88_cass_device::uart_tx_empty)); + m_uart->rts_handler().set(FUNC(h_88_5_device::uart_rts)); + m_uart->txempty_handler().set(FUNC(h_88_5_device::uart_tx_empty)); clock_device &cassette_clock(CLOCK(config, "cassette_clock", 4800)); cassette_clock.signal_handler().set(m_uart, FUNC(i8251_device::write_txc)); @@ -161,6 +203,12 @@ void heath_h_88_cass_device::device_add_mconfig(machine_config &config) m_cass_recorder->add_route(ALL_OUTPUTS, "mono", 0.15); m_cass_recorder->set_interface("h88_cass_recorder"); - TIMER(config, "kansas_w").configure_periodic(FUNC(heath_h_88_cass_device::kansas_w), attotime::from_hz(4800)); - TIMER(config, "kansas_r").configure_periodic(FUNC(heath_h_88_cass_device::kansas_r), attotime::from_hz(40000)); + SOFTWARE_LIST(config, "cass_list").set_original("h88_cass"); + + TIMER(config, "kansas_w").configure_periodic(FUNC(h_88_5_device::kansas_w), attotime::from_hz(4800)); + TIMER(config, "kansas_r").configure_periodic(FUNC(h_88_5_device::kansas_r), attotime::from_hz(40000)); +} + } + +DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_H_88_5, device_h89bus_right_card_interface, h_88_5_device, "h89h_88_5", "Heath H-88-5 Cassette Interface Board"); diff --git a/src/devices/bus/heathzenith/h89/h_88_5.h b/src/devices/bus/heathzenith/h89/h_88_5.h new file mode 100644 index 00000000000..a210e7d0579 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/h_88_5.h @@ -0,0 +1,12 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#ifndef MAME_BUS_HEATHZENITH_H89_H_88_5_H +#define MAME_BUS_HEATHZENITH_H89_H_88_5_H + +#pragma once + +#include "h89bus.h" + +DECLARE_DEVICE_TYPE(H89BUS_H_88_5, device_h89bus_right_card_interface) + +#endif // MAME_BUS_HEATHZENITH_H89_H_88_5_H diff --git a/src/mame/heathzenith/mms77316_fdc.cpp b/src/devices/bus/heathzenith/h89/mms77316_fdc.cpp index 621ed6bf922..b0af15bdcea 100644 --- a/src/mame/heathzenith/mms77316_fdc.cpp +++ b/src/devices/bus/heathzenith/h89/mms77316_fdc.cpp @@ -14,6 +14,9 @@ #include "mms77316_fdc.h" +#include "imagedev/floppy.h" +#include "machine/wd_fdc.h" + #define LOG_REG (1U << 1) // Shows register setup #define LOG_LINES (1U << 2) // Show control lines #define LOG_DRIVE (1U << 3) // Show drive select @@ -40,13 +43,58 @@ #define FUNCNAME __PRETTY_FUNCTION__ #endif -DEFINE_DEVICE_TYPE(MMS77316_FDC, mms77316_fdc_device, "mms77316_fdc", "Magnolia MicroSystems 77316 Soft-sectored Controller"); +namespace { + +class mms77316_fdc_device : public device_t, public device_h89bus_right_card_interface +{ +public: + mms77316_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + virtual void write(u8 select_lines, u8 offset, u8 data) override; + virtual u8 read(u8 select_lines, u8 offset) override; + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + + void ctrl_w(u8 val); + void data_w(u8 val); + u8 data_r(); + + void set_irq(int state); + void set_drq(int state); + + // Burst mode was required for a 2 MHz Z80 to handle 8" DD data rates. + // The typical irq/drq was too slow, this utilizes wait states to read the + // WD1797 data port once the drq line is high. + inline bool burst_mode_r() { return !m_drq_allowed; } + +private: + required_device<fd1797_device> m_fdc; + required_device_array<floppy_connector, 8> m_floppies; + + bool m_irq_allowed; + bool m_drq_allowed; + + bool m_irq; + bool m_drq; + u32 m_drq_count; + + /// Bits set in cmd_ControlPort_c + static constexpr u8 ctrl_525DriveSel_c = 2; + static constexpr u8 ctrl_EnableIntReq_c = 3; + static constexpr u8 ctrl_EnableDrqInt_c = 5; + static constexpr u8 ctrl_SetMFMRecording_c = 6; + + static constexpr XTAL MASTER_CLOCK = XTAL(8'000'000); + static constexpr XTAL FIVE_IN_CLOCK = MASTER_CLOCK / 8; + static constexpr XTAL EIGHT_IN_CLOCK = MASTER_CLOCK / 4; +}; mms77316_fdc_device::mms77316_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - device_t(mconfig, MMS77316_FDC, tag, owner, 0), - m_irq_cb(*this), - m_drq_cb(*this), - m_wait_cb(*this), + device_t(mconfig, H89BUS_MMS77316, tag, owner, 0), + device_h89bus_right_card_interface(mconfig, *this), m_fdc(*this, "mms_fdc"), m_floppies(*this, "mms_fdc:%u", 0U) { @@ -69,13 +117,13 @@ void mms77316_fdc_device::ctrl_w(u8 val) if (m_irq_allowed) { - m_irq_cb(m_irq); - m_drq_cb(m_drq); + set_slot_fdcirq(m_irq); + set_slot_fdcdrq(m_drq); } else { - m_irq_cb(CLEAR_LINE); - m_drq_cb(CLEAR_LINE); + set_slot_fdcirq(CLEAR_LINE); + set_slot_fdcdrq(CLEAR_LINE); } LOGDRIVE("%s: floppydrive: %d, 5.25 in: %d\n", FUNCNAME, floppy_drive, five_in_drv); @@ -107,16 +155,21 @@ void mms77316_fdc_device::data_w(u8 val) { LOGBURST("%s: burst_mode_r\n", FUNCNAME); - m_wait_cb(ASSERT_LINE); + set_slot_wait(ASSERT_LINE); return; } m_fdc->data_w(val); } -void mms77316_fdc_device::write(offs_t reg, u8 val) +void mms77316_fdc_device::write(u8 select_lines, u8 reg, u8 val) { - LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + if (!(select_lines & h89bus_device::H89_GPP)) + { + return; + } + + if (reg != 2) LOGREG("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); switch (reg) { @@ -153,7 +206,7 @@ u8 mms77316_fdc_device::data_r() if (!machine().side_effects_disabled()) { - m_wait_cb(ASSERT_LINE); + set_slot_wait(ASSERT_LINE); } } else @@ -166,8 +219,13 @@ u8 mms77316_fdc_device::data_r() return data; } -u8 mms77316_fdc_device::read(offs_t reg) +u8 mms77316_fdc_device::read(u8 select_lines, u8 reg) { + if (!(select_lines & h89bus_device::H89_GPP)) + { + return 0; + } + // default return for the h89 u8 value = 0xff; @@ -215,9 +273,9 @@ void mms77316_fdc_device::device_reset() m_irq = false; m_drq_count = 0; - m_irq_cb(CLEAR_LINE); - m_drq_cb(CLEAR_LINE); - m_wait_cb(CLEAR_LINE); + set_slot_fdcirq(CLEAR_LINE); + set_slot_fdcdrq(CLEAR_LINE); + set_slot_wait(CLEAR_LINE); for (int i = 0; i < 4; i++) { @@ -293,11 +351,11 @@ void mms77316_fdc_device::set_irq(int state) if (m_irq) { - m_wait_cb(CLEAR_LINE); + set_slot_wait(CLEAR_LINE); m_drq_count = 0; } - m_irq_cb(m_irq_allowed ? m_irq : CLEAR_LINE); + set_slot_fdcirq(m_irq_allowed ? m_irq : CLEAR_LINE); } void mms77316_fdc_device::set_drq(int state) @@ -312,13 +370,17 @@ void mms77316_fdc_device::set_drq(int state) if (m_drq) { - m_wait_cb(CLEAR_LINE); + set_slot_wait(CLEAR_LINE); } - m_drq_cb(m_drq_count == 0 ? m_drq : CLEAR_LINE); + set_slot_fdcdrq(m_drq_count == 0 ? m_drq : CLEAR_LINE); } else { - m_drq_cb(m_drq_allowed ? m_drq : CLEAR_LINE); + set_slot_fdcdrq(m_drq_allowed ? m_drq : CLEAR_LINE); } } + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_MMS77316, device_h89bus_right_card_interface, mms77316_fdc_device, "mms77316_fdc", "Magnolia MicroSystems 77316 Soft-sectored Controller"); diff --git a/src/devices/bus/heathzenith/h89/mms77316_fdc.h b/src/devices/bus/heathzenith/h89/mms77316_fdc.h new file mode 100644 index 00000000000..699db267adf --- /dev/null +++ b/src/devices/bus/heathzenith/h89/mms77316_fdc.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Magnolia Microsystems 77316 soft-sectored floppy controller + +****************************************************************************/ + +#ifndef MAME_BUS_HEATHZENITH_H89_MMS77316_FDC_H +#define MAME_BUS_HEATHZENITH_H89_MMS77316_FDC_H + +#pragma once + +#include "h89bus.h" + +DECLARE_DEVICE_TYPE(H89BUS_MMS77316, device_h89bus_right_card_interface) + +#endif // MAME_BUS_HEATHZENITH_H89_MMS77316_FDC_H diff --git a/src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp b/src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp new file mode 100644 index 00000000000..bac365e3c37 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp @@ -0,0 +1,216 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + SigmaSoft Sound Effects Board + +****************************************************************************/ + +#include "emu.h" + +#include "sound/ay8910.h" +#include "speaker.h" + +#include "sigmasoft_sound.h" + +// +// Logging defines +// +#define LOG_REG (1U << 1) // Shows register setup +#define LOG_FUNC (1U << 2) // Function calls +#define LOG_ERR (1U << 3) + +#define VERBOSE (0) + +#include "logmacro.h" + +#define LOGREG(...) LOGMASKED(LOG_REG, __VA_ARGS__) +#define LOGFUNC(...) LOGMASKED(LOG_FUNC, __VA_ARGS__) +#define LOGERR(...) LOGMASKED(LOG_ERR, __VA_ARGS__) + +#ifdef _MSC_VER +#define FUNCNAME __func__ +#else +#define FUNCNAME __PRETTY_FUNCTION__ +#endif + +namespace { + +class h89bus_sigmasoft_snd_device : public device_t, public device_h89bus_right_card_interface +{ +public: + h89bus_sigmasoft_snd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + virtual u8 read(u8 select_lines, u8 reg) override; + virtual void write(u8 select_lines, u8 reg, u8 val) override; + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual ioport_constructor device_input_ports() const override ATTR_COLD; + + u8 read_joystick(); + + u8 transform_joystick_input(u8 raw_value); + +private: + required_device<ay8910_device> m_ay8910; + required_ioport m_joystick1, m_joystick2; + required_ioport m_config; + + u8 port_selection; +}; + +//************************************************************************** +// INPUT PORTS +//************************************************************************** +static INPUT_PORTS_START( sigma_sound ) + PORT_START("joystick_p1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) + + PORT_START("joystick_p2") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(2) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2) + + PORT_START("CONFIG") + PORT_CONFNAME(0x03, 0x01, "Port selection") + PORT_CONFSETTING( 0x00, "Disabled") + PORT_CONFSETTING( 0x01, "AUX - 320 Octal (0xD0)") + PORT_CONFSETTING( 0x02, "MODEM - 330 Octal (0xD8)") + PORT_CONFSETTING( 0x03, "LP - 340 Octal (0xE0)") +INPUT_PORTS_END + + +h89bus_sigmasoft_snd_device::h89bus_sigmasoft_snd_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, H89BUS_SIGMASOFT_SND, tag, owner, clock), + device_h89bus_right_card_interface(mconfig, *this), + m_ay8910(*this, "ay8910"), + m_joystick1(*this, "joystick_p1"), + m_joystick2(*this, "joystick_p2"), + m_config(*this, "CONFIG") +{ +} + +void h89bus_sigmasoft_snd_device::write(u8 select_lines, u8 reg, u8 val) +{ + // we respond to the SER0 decode + if (!(select_lines & port_selection)) + { + return; + } + + LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, val); + + switch (reg) + { + case 0: + m_ay8910->data_w(val); + break; + case 1: + m_ay8910->address_w(val); + break; + default: + LOGERR("%s: unexpected port write: %d - 0x%02x]n", FUNCNAME, reg, val); + } +} + +u8 h89bus_sigmasoft_snd_device::read(u8 select_lines, u8 reg) +{ + if (!(select_lines & port_selection)) + { + return 0; + } + + u8 value = 0x00; + + switch (reg) + { + case 0: + value = m_ay8910->data_r(); + break; + case 1: + value = this->read_joystick(); + break; + default: + LOGERR("%s: unexpected port read: %d\n", FUNCNAME, reg); + } + + LOGFUNC("%s: reg: %d val: %d\n", FUNCNAME, reg, value); + + return value; +} + +u8 h89bus_sigmasoft_snd_device::transform_joystick_input(u8 raw_value) +{ + // when button on joystick is pressed, return 0xf + if (raw_value & 0x10) + { + return 0xf; + } + + return raw_value & 0xf; +} + +// high nibble is for left joystick, low nibble is for right joystick +// when the button is pressed nibble will be set to 0xf +// +// note: 2 bits may be set if the direction of the joystick is diagonal, such as 0x9 for left & up. +// +u8 h89bus_sigmasoft_snd_device::read_joystick() +{ + u8 joy1 = m_joystick1->read(); + u8 joy2 = m_joystick2->read(); + + return this->transform_joystick_input(joy1) << 4 & this->transform_joystick_input(joy2); +} + +void h89bus_sigmasoft_snd_device::device_start() +{ +} + +void h89bus_sigmasoft_snd_device::device_reset() +{ + ioport_value const config(m_config->read()); + + + switch (config & 0x03) + { + case 0x00: + port_selection = 0; + break; + case 0x01: + port_selection = h89bus_device::H89_SER0; + break; + case 0x02: + port_selection = h89bus_device::H89_SER1; + break; + case 0x03: + port_selection = h89bus_device::H89_LP; + break; + } +} + +ioport_constructor h89bus_sigmasoft_snd_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( sigma_sound ); +} + +void h89bus_sigmasoft_snd_device::device_add_mconfig(machine_config &config) +{ + SPEAKER(config, "mono").front_center(); + + AY8910(config, m_ay8910, XTAL(8'000'000)/4); /* ??? 2.000 MHz */ + m_ay8910->add_route(ALL_OUTPUTS, "mono", 0.25); +} + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_SIGMASOFT_SND, device_h89bus_right_card_interface, h89bus_sigmasoft_snd_device, "h89sigmasnd", "SigmaSoft Sound Effects Board"); diff --git a/src/devices/bus/heathzenith/h89/sigmasoft_sound.h b/src/devices/bus/heathzenith/h89/sigmasoft_sound.h new file mode 100644 index 00000000000..b432bc6ef10 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/sigmasoft_sound.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + SigmaSoft Sound Effects Board + +****************************************************************************/ + +#ifndef MAME_BUS_HEATHZENITH_H89_SIGMASOFT_SOUND_H +#define MAME_BUS_HEATHZENITH_H89_SIGMASOFT_SOUND_H + +#pragma once + +#include "h89bus.h" + +DECLARE_DEVICE_TYPE(H89BUS_SIGMASOFT_SND, device_h89bus_right_card_interface) + +#endif // MAME_BUS_HEATHZENITH_H89_SIGMASOFT_SOUND_H diff --git a/src/devices/bus/heathzenith/h89/we_pullup.cpp b/src/devices/bus/heathzenith/h89/we_pullup.cpp new file mode 100644 index 00000000000..aaba8f575d1 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/we_pullup.cpp @@ -0,0 +1,45 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Write enable pull + + On + +****************************************************************************/ + +#include "emu.h" + +#include "we_pullup.h" + + +namespace { + +class h89bus_we_pullup_device : public device_t, public device_h89bus_right_card_interface +{ +public: + h89bus_we_pullup_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; +}; + +h89bus_we_pullup_device::h89bus_we_pullup_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, H89BUS_WE_PULLUP, tag, owner, 0), + device_h89bus_right_card_interface(mconfig, *this) +{ +} + +void h89bus_we_pullup_device::device_start() +{ +} + +void h89bus_we_pullup_device::device_reset() +{ + set_slot_fmwe(ASSERT_LINE); +} + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_WE_PULLUP, device_h89bus_right_card_interface, h89bus_we_pullup_device, "h89_we_pullup", "Pullup resistor needed when P506 slot is empty"); diff --git a/src/devices/bus/heathzenith/h89/we_pullup.h b/src/devices/bus/heathzenith/h89/we_pullup.h new file mode 100644 index 00000000000..501d78c278e --- /dev/null +++ b/src/devices/bus/heathzenith/h89/we_pullup.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Write Enable Pullup + +****************************************************************************/ + +#ifndef MAME_BUS_HEATHZENITH_H89_WE_PULLUP_H +#define MAME_BUS_HEATHZENITH_H89_WE_PULLUP_H + +#pragma once + +#include "h89bus.h" + +DECLARE_DEVICE_TYPE(H89BUS_WE_PULLUP, device_h89bus_right_card_interface) + +#endif // MAME_BUS_HEATHZENITH_H89_WE_PULLUP_H diff --git a/src/mame/heathzenith/z37_fdc.cpp b/src/devices/bus/heathzenith/h89/z37_fdc.cpp index f23f3fea8ae..41dc53b4b8a 100644 --- a/src/mame/heathzenith/z37_fdc.cpp +++ b/src/devices/bus/heathzenith/h89/z37_fdc.cpp @@ -10,6 +10,9 @@ #include "emu.h" +#include "imagedev/floppy.h" +#include "machine/wd_fdc.h" + #include "z37_fdc.h" #define LOG_REG (1U << 1) // Shows register setup @@ -32,20 +35,66 @@ #define FUNCNAME __PRETTY_FUNCTION__ #endif -DEFINE_DEVICE_TYPE(HEATH_Z37_FDC, heath_z37_fdc_device, "heath_z37_fdc", "Heath H/Z-37 Soft-sectored Controller"); +namespace { + +class h89bus_z37_device : public device_t, public device_h89bus_right_card_interface +{ +public: + h89bus_z37_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + + virtual void write(u8 select_lines, u8 offset, u8 data) override; + virtual u8 read(u8 select_lines, u8 offset) override; + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + + void ctrl_w(u8 val); + + void intf_w(u8 val); + + void cmd_w(u8 val); + u8 stat_r(); + + void data_w(u8 val); + u8 data_r(); + + void set_irq(int state); + void set_drq(int state); + +private: + required_device<fd1797_device> m_fdc; + required_device_array<floppy_connector, 4> m_floppies; -heath_z37_fdc_device::heath_z37_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): - device_t(mconfig, HEATH_Z37_FDC, tag, owner, 0), - m_irq_cb(*this), - m_drq_cb(*this), - m_block_interrupt_cb(*this), + bool m_irq_allowed; + bool m_drq_allowed; + bool m_access_track_sector; + + /// Bits set in cmd_ControlPort_c - DK.CON + static constexpr u8 ctrl_EnableIntReq_c = 0; + static constexpr u8 ctrl_EnableDrqInt_c = 1; + static constexpr u8 ctrl_SetMFMRecording_c = 2; + static constexpr u8 ctrl_MotorsOn_c = 3; + static constexpr u8 ctrl_Drive_0_c = 4; + static constexpr u8 ctrl_Drive_1_c = 5; + static constexpr u8 ctrl_Drive_2_c = 6; + static constexpr u8 ctrl_Drive_3_c = 7; + + /// Bits to set alternate registers on InterfaceControl_c - DK.INT + static constexpr u8 if_SelectSectorTrack_c = 0; +}; + +h89bus_z37_device::h89bus_z37_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock): + device_t(mconfig, H89BUS_Z37, tag, owner, 0), + device_h89bus_right_card_interface(mconfig, *this), m_fdc(*this, "z37_fdc"), m_floppies(*this, "z37_fdc:%u", 0U) { } -void heath_z37_fdc_device::ctrl_w(u8 val) +void h89bus_z37_device::ctrl_w(u8 val) { bool motor_on = bool(BIT(val, ctrl_MotorsOn_c)); @@ -58,12 +107,12 @@ void heath_z37_fdc_device::ctrl_w(u8 val) if (m_drq_allowed) { - m_block_interrupt_cb(1); + set_slot_blockirq(1); } else { - m_block_interrupt_cb(0); - m_drq_cb(0); + set_slot_blockirq(0); + set_slot_fdcdrq(0); } if (BIT(val, ctrl_Drive_0_c)) @@ -102,60 +151,70 @@ void heath_z37_fdc_device::ctrl_w(u8 val) } } -void heath_z37_fdc_device::intf_w(u8 val) +void h89bus_z37_device::intf_w(u8 val) { m_access_track_sector = bool(BIT(val, if_SelectSectorTrack_c)); LOGREG("access track/sector: %d\n", m_access_track_sector); } -void heath_z37_fdc_device::cmd_w(u8 val) +void h89bus_z37_device::cmd_w(u8 val) { m_access_track_sector ? m_fdc->sector_w(val) : m_fdc->cmd_w(val); } -u8 heath_z37_fdc_device::stat_r() +u8 h89bus_z37_device::stat_r() { return m_access_track_sector ? m_fdc->sector_r() : m_fdc->status_r(); } -void heath_z37_fdc_device::data_w(u8 val) +void h89bus_z37_device::data_w(u8 val) { m_access_track_sector ? m_fdc->track_w(val) : m_fdc->data_w(val); } -u8 heath_z37_fdc_device::data_r() +u8 h89bus_z37_device::data_r() { return m_access_track_sector ? m_fdc->track_r() : m_fdc->data_r(); } -void heath_z37_fdc_device::write(offs_t reg, u8 val) +void h89bus_z37_device::write(u8 select_lines, u8 offset, u8 data) { - LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, val); + if (!(select_lines & h89bus_device::H89_CASS)) + { + return; + } + + LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, offset, data); - switch (reg) + switch (offset) { case 0: - ctrl_w(val); + ctrl_w(data); break; case 1: - intf_w(val); + intf_w(data); break; case 2: - cmd_w(val); + cmd_w(data); break; case 3: - data_w(val); + data_w(data); break; } } -u8 heath_z37_fdc_device::read(offs_t reg) +u8 h89bus_z37_device::read(u8 select_lines, u8 offset) { + if (!(select_lines & h89bus_device::H89_CASS)) + { + return 0; + } + // default return for the h89 u8 value = 0xff; - switch (reg) + switch (offset) { case 0: case 1: @@ -169,27 +228,27 @@ u8 heath_z37_fdc_device::read(offs_t reg) break; } - LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, reg, value); + LOGFUNC("%s: reg: %d val: 0x%02x\n", FUNCNAME, offset, value); return value; } -void heath_z37_fdc_device::device_start() +void h89bus_z37_device::device_start() { save_item(NAME(m_irq_allowed)); save_item(NAME(m_drq_allowed)); save_item(NAME(m_access_track_sector)); } -void heath_z37_fdc_device::device_reset() +void h89bus_z37_device::device_reset() { m_irq_allowed = false; m_drq_allowed = false; m_access_track_sector = false; - m_irq_cb(0); - m_drq_cb(0); - m_block_interrupt_cb(0); + set_slot_fdcirq(0); + set_slot_fdcdrq(0); + set_slot_blockirq(0); } static void z37_floppies(device_slot_interface &device) @@ -204,11 +263,11 @@ static void z37_floppies(device_slot_interface &device) device.option_add("qd", FLOPPY_525_QD); } -void heath_z37_fdc_device::device_add_mconfig(machine_config &config) +void h89bus_z37_device::device_add_mconfig(machine_config &config) { FD1797(config, m_fdc, 16_MHz_XTAL / 16); - m_fdc->intrq_wr_callback().set(FUNC(heath_z37_fdc_device::set_irq)); - m_fdc->drq_wr_callback().set(FUNC(heath_z37_fdc_device::set_drq)); + m_fdc->intrq_wr_callback().set(FUNC(h89bus_z37_device::set_irq)); + m_fdc->drq_wr_callback().set(FUNC(h89bus_z37_device::set_drq)); // Z-89-37 schematics show the ready line tied high. m_fdc->set_force_ready(true); @@ -222,16 +281,20 @@ void heath_z37_fdc_device::device_add_mconfig(machine_config &config) m_floppies[3]->enable_sound(true); } -void heath_z37_fdc_device::set_irq(int state) +void h89bus_z37_device::set_irq(int state) { LOGLINES("set irq, allowed: %d state: %d\n", m_irq_allowed, state); - m_irq_cb(m_irq_allowed ? state : CLEAR_LINE); + set_slot_fdcirq(m_irq_allowed ? state : CLEAR_LINE); } -void heath_z37_fdc_device::set_drq(int state) +void h89bus_z37_device::set_drq(int state) { LOGLINES("set drq, allowed: %d state: %d\n", m_drq_allowed, state); - m_drq_cb(m_drq_allowed ? state : CLEAR_LINE); + set_slot_fdcdrq(m_drq_allowed ? state : CLEAR_LINE); } + +} // anonymous namespace + +DEFINE_DEVICE_TYPE_PRIVATE(H89BUS_Z37, device_h89bus_right_card_interface, h89bus_z37_device, "h89_z37", "Heathkit Z-37 Floppy Disk Controller"); diff --git a/src/devices/bus/heathzenith/h89/z37_fdc.h b/src/devices/bus/heathzenith/h89/z37_fdc.h new file mode 100644 index 00000000000..a3400914250 --- /dev/null +++ b/src/devices/bus/heathzenith/h89/z37_fdc.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:Mark Garlanger +/*************************************************************************** + + Heathkit Z-37 Floppy Disk Controller + +****************************************************************************/ + +#ifndef MAME__Z37_FDC_H +#define MAME_BUS_HEATHZENITH_H89_Z37_FDC_H + +#pragma once + +#include "h89bus.h" + +DECLARE_DEVICE_TYPE(H89BUS_Z37, device_h89bus_right_card_interface) + +#endif // MAME_BUS_HEATHZENITH_H89_Z37_FDC_H diff --git a/src/mame/heathzenith/h89.cpp b/src/mame/heathzenith/h89.cpp index 4e459099d76..7fa9851f0de 100644 --- a/src/mame/heathzenith/h89.cpp +++ b/src/mame/heathzenith/h89.cpp @@ -43,13 +43,13 @@ #include "emu.h" -#include "h_88_cass.h" #include "intr_cntrl.h" -#include "mms77316_fdc.h" +//#include "mms77316_fdc.h" #include "sigmasoft_parallel_port.h" #include "tlb.h" -#include "z37_fdc.h" +#include "bus/heathzenith/h89/h89bus.h" +#include "bus/heathzenith/h89/cards.h" #include "cpu/z80/z80.h" #include "machine/ins8250.h" #include "machine/ram.h" @@ -86,11 +86,10 @@ protected: m_floppy_ram(*this, "floppyram"), m_tlbc(*this, "tlbc"), m_intr_socket(*this, "intr_socket"), + m_h89bus(*this, "h89bus"), m_console(*this, "console"), - m_serial1(*this, "serial1"), - m_serial2(*this, "serial2"), - m_serial3(*this, "serial3"), - m_config(*this, "CONFIG") + m_config(*this, "CONFIG"), + m_sw501(*this, "SW501") { } @@ -103,11 +102,9 @@ protected: required_shared_ptr<u8> m_floppy_ram; required_device<heath_tlb_connector> m_tlbc; required_device<heath_intr_socket> m_intr_socket; + required_device<h89bus_device> m_h89bus; required_device<ins8250_device> m_console; - required_device<ins8250_device> m_serial1; - required_device<ins8250_device> m_serial2; - required_device<ins8250_device> m_serial3; - required_ioport m_config; + required_ioport m_config, m_sw501; memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_program; // General Purpose Port (GPP) @@ -129,16 +126,18 @@ protected: static constexpr XTAL H89_CLOCK = XTAL(12'288'000) / 6; static constexpr XTAL INS8250_CLOCK = XTAL(1'843'200); - static constexpr u8 GPP_SINGLE_STEP_BIT = 0; - static constexpr u8 GPP_ENABLE_TIMER_INTERRUPT_BIT = 1; - static constexpr u8 GPP_SPEED_SELECT_BIT = 4; - static constexpr u8 GPP_DISABLE_ROM_BIT = 5; - static constexpr u8 GPP_H17_SIDE_SELECT_BIT = 6; + static constexpr u8 GPP_SINGLE_STEP_BIT = 0; + static constexpr u8 GPP_ENABLE_TIMER_INTERRUPT_BIT = 1; + static constexpr u8 GPP_MEM1_BIT = 2; + static constexpr u8 GPP_MEM0_BIT = 4; + static constexpr u8 GPP_DISABLE_ROM_BIT = 5; + static constexpr u8 GPP_IO0_BIT = 6; + static constexpr u8 GPP_IO1_BIT = 7; void update_mem_view(); void update_gpp(u8 gpp); - void port_f2_w(u8 data); + void port_f2_w(offs_t offset, u8 data); virtual void machine_start() override ATTR_COLD; virtual void machine_reset() override ATTR_COLD; @@ -157,6 +156,8 @@ protected: void console_intr(int data); void reset_line(int data); void reset_single_step_state(); + + template <int line> void slot_irq(int state); }; /** @@ -169,17 +170,14 @@ class h88_state : public h89_base_state { public: h88_state(const machine_config &mconfig, device_type type, const char *tag): - h89_base_state(mconfig, type, tag), - m_cassette(*this, "h_88_5") + h89_base_state(mconfig, type, tag) { } void h88(machine_config &config); protected: - required_device<heath_h_88_cass_device> m_cassette; - - void h88_io(address_map &map) ATTR_COLD; + void h88_io(address_map &map); }; @@ -192,20 +190,13 @@ class h89_state : public h89_base_state { public: h89_state(const machine_config &mconfig, device_type type, const char *tag): - h89_base_state(mconfig, type, tag), - m_h37(*this, "h37") + h89_base_state(mconfig, type, tag) { } void h89(machine_config &config); - -protected: - required_device<heath_z37_fdc_device> m_h37; - - void h89_io(address_map &map) ATTR_COLD; }; - class h89_sigmasoft_state : public h89_state { public: @@ -220,7 +211,7 @@ public: protected: required_device<sigmasoft_parallel_port> m_sigma_parallel; - void h89_sigmasoft_io(address_map &map) ATTR_COLD; + void h89_sigmasoft_io(address_map &map); }; @@ -248,17 +239,15 @@ class h89_mms_state : public h89_base_state { public: h89_mms_state(const machine_config &mconfig, device_type type, const char *tag): - h89_base_state(mconfig, type, tag), - m_mms316(*this, "mms77316") + h89_base_state(mconfig, type, tag) { } void h89_mms(machine_config &config); protected: - required_device<mms77316_fdc_device> m_mms316; - - void h89_mms_io(address_map &map) ATTR_COLD; + u8 port_f2_mms_r(offs_t offset); + void port_f2_mms_w(offs_t offset, u8 data); }; @@ -389,46 +378,11 @@ void h89_base_state::h89_base_io(address_map &map) { map.unmap_value_high(); map.global_mask(0xff); - - // 8250 UART DCE 0320 (0xd0) - map(0xd0, 0xd7).rw(m_serial1, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - // 8250 UART DTE 0330 (0xd8) - typically used for modem - map(0xd8, 0xdf).rw(m_serial2, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - // 8250 UART DCE 0340 (0xe0) - typically used for printer - map(0xe0, 0xe7).rw(m_serial3, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - - // 8250 UART console - this connects internally to the Terminal Logic board that is also used in the H19. - map(0xe8, 0xef).rw(m_console, FUNC(ins8250_device::ins8250_r), FUNC(ins8250_device::ins8250_w)); - - // ports defined on the H8. On the H89, access to these addresses causes a NMI - map(0xf0, 0xf1).rw(FUNC(h89_base_state::raise_NMI_r),FUNC(h89_base_state::raise_NMI_w)); - - // General Purpose Port (GPP) - map(0xf2, 0xf2).w(FUNC(h89_base_state::port_f2_w)).portr("SW501"); - - // port defined on the H8. On the H89, access to these addresses causes a NMI - map(0xfa, 0xfb).rw(FUNC(h89_base_state::raise_NMI_r), FUNC(h89_base_state::raise_NMI_w)); -} - -void h88_state::h88_io(address_map &map) -{ - h89_base_state::h89_base_io(map); - - // Cassette I/O (uses 0xf8 - 0xf9) - Requires MTR-88 ROM - map(0xf8, 0xf9).rw(m_cassette, FUNC(heath_h_88_cass_device::read), FUNC(heath_h_88_cass_device::write)); -} - -void h89_state::h89_io(address_map &map) -{ - h89_base_state::h89_base_io(map); - - // H37 5-1/4" Soft-sectored Controller - Requires MTR-90 ROM - map(0x78, 0x7b).rw(m_h37, FUNC(heath_z37_fdc_device::read), FUNC(heath_z37_fdc_device::write)); } void h89_sigmasoft_state::h89_sigmasoft_io(address_map &map) { - h89_io(map); + h89_base_io(map); // Add SigmaSoft parallel port board, required for IGC graphics map(0x08,0x0f).rw(m_sigma_parallel, FUNC(sigmasoft_parallel_port::read), FUNC(sigmasoft_parallel_port::write)); @@ -463,14 +417,6 @@ void h89_sigmasoft_state::h89_sigmasoft_io(address_map &map) NMI | FA-FB | Unused | FC-FF | */ -void h89_mms_state::h89_mms_io(address_map &map) -{ - h89_base_state::h89_base_io(map); - - // Add MMS 77316 Double Density Controller - map(0x38,0x3f).rw(m_mms316, FUNC(mms77316_fdc_device::read), FUNC(mms77316_fdc_device::write)); -} - // Input ports static INPUT_PORTS_START( h88 ) @@ -818,6 +764,15 @@ void h89_base_state::console_intr(int data) m_intr_socket->set_irq_level(3, data); } +template <int line> void h89_base_state::slot_irq(int state) +{ + m_intr_socket->set_irq_level(line, state); +} + +template void h89_base_state::slot_irq<3>(int state); +template void h89_base_state::slot_irq<4>(int state); +template void h89_base_state::slot_irq<5>(int state); + void h89_base_state::reset_line(int data) { if (bool(data)) @@ -870,6 +825,11 @@ void h89_base_state::update_gpp(u8 gpp) m_timer_intr_enabled = bool(BIT(m_gpp, GPP_ENABLE_TIMER_INTERRUPT_BIT)); + m_h89bus->set_mem0(BIT(m_gpp, GPP_MEM0_BIT)); + m_h89bus->set_mem1(BIT(m_gpp, GPP_MEM1_BIT)); + m_h89bus->set_io0(BIT(m_gpp, GPP_IO0_BIT)); + m_h89bus->set_io1(BIT(m_gpp, GPP_IO1_BIT)); + if (BIT(changed_gpp, GPP_SINGLE_STEP_BIT)) { LOGSS("single step enable: %d\n", BIT(m_gpp, GPP_SINGLE_STEP_BIT)); @@ -888,21 +848,46 @@ void h89_base_state::update_gpp(u8 gpp) update_mem_view(); } - if (BIT(changed_gpp, GPP_SPEED_SELECT_BIT)) + if (BIT(changed_gpp, GPP_MEM0_BIT)) { - m_maincpu->set_clock(BIT(m_gpp, GPP_SPEED_SELECT_BIT) ? + m_maincpu->set_clock(BIT(m_gpp, GPP_MEM0_BIT) ? H89_CLOCK * m_cpu_speed_multiplier : H89_CLOCK); } } // General Purpose Port -void h89_base_state::port_f2_w(u8 data) +void h89_base_state::port_f2_w(offs_t offset, u8 data) { update_gpp(data); m_intr_socket->set_irq_level(1, CLEAR_LINE); } +// MMS intercepts the GPIO decoding so the GPIO pin on +// the right slots can be used as a card select without +// interfering with normal GPIO port operation. +u8 h89_mms_state::port_f2_mms_r(offs_t offset) +{ + if ((offset & 7) != 2) + { + return 0; + } + + return m_sw501->read(); +} + +void h89_mms_state::port_f2_mms_w(offs_t offset, u8 data) +{ + if ((offset & 7) != 2) + { + return; + } + + update_gpp(data); + + m_intr_socket->set_irq_level(1, CLEAR_LINE); +} + static void tlb_options(device_slot_interface &device) { device.option_add("heath", HEATH_TLB); @@ -940,6 +925,7 @@ void h89_base_state::h89_base(machine_config &config) Z80(config, m_maincpu, H89_CLOCK); m_maincpu->set_m1_map(&h89_base_state::map_fetch); m_maincpu->set_memory_map(&h89_base_state::h89_mem); + m_maincpu->set_io_map(&h88_state::h89_base_io); m_maincpu->set_irq_acknowledge_callback("intr_socket", FUNC(heath_intr_socket::irq_callback)); RAM(config, m_ram).set_default_size("64K").set_extra_options("16K,32K,48K").set_default_value(0x00); @@ -962,10 +948,28 @@ void h89_base_state::h89_base(machine_config &config) m_tlbc->reset_cb().set(FUNC(h89_base_state::reset_line)); - // H-88-3 3-port serial board - INS8250(config, m_serial1, INS8250_CLOCK); - INS8250(config, m_serial2, INS8250_CLOCK); - INS8250(config, m_serial3, INS8250_CLOCK); + H89BUS(config, m_h89bus, 0); + m_h89bus->set_program_space(m_maincpu, AS_PROGRAM); + m_h89bus->set_io_space(m_maincpu, AS_IO); + m_h89bus->in_tlb_callback().set(m_console, FUNC(ins8250_device::ins8250_r)); + m_h89bus->out_tlb_callback().set(m_console, FUNC(ins8250_device::ins8250_w)); + m_h89bus->in_nmi_callback().set(FUNC(h89_base_state::raise_NMI_r)); + m_h89bus->out_nmi_callback().set(FUNC(h89_base_state::raise_NMI_w)); + m_h89bus->in_gpp_callback().set_ioport("SW501"); + m_h89bus->out_gpp_callback().set(FUNC(h89_base_state::port_f2_w)); + m_h89bus->out_int3_callback().set(FUNC(h89_base_state::slot_irq<3>)); + m_h89bus->out_int4_callback().set(FUNC(h89_base_state::slot_irq<4>)); + m_h89bus->out_int5_callback().set(FUNC(h89_base_state::slot_irq<5>)); + m_h89bus->out_wait_callback().set(FUNC(h89_base_state::set_wait_state)); + m_h89bus->out_fdcirq_callback().set(m_intr_socket, FUNC(heath_intr_socket::set_irq)); + m_h89bus->out_fdcdrq_callback().set(m_intr_socket, FUNC(heath_intr_socket::set_drq)); + m_h89bus->out_blockirq_callback().set(m_intr_socket, FUNC(heath_intr_socket::block_interrupts)); + H89BUS_LEFT_SLOT(config, "p501", "h89bus", h89_left_cards, nullptr); + H89BUS_LEFT_SLOT(config, "p502", "h89bus", h89_left_cards, nullptr); + H89BUS_LEFT_SLOT(config, "p503", "h89bus", h89_left_cards, nullptr); + H89BUS_RIGHT_SLOT(config, "p504", "h89bus", h89_right_cards, nullptr); + H89BUS_RIGHT_SLOT(config, "p505", "h89bus", h89_right_cards, "ha_88_3"); + H89BUS_RIGHT_SLOT(config, "p506", "h89bus", h89_right_p506_cards, "we_pullup").set_p506_signalling(true); // H89 interrupt interval is 2mSec TIMER(config, "irq_timer", 0).configure_periodic(FUNC(h89_base_state::h89_irq_timer), attotime::from_msec(2)); @@ -974,37 +978,31 @@ void h89_base_state::h89_base(machine_config &config) void h88_state::h88(machine_config &config) { h89_base(config); - - m_maincpu->set_io_map(&h88_state::h88_io); + m_h89bus->set_default_bios_tag("444-43"); m_intr_socket->set_default_option("original"); m_intr_socket->set_fixed(true); - SOFTWARE_LIST(config, "cass_list").set_original("h88_cass"); - - // H-88-5 Cassette interface board - HEATH_H88_CASS(config, m_cassette, H89_CLOCK); + H89BUS_RIGHT_SLOT(config.replace(), "p504", "h89bus", h89_right_cards, "h_88_5"); } void h89_state::h89(machine_config &config) { h89_base(config); + m_h89bus->set_default_bios_tag("444-61"); - m_maincpu->set_io_map(&h89_state::h89_io); + m_maincpu->set_io_map(&h89_state::h89_base_io); m_intr_socket->set_default_option("h37"); m_intr_socket->set_fixed(true); - // Z-89-37 Soft-sectored controller - HEATH_Z37_FDC(config, m_h37); - m_h37->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq)); - m_h37->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq)); - m_h37->block_interrupt_cb().set(m_intr_socket, FUNC(heath_intr_socket::block_interrupts)); + H89BUS_RIGHT_SLOT(config.replace(), "p504", "h89bus", h89_right_cards, "z37fdc"); } void h89_sigmasoft_state::h89_sigmasoft(machine_config &config) { h89(config); + m_h89bus->set_default_bios_tag("444-61"); m_maincpu->set_addrmap(AS_IO, &h89_sigmasoft_state::h89_sigmasoft_io); sigma_tlb_options(m_tlbc); @@ -1023,15 +1021,18 @@ void h89_sigmasoft_state::h89_sigmasoft(machine_config &config) void h89_mms_state::h89_mms(machine_config &config) { h89_base(config); - m_maincpu->set_addrmap(AS_IO, &h89_mms_state::h89_mms_io); + m_h89bus->set_default_bios_tag("444-61c"); + + m_h89bus->in_gpp_callback().set(FUNC(h89_mms_state::port_f2_mms_r)); + m_h89bus->out_gpp_callback().set(FUNC(h89_mms_state::port_f2_mms_w)); + + // the card selection is different with the MMS mapping PROM + H89BUS_RIGHT_SLOT(config.replace(), "p504", "h89bus", h89_right_cards_mms, "mms77316"); + H89BUS_RIGHT_SLOT(config.replace(), "p505", "h89bus", h89_right_cards_mms, "ha_88_3"); + H89BUS_RIGHT_SLOT(config.replace(), "p506", "h89bus", h89_right_cards_mms, nullptr).set_p506_signalling(true); m_intr_socket->set_default_option("mms"); m_intr_socket->set_fixed(true); - - MMS77316_FDC(config, m_mms316); - m_mms316->drq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_drq)); - m_mms316->irq_cb().set(m_intr_socket, FUNC(heath_intr_socket::set_irq)); - m_mms316->wait_cb().set(FUNC(h89_mms_state::set_wait_state)); } diff --git a/src/mame/heathzenith/h_88_cass.h b/src/mame/heathzenith/h_88_cass.h deleted file mode 100644 index ab705d0763a..00000000000 --- a/src/mame/heathzenith/h_88_cass.h +++ /dev/null @@ -1,53 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit H-88-5 Cassette Interface card - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_H_88_CASS_H -#define MAME_HEATHKIT_H_88_CASS_H - -#pragma once - -#include "imagedev/cassette.h" -#include "machine/i8251.h" -#include "machine/timer.h" - -#include "formats/h8_cas.h" - - -class heath_h_88_cass_device : public device_t -{ -public: - heath_h_88_cass_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - void write(offs_t reg, u8 val); - u8 read(offs_t reg); - -protected: - - virtual void device_start() override ATTR_COLD; - virtual void device_reset() override ATTR_COLD; - virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; - - void uart_rts(u8 data); - void uart_tx_empty(u8 data); - - TIMER_DEVICE_CALLBACK_MEMBER(kansas_r); - TIMER_DEVICE_CALLBACK_MEMBER(kansas_w); - - required_device<i8251_device> m_uart; - required_device<cassette_image_device> m_cass_player; - required_device<cassette_image_device> m_cass_recorder; - - u8 m_cass_data[4]; - bool m_cassbit; - bool m_cassold; -}; - -DECLARE_DEVICE_TYPE(HEATH_H88_CASS, heath_h_88_cass_device) - - -#endif // MAME_HEATHKIT_H_88_CASS_H diff --git a/src/mame/heathzenith/mms77316_fdc.h b/src/mame/heathzenith/mms77316_fdc.h deleted file mode 100644 index eea4c671f63..00000000000 --- a/src/mame/heathzenith/mms77316_fdc.h +++ /dev/null @@ -1,80 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Magnolia Microsystems 77316 soft-sectored floppy controller - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_MMS77316_FDC_H -#define MAME_HEATHKIT_MMS77316_FDC_H - -#pragma once - -#include "imagedev/floppy.h" -#include "machine/wd_fdc.h" - - -class mms77316_fdc_device : public device_t -{ -public: - - mms77316_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - void write(offs_t reg, u8 val); - u8 read(offs_t reg); - - auto irq_cb() { return m_irq_cb.bind(); } - auto drq_cb() { return m_drq_cb.bind(); } - auto wait_cb() { return m_wait_cb.bind(); } - -protected: - - virtual void device_start() override ATTR_COLD; - virtual void device_reset() override ATTR_COLD; - virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; - - void ctrl_w(u8 val); - void data_w(u8 val); - u8 data_r(); - - void set_irq(int state); - void set_drq(int state); - - // Burst mode was required for a 2 MHz Z80 to handle 8" DD data rates. - // The typical irq/drq was too slow, this utilizes wait states to read the - // WD1797 data port once the drq line is high. - inline bool burst_mode_r() { return !m_drq_allowed; } - -private: - - devcb_write_line m_irq_cb; - devcb_write_line m_drq_cb; - devcb_write_line m_wait_cb; - - required_device<fd1797_device> m_fdc; - required_device_array<floppy_connector, 8> m_floppies; - - bool m_irq_allowed; - bool m_drq_allowed; - - bool m_irq; - bool m_drq; - u32 m_drq_count; - - /// Bits set in cmd_ControlPort_c - static constexpr u8 ctrl_525DriveSel_c = 2; - static constexpr u8 ctrl_EnableIntReq_c = 3; - static constexpr u8 ctrl_EnableDrqInt_c = 5; - static constexpr u8 ctrl_SetMFMRecording_c = 6; - - static constexpr XTAL MASTER_CLOCK = XTAL(8'000'000); - static constexpr XTAL FIVE_IN_CLOCK = MASTER_CLOCK / 8; - static constexpr XTAL EIGHT_IN_CLOCK = MASTER_CLOCK / 4; - -}; - -DECLARE_DEVICE_TYPE(MMS77316_FDC, mms77316_fdc_device) - - -#endif // MAME_HEATHKIT_MMS77316_FDC_H diff --git a/src/mame/heathzenith/z37_fdc.h b/src/mame/heathzenith/z37_fdc.h deleted file mode 100644 index b7b54b2f7ef..00000000000 --- a/src/mame/heathzenith/z37_fdc.h +++ /dev/null @@ -1,78 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Mark Garlanger -/*************************************************************************** - - Heathkit Z-37 Floppy Disk Controller - -****************************************************************************/ - -#ifndef MAME_HEATHKIT_Z37_FDC_H -#define MAME_HEATHKIT_Z37_FDC_H - -#pragma once - -#include "imagedev/floppy.h" -#include "machine/wd_fdc.h" - - -class heath_z37_fdc_device : public device_t -{ -public: - heath_z37_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); - - void write(offs_t reg, u8 val); - u8 read(offs_t reg); - auto irq_cb() { return m_irq_cb.bind(); } - auto drq_cb() { return m_drq_cb.bind(); } - - auto block_interrupt_cb() { return m_block_interrupt_cb.bind(); } - -protected: - - virtual void device_start() override ATTR_COLD; - virtual void device_reset() override ATTR_COLD; - virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; - - void ctrl_w(u8 val); - - void intf_w(u8 val); - - void cmd_w(u8 val); - u8 stat_r(); - - void data_w(u8 val); - u8 data_r(); - - void set_irq(int state); - void set_drq(int state); - -private: - devcb_write_line m_irq_cb; - devcb_write_line m_drq_cb; - devcb_write_line m_block_interrupt_cb; - - required_device<fd1797_device> m_fdc; - required_device_array<floppy_connector, 4> m_floppies; - - bool m_irq_allowed; - bool m_drq_allowed; - bool m_access_track_sector; - - /// Bits set in cmd_ControlPort_c - DK.CON - static constexpr u8 ctrl_EnableIntReq_c = 0; - static constexpr u8 ctrl_EnableDrqInt_c = 1; - static constexpr u8 ctrl_SetMFMRecording_c = 2; - static constexpr u8 ctrl_MotorsOn_c = 3; - static constexpr u8 ctrl_Drive_0_c = 4; - static constexpr u8 ctrl_Drive_1_c = 5; - static constexpr u8 ctrl_Drive_2_c = 6; - static constexpr u8 ctrl_Drive_3_c = 7; - - /// Bits to set alternate registers on InterfaceControl_c - DK.INT - static constexpr u8 if_SelectSectorTrack_c = 0; -}; - -DECLARE_DEVICE_TYPE(HEATH_Z37_FDC, heath_z37_fdc_device) - - -#endif // MAME_HEATHKIT_Z37_FDC_H |