summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/bus.lua26
-rw-r--r--src/devices/bus/heathzenith/h89/cards.cpp44
-rw-r--r--src/devices/bus/heathzenith/h89/cards.h19
-rw-r--r--src/devices/bus/heathzenith/h89/h89bus.cpp406
-rw-r--r--src/devices/bus/heathzenith/h89/h89bus.h424
-rw-r--r--src/devices/bus/heathzenith/h89/h_88_3.cpp323
-rw-r--r--src/devices/bus/heathzenith/h89/h_88_3.h13
-rwxr-xr-x[-rw-r--r--]src/devices/bus/heathzenith/h89/h_88_5.cpp (renamed from src/mame/heathzenith/h_88_cass.cpp)94
-rw-r--r--src/devices/bus/heathzenith/h89/h_88_5.h12
-rw-r--r--src/devices/bus/heathzenith/h89/mms77316_fdc.cpp (renamed from src/mame/heathzenith/mms77316_fdc.cpp)106
-rw-r--r--src/devices/bus/heathzenith/h89/mms77316_fdc.h18
-rw-r--r--src/devices/bus/heathzenith/h89/sigmasoft_sound.cpp216
-rw-r--r--src/devices/bus/heathzenith/h89/sigmasoft_sound.h18
-rw-r--r--src/devices/bus/heathzenith/h89/we_pullup.cpp45
-rw-r--r--src/devices/bus/heathzenith/h89/we_pullup.h18
-rw-r--r--src/devices/bus/heathzenith/h89/z37_fdc.cpp (renamed from src/mame/heathzenith/z37_fdc.cpp)137
-rw-r--r--src/devices/bus/heathzenith/h89/z37_fdc.h18
-rw-r--r--src/mame/heathzenith/h89.cpp211
-rw-r--r--src/mame/heathzenith/h_88_cass.h53
-rw-r--r--src/mame/heathzenith/mms77316_fdc.h80
-rw-r--r--src/mame/heathzenith/z37_fdc.h78
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