summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author fulivi <fulivi@users.noreply.github.com>2017-10-25 16:25:42 +0200
committer fulivi <fulivi@users.noreply.github.com>2017-10-25 16:25:42 +0200
commitbd7800c9a658e53f87e221ba23b4367da6912b82 (patch)
treed85c1de9b74b093a4510d1746ee28d440d55672d
parenta6b76aab2f65744c0367a9908c96f3f674803c42 (diff)
hp85: support for I/O slots added. Emulation of HP82937 module added.
-rw-r--r--scripts/src/bus.lua12
-rw-r--r--scripts/src/machine.lua12
-rw-r--r--scripts/target/mame/mess.lua2
-rw-r--r--src/devices/bus/hp80_io/82937.cpp354
-rw-r--r--src/devices/bus/hp80_io/82937.h71
-rw-r--r--src/devices/bus/hp80_io/hp80_io.cpp150
-rw-r--r--src/devices/bus/hp80_io/hp80_io.h107
-rw-r--r--src/devices/machine/1mb5.cpp295
-rw-r--r--src/devices/machine/1mb5.h95
-rw-r--r--src/mame/drivers/hp80.cpp97
10 files changed, 1190 insertions, 5 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 29605ec7213..76e874b7fca 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -3164,6 +3164,18 @@ end
---------------------------------------------------
--
+--@src/devices/bus/hp80_io/hp80_io.h,BUSES["HP80_IO"] = true
+---------------------------------------------------
+
+if (BUSES["HP80_IO"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/bus/hp80_io/hp80_io.cpp",
+ MAME_DIR .. "src/devices/bus/hp80_io/82937.cpp",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/bus/hp9845_io/hp9845_io.h,BUSES["HP9845_IO"] = true
---------------------------------------------------
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index f0bb0db561b..d5a30d27756 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -1038,6 +1038,18 @@ end
---------------------------------------------------
--
+--@src/devices/machine/1mb5.h,MACHINES["1MB5"] = true
+---------------------------------------------------
+
+if (MACHINES["1MB5"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/1mb5.cpp",
+ MAME_DIR .. "src/devices/machine/1mb5.h",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/machine/i2cmem.h,MACHINES["I2CMEM"] = true
---------------------------------------------------
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 916c4be6903..35209b53114 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -418,6 +418,7 @@ MACHINES["HD63450"] = true
MACHINES["HD64610"] = true
MACHINES["HP_TACO"] = true
MACHINES["1MA6"] = true
+MACHINES["1MB5"] = true
MACHINES["I2CMEM"] = true
MACHINES["I7220"] = true
MACHINES["I80130"] = true
@@ -682,6 +683,7 @@ BUSES["ISA"] = true
BUSES["ISBX"] = true
BUSES["HP_OPTROM"] = true
BUSES["HP80_OPTROM"] = true
+BUSES["HP80_IO"] = true
BUSES["HP9845_IO"] = true
BUSES["KC"] = true
BUSES["LPCI"] = true
diff --git a/src/devices/bus/hp80_io/82937.cpp b/src/devices/bus/hp80_io/82937.cpp
new file mode 100644
index 00000000000..afeb561b8bc
--- /dev/null
+++ b/src/devices/bus/hp80_io/82937.cpp
@@ -0,0 +1,354 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82937.cpp
+
+ 82937 module (HPIB interface)
+
+ TODO: Implement Parallel Poll response
+
+ Thanks to Tim Nye & Everett Kaser for dumping the 8049 ROM
+
+ Main reference for this module is:
+ HP 82937-90007, oct 80, HP82937A HP-IB Installation and theory
+ of operation manual
+
+*********************************************************************/
+
+#include "emu.h"
+#include "82937.h"
+#include "coreutil.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// Bit manipulation
+namespace {
+ static constexpr unsigned BIT_MASK(unsigned n)
+ {
+ return 1U << n;
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= (T)BIT_MASK(n);
+ }
+}
+
+// Bits in U3 (m_latch)
+static constexpr unsigned LATCH_CA_BIT = 5; // Controller Active
+static constexpr unsigned LATCH_TA_BIT = 4; // Talker Active
+static constexpr unsigned LATCH_EN_IFC_INT_BIT = 3; // Enable IFC interrupt
+static constexpr unsigned LATCH_EN_REN_INT_BIT = 2; // Enable REN interrupt
+static constexpr unsigned LATCH_EN_ATN_INT_BIT = 1; // Enable ATN interrupt
+static constexpr unsigned LATCH_EN_NDAC_BIT = 0; // Enable NDAC
+
+// Bits on P1 port of 8049
+static constexpr unsigned P1_IFC_BIT = 7;
+static constexpr unsigned P1_REN_BIT = 6;
+static constexpr unsigned P1_SRQ_BIT = 5;
+static constexpr unsigned P1_ATN_BIT = 4;
+static constexpr unsigned P1_EOI_BIT = 3;
+static constexpr unsigned P1_DAV_BIT = 2;
+static constexpr unsigned P1_NDAC_BIT = 1;
+static constexpr unsigned P1_NRFD_BIT = 0;
+
+hp82937_io_card_device::hp82937_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : hp80_io_card_device(mconfig , HP82937_IO_CARD , tag , owner , clock),
+ m_cpu(*this , "cpu"),
+ m_translator(*this , "xlator"),
+ m_sw1(*this , "sw1"),
+ m_ieee488(*this , IEEE488_TAG)
+{
+}
+
+hp82937_io_card_device::~hp82937_io_card_device()
+{
+}
+
+void hp82937_io_card_device::install_read_write_handlers(address_space& space , uint16_t base_addr)
+{
+ space.install_readwrite_handler(base_addr , base_addr + 1 , READ8_DEVICE_DELEGATE(m_translator , hp_1mb5_device , cpu_r) , WRITE8_DEVICE_DELEGATE(m_translator , hp_1mb5_device , cpu_w));
+}
+
+void hp82937_io_card_device::inten()
+{
+ m_translator->inten();
+}
+
+void hp82937_io_card_device::clear_service()
+{
+ m_translator->clear_service();
+}
+
+WRITE_LINE_MEMBER(hp82937_io_card_device::reset_w)
+{
+ m_cpu->set_input_line(INPUT_LINE_RESET , state);
+ if (state) {
+ // When reset is asserted, clear state
+ device_reset();
+ }
+}
+
+READ_LINE_MEMBER(hp82937_io_card_device::t0_r)
+{
+ return m_iatn;
+}
+
+READ8_MEMBER(hp82937_io_card_device::p1_r)
+{
+ uint8_t res = 0;
+
+ if (BIT(m_sw1->read() , 5)) {
+ // System controller
+ BIT_SET(res , P1_IFC_BIT);
+ BIT_SET(res , P1_REN_BIT);
+ } else {
+ // Not system controller
+ if (m_ieee488->ifc_r()) {
+ BIT_SET(res , P1_IFC_BIT);
+ }
+ if (m_ieee488->ren_r()) {
+ BIT_SET(res , P1_REN_BIT);
+ }
+ }
+ if (!BIT(m_latch , LATCH_CA_BIT) || m_ieee488->srq_r()) {
+ BIT_SET(res , P1_SRQ_BIT);
+ }
+ if (m_iatn) {
+ BIT_SET(res , P1_ATN_BIT);
+ }
+ bool ndac = !BIT(m_latch , LATCH_EN_NDAC_BIT) || m_iatn;
+ if (m_talker_out) {
+ BIT_SET(res , P1_EOI_BIT);
+ BIT_SET(res , P1_DAV_BIT);
+ if (ndac && m_ieee488->ndac_r()) {
+ BIT_SET(res , P1_NDAC_BIT);
+ }
+ if (m_ieee488->nrfd_r()) {
+ BIT_SET(res , P1_NRFD_BIT);
+ }
+ } else {
+ if (m_ieee488->eoi_r()) {
+ BIT_SET(res , P1_EOI_BIT);
+ }
+ if (m_ieee488->dav_r()) {
+ BIT_SET(res , P1_DAV_BIT);
+ }
+ if (ndac) {
+ BIT_SET(res , P1_NDAC_BIT);
+ }
+ BIT_SET(res , P1_NRFD_BIT);
+ }
+
+ return res;
+}
+
+WRITE8_MEMBER(hp82937_io_card_device::p1_w)
+{
+ update_signals();
+ update_data_out();
+}
+
+READ8_MEMBER(hp82937_io_card_device::dio_r)
+{
+ if (m_dio_out) {
+ return 0xff;
+ } else {
+ return m_ieee488->dio_r();
+ }
+}
+
+WRITE8_MEMBER(hp82937_io_card_device::dio_w)
+{
+ update_data_out();
+}
+
+READ8_MEMBER(hp82937_io_card_device::switch_r)
+{
+ return m_sw1->read() | 0xc0;
+}
+
+WRITE8_MEMBER(hp82937_io_card_device::latch_w)
+{
+ LOG("latch=%02x\n" , data);
+ m_latch = data;
+ update_signals();
+ update_data_out();
+}
+
+WRITE_LINE_MEMBER(hp82937_io_card_device::ieee488_ctrl_w)
+{
+ update_signals();
+ update_data_out();
+}
+
+static INPUT_PORTS_START(hp82937_port)
+ MCFG_HP80_IO_SC(7)
+ PORT_START("sw1")
+ PORT_DIPNAME(0x1f , 0x15 , "HPIB address")
+ PORT_DIPLOCATION("S1:7,6,5,4,3")
+ PORT_DIPSETTING(0x00 , "0")
+ PORT_DIPSETTING(0x01 , "1")
+ PORT_DIPSETTING(0x02 , "2")
+ PORT_DIPSETTING(0x03 , "3")
+ PORT_DIPSETTING(0x04 , "4")
+ PORT_DIPSETTING(0x05 , "5")
+ PORT_DIPSETTING(0x06 , "6")
+ PORT_DIPSETTING(0x07 , "7")
+ PORT_DIPSETTING(0x08 , "8")
+ PORT_DIPSETTING(0x09 , "9")
+ PORT_DIPSETTING(0x0a , "10")
+ PORT_DIPSETTING(0x0b , "11")
+ PORT_DIPSETTING(0x0c , "12")
+ PORT_DIPSETTING(0x0d , "13")
+ PORT_DIPSETTING(0x0e , "14")
+ PORT_DIPSETTING(0x0f , "15")
+ PORT_DIPSETTING(0x10 , "16")
+ PORT_DIPSETTING(0x11 , "17")
+ PORT_DIPSETTING(0x12 , "18")
+ PORT_DIPSETTING(0x13 , "19")
+ PORT_DIPSETTING(0x14 , "20")
+ PORT_DIPSETTING(0x15 , "21")
+ PORT_DIPSETTING(0x16 , "22")
+ PORT_DIPSETTING(0x17 , "23")
+ PORT_DIPSETTING(0x18 , "24")
+ PORT_DIPSETTING(0x19 , "25")
+ PORT_DIPSETTING(0x1a , "26")
+ PORT_DIPSETTING(0x1b , "27")
+ PORT_DIPSETTING(0x1c , "28")
+ PORT_DIPSETTING(0x1d , "29")
+ PORT_DIPSETTING(0x1e , "30")
+ PORT_DIPSETTING(0x1f , "31")
+ PORT_DIPNAME(0x20 , 0x20 , "Sys. controller")
+ PORT_DIPLOCATION("S1:2")
+ PORT_DIPSETTING(0x00 , DEF_STR(Off))
+ PORT_DIPSETTING(0x20 , DEF_STR(On))
+INPUT_PORTS_END
+
+ioport_constructor hp82937_io_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp82937_port);
+}
+
+void hp82937_io_card_device::device_start()
+{
+ save_item(NAME(m_dio_out));
+ save_item(NAME(m_talker_out));
+ save_item(NAME(m_iatn));
+ save_item(NAME(m_latch));
+}
+
+void hp82937_io_card_device::device_reset()
+{
+ hp80_io_card_device::device_reset();
+
+ m_latch = 0;
+ m_updating = false;
+ update_signals();
+ update_data_out();
+}
+
+void hp82937_io_card_device::update_data_out()
+{
+ m_ieee488->dio_w(m_dio_out ? m_cpu->p2_r(machine().dummy_space() , 0) : 0xff);
+}
+
+void hp82937_io_card_device::update_signals()
+{
+ // Avoid recursive re-enter when writing to IEEE488 signals
+ if (m_updating) {
+ return;
+ }
+ m_updating = true;
+ bool ctrl_active = BIT(m_latch , LATCH_CA_BIT);
+ uint8_t p1 = m_cpu->p1_r(machine().dummy_space() , 0);
+ m_iatn = BIT(p1 , P1_ATN_BIT);
+ if (ctrl_active) {
+ m_ieee488->atn_w(m_iatn);
+ m_ieee488->srq_w(1);
+ } else {
+ m_ieee488->atn_w(1);
+ m_iatn = m_iatn && m_ieee488->atn_r();
+ m_ieee488->srq_w(BIT(p1 , P1_SRQ_BIT));
+ }
+ m_talker_out = (ctrl_active && !m_iatn) || (BIT(m_latch , LATCH_TA_BIT) && m_iatn);
+ if (m_talker_out) {
+ m_ieee488->nrfd_w(1);
+ m_ieee488->dav_w(BIT(p1 , P1_DAV_BIT));
+ m_ieee488->eoi_w(BIT(p1 , P1_EOI_BIT));
+ m_ieee488->ndac_w(1);
+
+ } else {
+ m_ieee488->nrfd_w(BIT(p1 , P1_NRFD_BIT));
+ m_ieee488->dav_w(1);
+ m_ieee488->eoi_w(1);
+ bool ndac = BIT(p1 , P1_NDAC_BIT);
+ if (BIT(m_latch , LATCH_EN_NDAC_BIT) && !m_iatn) {
+ ndac = false;
+ }
+ m_ieee488->ndac_w(ndac);
+ }
+ bool iren = BIT(p1 , P1_REN_BIT);
+ if (BIT(m_sw1->read() , 5)) {
+ // System controller
+ m_ieee488->ren_w(iren);
+ m_ieee488->ifc_w(BIT(p1 , P1_IFC_BIT));
+ } else {
+ // Not system controller
+ m_ieee488->ren_w(1);
+ iren = iren && m_ieee488->ren_r();
+ m_ieee488->ifc_w(1);
+ }
+ bool not_u8_1 = m_iatn || m_ieee488->eoi_r();
+ m_dio_out = not_u8_1 && m_talker_out;
+ bool irq = (BIT(m_latch , LATCH_EN_IFC_INT_BIT) && !m_ieee488->ifc_r()) ||
+ (BIT(m_latch , LATCH_EN_REN_INT_BIT) && iren) ||
+ (BIT(m_latch , LATCH_EN_ATN_INT_BIT) && !m_iatn);
+ m_cpu->set_input_line(MCS48_INPUT_IRQ , irq);
+ m_updating = false;
+}
+
+ROM_START(hp82937)
+ ROM_REGION(0x800 , "cpu" , 0)
+ ROM_LOAD("1820-2437.bin" , 0 , 0x800 , CRC(687d1559) SHA1(44dfc8c3f431cd37a270b094f1db751214009214))
+ROM_END
+
+static ADDRESS_MAP_START(cpu_io_map , AS_IO , 8 , hp82937_io_card_device)
+ ADDRESS_MAP_UNMAP_HIGH
+ AM_RANGE(0x00 , 0x01) AM_DEVREADWRITE("xlator" , hp_1mb5_device , uc_r , uc_w)
+ AM_RANGE(0x03 , 0x03) AM_READWRITE(switch_r , latch_w)
+ADDRESS_MAP_END
+
+const tiny_rom_entry *hp82937_io_card_device::device_rom_region() const
+{
+ return ROM_NAME(hp82937);
+}
+
+MACHINE_CONFIG_MEMBER(hp82937_io_card_device::device_add_mconfig)
+ MCFG_CPU_ADD("cpu" , I8049 , XTAL_11MHz)
+ MCFG_CPU_IO_MAP(cpu_io_map)
+ MCFG_MCS48_PORT_T0_IN_CB(READLINE(hp82937_io_card_device , t0_r))
+ MCFG_MCS48_PORT_T1_IN_CB(DEVREADLINE("xlator" , hp_1mb5_device , int_r))
+ MCFG_MCS48_PORT_P1_IN_CB(READ8(hp82937_io_card_device , p1_r))
+ MCFG_MCS48_PORT_P1_OUT_CB(WRITE8(hp82937_io_card_device , p1_w))
+ MCFG_MCS48_PORT_P2_IN_CB(READ8(hp82937_io_card_device , dio_r))
+ MCFG_MCS48_PORT_P2_OUT_CB(WRITE8(hp82937_io_card_device , dio_w))
+
+ MCFG_DEVICE_ADD("xlator" , HP_1MB5 , 0)
+ MCFG_1MB5_IRL_HANDLER(WRITELINE(hp82937_io_card_device , irl_w))
+ MCFG_1MB5_HALT_HANDLER(WRITELINE(hp82937_io_card_device , halt_w))
+ MCFG_1MB5_RESET_HANDLER(WRITELINE(hp82937_io_card_device , reset_w))
+
+ MCFG_IEEE488_SLOT_ADD("ieee_dev" , 0 , hp_ieee488_devices , nullptr)
+ MCFG_IEEE488_BUS_ADD()
+ MCFG_IEEE488_IFC_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
+ MCFG_IEEE488_ATN_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
+ MCFG_IEEE488_REN_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
+ MCFG_IEEE488_EOI_CALLBACK(WRITELINE(hp82937_io_card_device , ieee488_ctrl_w))
+MACHINE_CONFIG_END
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP82937_IO_CARD, hp82937_io_card_device, "hp82937", "HP82937 card")
diff --git a/src/devices/bus/hp80_io/82937.h b/src/devices/bus/hp80_io/82937.h
new file mode 100644
index 00000000000..4402eee8a13
--- /dev/null
+++ b/src/devices/bus/hp80_io/82937.h
@@ -0,0 +1,71 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 82937.h
+
+ 82937 module (HPIB interface)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP80_IO_82937_H
+#define MAME_BUS_HP80_IO_82937_H
+
+#pragma once
+
+#include "hp80_io.h"
+#include "cpu/mcs48/mcs48.h"
+#include "bus/ieee488/ieee488.h"
+#include "machine/1mb5.h"
+
+class hp82937_io_card_device : public hp80_io_card_device
+{
+public:
+ // construction/destruction
+ hp82937_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp82937_io_card_device();
+
+ virtual void install_read_write_handlers(address_space& space , uint16_t base_addr) override;
+
+ virtual void inten() override;
+ virtual void clear_service() override;
+
+ DECLARE_WRITE_LINE_MEMBER(reset_w);
+ DECLARE_READ_LINE_MEMBER(t0_r);
+ DECLARE_READ8_MEMBER(p1_r);
+ DECLARE_WRITE8_MEMBER(p1_w);
+ DECLARE_READ8_MEMBER(dio_r);
+ DECLARE_WRITE8_MEMBER(dio_w);
+ DECLARE_READ8_MEMBER(switch_r);
+ DECLARE_WRITE8_MEMBER(latch_w);
+ DECLARE_WRITE_LINE_MEMBER(ieee488_ctrl_w);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ // device-level overrides
+ virtual ioport_constructor device_input_ports() const override;
+ virtual const tiny_rom_entry *device_rom_region() const override;
+ virtual void device_add_mconfig(machine_config &config) override;
+
+private:
+ required_device<i8049_device> m_cpu;
+ required_device<hp_1mb5_device> m_translator;
+ required_ioport m_sw1;
+ required_device<ieee488_device> m_ieee488;
+
+ bool m_dio_out; // U8-4
+ bool m_talker_out; // U7-6
+ bool m_iatn;
+ uint8_t m_latch; // U3
+ bool m_updating;
+
+ void update_data_out();
+ void update_signals();
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP82937_IO_CARD, hp82937_io_card_device)
+
+#endif // MAME_BUS_HP80_IO_82937_H
diff --git a/src/devices/bus/hp80_io/hp80_io.cpp b/src/devices/bus/hp80_io/hp80_io.cpp
new file mode 100644
index 00000000000..e9ab08bb43c
--- /dev/null
+++ b/src/devices/bus/hp80_io/hp80_io.cpp
@@ -0,0 +1,150 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp80_io.cpp
+
+ I/O bus of HP80 systems
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp80_io.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP80_IO_SLOT, hp80_io_slot_device, "hp80_io_slot", "HP80 I/O Slot")
+
+// +-------------------+
+// |hp80_io_slot_device|
+// +-------------------+
+hp80_io_slot_device::hp80_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ device_t(mconfig, HP80_IO_SLOT, tag, owner, clock),
+ device_slot_interface(mconfig, *this),
+ m_irl_cb_func(*this),
+ m_halt_cb_func(*this),
+ m_slot_no(0)
+{
+}
+
+hp80_io_slot_device::~hp80_io_slot_device()
+{
+}
+
+void hp80_io_slot_device::device_start()
+{
+ m_irl_cb_func.resolve_safe();
+ m_halt_cb_func.resolve_safe();
+}
+
+WRITE_LINE_MEMBER(hp80_io_slot_device::irl_w)
+{
+ LOG("irl_w slot %u=%d\n" , m_slot_no , state);
+ m_irl_cb_func(m_slot_no , state , 0xff);
+}
+
+WRITE_LINE_MEMBER(hp80_io_slot_device::halt_w)
+{
+ LOG("halt_w slot %u=%d\n" , m_slot_no , state);
+ m_halt_cb_func(m_slot_no , state , 0xff);
+}
+
+void hp80_io_slot_device::inten()
+{
+ hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+
+ if (card != nullptr) {
+ card->inten();
+ }
+}
+
+void hp80_io_slot_device::clear_service()
+{
+ hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+
+ if (card != nullptr) {
+ card->clear_service();
+ }
+}
+
+void hp80_io_slot_device::install_read_write_handlers(address_space& space)
+{
+ hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+
+ if (card != nullptr) {
+ card->install_read_write_handlers(space , get_base_addr());
+ }
+}
+
+uint8_t hp80_io_slot_device::get_sc() const
+{
+ const hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+
+ if (card != nullptr) {
+ return card->get_sc();
+ } else {
+ return 0;
+ }
+}
+
+uint16_t hp80_io_slot_device::get_base_addr() const
+{
+ const hp80_io_card_device *card = downcast<hp80_io_card_device*>(get_card_device());
+
+ if (card != nullptr) {
+ uint16_t addr = ((uint16_t)(card->get_sc() - HP80_IO_FIRST_SC) << 1) | 0xff50;
+ return addr;
+ } else {
+ return 0;
+ }
+}
+
+// +-------------------+
+// |hp80_io_card_device|
+// +-------------------+
+uint8_t hp80_io_card_device::get_sc() const
+{
+ return m_select_code_port->read() + HP80_IO_FIRST_SC;
+}
+
+void hp80_io_card_device::inten()
+{
+}
+
+void hp80_io_card_device::clear_service()
+{
+}
+
+hp80_io_card_device::hp80_io_card_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_slot_card_interface(mconfig, *this),
+ m_select_code_port(*this , "SC")
+{
+}
+
+hp80_io_card_device::~hp80_io_card_device()
+{
+}
+
+WRITE_LINE_MEMBER(hp80_io_card_device::irl_w)
+{
+ LOG("irl_w card=%d\n" , state);
+ hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(owner());
+ slot->irl_w(state);
+}
+
+WRITE_LINE_MEMBER(hp80_io_card_device::halt_w)
+{
+ LOG("halt_w card=%d\n" , state);
+ hp80_io_slot_device *slot = downcast<hp80_io_slot_device *>(owner());
+ slot->halt_w(state);
+}
+
+#include "82937.h"
+
+SLOT_INTERFACE_START(hp80_io_slot_devices)
+SLOT_INTERFACE("82937_hpib" , HP82937_IO_CARD)
+SLOT_INTERFACE_END
diff --git a/src/devices/bus/hp80_io/hp80_io.h b/src/devices/bus/hp80_io/hp80_io.h
new file mode 100644
index 00000000000..64430f8b6b4
--- /dev/null
+++ b/src/devices/bus/hp80_io/hp80_io.h
@@ -0,0 +1,107 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ hp80_io.h
+
+ I/O bus of HP80 systems
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP80_IO_HP80_IO_H
+#define MAME_BUS_HP80_IO_HP80_IO_H
+
+#pragma once
+
+#define MCFG_HP80_IO_SLOT_ADD(_tag , _idx) \
+ MCFG_DEVICE_ADD(_tag, HP80_IO_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(hp80_io_slot_devices, nullptr, false) \
+ hp80_io_slot_device::set_slot_no(*device , _idx);
+
+#define MCFG_HP80_IO_IRL_CB(_devcb) \
+ devcb = &hp80_io_slot_device::set_irl_cb_func(*device , DEVCB_##_devcb);
+
+#define MCFG_HP80_IO_HALT_CB(_devcb) \
+ devcb = &hp80_io_slot_device::set_halt_cb_func(*device , DEVCB_##_devcb);
+
+#define HP80_IO_FIRST_SC 3 // Lowest SC used by I/O cards
+
+#define MCFG_HP80_IO_SC(_default_sc) \
+ PORT_START("SC") \
+ PORT_CONFNAME(0xf , (_default_sc) - HP80_IO_FIRST_SC , "Select Code") \
+ PORT_CONFSETTING(0 , "3")\
+ PORT_CONFSETTING(1 , "4")\
+ PORT_CONFSETTING(2 , "5")\
+ PORT_CONFSETTING(3 , "6")\
+ PORT_CONFSETTING(4 , "7")\
+ PORT_CONFSETTING(5 , "8")\
+ PORT_CONFSETTING(6 , "9")\
+ PORT_CONFSETTING(7 , "10")
+
+class hp80_io_slot_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ hp80_io_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp80_io_slot_device();
+
+ // static configuration helpers
+ static void set_slot_no(device_t &device, unsigned slot_no) { downcast<hp80_io_slot_device &>(device).m_slot_no = slot_no; }
+
+ // device-level overrides
+ virtual void device_start() override;
+
+ // Callback setups
+ template <class Object> static devcb_base &set_irl_cb_func(device_t &device, Object &&cb) { return downcast<hp80_io_slot_device &>(device).m_irl_cb_func.set_callback(std::forward<Object>(cb)); }
+ template <class Object> static devcb_base &set_halt_cb_func(device_t &device, Object &&cb) { return downcast<hp80_io_slot_device &>(device).m_halt_cb_func.set_callback(std::forward<Object>(cb)); }
+
+ // SC getter
+ uint8_t get_sc() const;
+
+ uint16_t get_base_addr() const;
+
+ void install_read_write_handlers(address_space& space);
+
+ DECLARE_WRITE_LINE_MEMBER(irl_w);
+ DECLARE_WRITE_LINE_MEMBER(halt_w);
+
+ void inten();
+ void clear_service();
+
+private:
+ devcb_write8 m_irl_cb_func;
+ devcb_write8 m_halt_cb_func;
+ unsigned m_slot_no;
+};
+
+class hp80_io_card_device : public device_t,
+ public device_slot_card_interface
+{
+public:
+ // SC getter
+ uint8_t get_sc() const;
+
+ virtual void install_read_write_handlers(address_space& space , uint16_t base_addr) = 0;
+
+ virtual void inten();
+ virtual void clear_service();
+
+protected:
+ // construction/destruction
+ hp80_io_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp80_io_card_device();
+
+ required_ioport m_select_code_port;
+
+ // card device handling
+ DECLARE_WRITE_LINE_MEMBER(irl_w);
+ DECLARE_WRITE_LINE_MEMBER(halt_w);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP80_IO_SLOT, hp80_io_slot_device)
+
+SLOT_INTERFACE_EXTERN(hp80_io_slot_devices);
+
+#endif // MAME_BUS_HP80_IO_HP80_IO_H
diff --git a/src/devices/machine/1mb5.cpp b/src/devices/machine/1mb5.cpp
new file mode 100644
index 00000000000..0aa151251d2
--- /dev/null
+++ b/src/devices/machine/1mb5.cpp
@@ -0,0 +1,295 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+/*********************************************************************
+
+ 1mb5.cpp
+
+ HP-8x I/O Translator chip (1MB5-0101)
+
+ Reference for this chip:
+ HP, aug 79, 1MB5 Detailed specification - Translator chip
+
+*********************************************************************/
+
+#include "emu.h"
+#include "1mb5.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP_1MB5, hp_1mb5_device, "hp_1mb5", "HP 1MB5")
+
+// Bit manipulation
+namespace {
+ static constexpr unsigned BIT_MASK(unsigned n)
+ {
+ return 1U << n;
+ }
+
+ template<typename T> void BIT_CLR(T& w , unsigned n)
+ {
+ w &= ~(T)BIT_MASK(n);
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= (T)BIT_MASK(n);
+ }
+
+ template<typename T> void COPY_BIT(bool bit , T& w , unsigned n)
+ {
+ if (bit) {
+ BIT_SET(w , n);
+ } else {
+ BIT_CLR(w , n);
+ }
+ }
+}
+
+hp_1mb5_device::hp_1mb5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+: device_t(mconfig , HP_1MB5 , tag , owner , clock),
+ m_irl_handler(*this),
+ m_halt_handler(*this),
+ m_reset_handler(*this),
+ m_int_handler(*this)
+{
+}
+
+READ8_MEMBER(hp_1mb5_device::cpu_r)
+{
+ uint8_t res = 0;
+
+ switch (offset) {
+ case 0:
+ // Read SR
+ res = m_sr & 0x7e;
+ if (m_obf) {
+ BIT_SET(res , 7);
+ }
+ if (m_ibf) {
+ BIT_SET(res , 0);
+ }
+ break;
+
+ case 1:
+ // Read IB
+ res = m_ib;
+ m_ibf = false;
+ update_halt();
+ break;
+ }
+
+ //LOG("RD %u=%02x\n" , offset , res);
+ return res;
+}
+
+WRITE8_MEMBER(hp_1mb5_device::cpu_w)
+{
+ //LOG("WR %u=%02x\n" , offset , data);
+ bool need_resched = false;
+
+ switch (offset) {
+ case 0:
+ // Write CR
+ m_cr = data;
+ need_resched |= set_reset(BIT(m_cr , 7));
+ need_resched |= set_int(!BIT(m_cr , 0));
+ break;
+
+ case 1:
+ // Write OB
+ m_ob = data;
+ m_obf = true;
+ update_halt();
+ break;
+ }
+ if (need_resched) {
+ LOG("resched %s\n" , space.device().tag());
+ space.device().execute().yield();
+ }
+}
+
+READ8_MEMBER(hp_1mb5_device::uc_r)
+{
+ uint8_t res = 0;
+ bool need_resched = false;
+
+ switch (offset) {
+ case 0:
+ // Read CR
+ res = m_cr & 0x7e;
+ if (m_obf) {
+ BIT_SET(res , 7);
+ }
+ if (m_ibf) {
+ BIT_SET(res , 0);
+ }
+ break;
+
+ case 1:
+ // Read OB
+ res = m_ob;
+ m_obf = false;
+ need_resched |= update_halt();
+ break;
+ }
+
+ if (need_resched) {
+ LOG("resched %s\n" , space.device().tag());
+ space.device().execute().spin();
+ }
+ //LOG("RDU %u=%02x\n" , offset , res);
+ return res;
+}
+
+WRITE8_MEMBER(hp_1mb5_device::uc_w)
+{
+ //LOG("WRU %u=%02x SR=%02x\n" , offset , data , m_sr);
+ bool need_resched = false;
+
+ switch (offset) {
+ case 0:
+ // Write SR
+ if (!BIT(m_sr , 0) && BIT(data , 0)) {
+ need_resched |= set_service(true);
+ }
+ m_sr = data;
+ m_hlten = BIT(m_sr , 7);
+ if (update_halt() && !m_halt) {
+ need_resched = true;
+ }
+ break;
+
+ case 1:
+ // Write IB
+ m_ib = data;
+ m_ibf = true;
+ need_resched |= update_halt();
+ break;
+ }
+ if (need_resched) {
+ LOG("resched %s\n" , space.device().tag());
+ space.device().execute().spin();
+ }
+}
+
+READ_LINE_MEMBER(hp_1mb5_device::irl_r)
+{
+ return m_service;
+}
+
+READ_LINE_MEMBER(hp_1mb5_device::halt_r)
+{
+ return m_halt;
+}
+
+READ_LINE_MEMBER(hp_1mb5_device::reset_r)
+{
+ return m_reset;
+}
+
+READ_LINE_MEMBER(hp_1mb5_device::int_r)
+{
+ return m_cint;
+}
+
+void hp_1mb5_device::inten()
+{
+ // Enabling interrupts (i.e. writing to 0xff40) removes uC reset
+ set_reset(false);
+}
+
+void hp_1mb5_device::clear_service()
+{
+ set_service(false);
+}
+
+void hp_1mb5_device::device_start()
+{
+ m_irl_handler.resolve_safe();
+ m_halt_handler.resolve_safe();
+ m_reset_handler.resolve_safe();
+ m_int_handler.resolve_safe();
+
+ save_item(NAME(m_sr));
+ save_item(NAME(m_cr));
+ save_item(NAME(m_ib));
+ save_item(NAME(m_ob));
+ save_item(NAME(m_ibf));
+ save_item(NAME(m_obf));
+ save_item(NAME(m_hlten));
+ save_item(NAME(m_service));
+ save_item(NAME(m_cint));
+ save_item(NAME(m_reset));
+ save_item(NAME(m_halt));
+}
+
+void hp_1mb5_device::device_reset()
+{
+ m_sr = 0;
+ m_cr = 0;
+ m_ib = 0;
+ m_ob = 0;
+ m_ibf = false;
+ m_obf = false;
+ m_hlten = false;
+ m_service = false;
+ m_cint = true;
+ m_reset = true;
+ m_halt = false;
+
+ m_irl_handler(false);
+ m_halt_handler(false);
+ m_reset_handler(true);
+ m_int_handler(true);
+}
+
+bool hp_1mb5_device::set_service(bool new_service)
+{
+ if (new_service != m_service) {
+ m_service = new_service;
+ //LOG("irl=%d\n" , m_service);
+ m_irl_handler(m_service);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool hp_1mb5_device::update_halt()
+{
+ bool new_halt = m_hlten && m_obf && !m_ibf;
+ if (new_halt != m_halt) {
+ //LOG("HALT=%d\n" , new_halt);
+ m_halt = new_halt;
+ m_halt_handler(m_halt);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool hp_1mb5_device::set_reset(bool new_reset)
+{
+ if (new_reset != m_reset) {
+ m_reset = new_reset;
+ m_reset_handler(m_reset);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool hp_1mb5_device::set_int(bool new_int)
+{
+ if (new_int != m_cint) {
+ m_cint = new_int;
+ LOG("cint=%d\n" , m_cint);
+ m_int_handler(m_cint);
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/src/devices/machine/1mb5.h b/src/devices/machine/1mb5.h
new file mode 100644
index 00000000000..3350e4a968c
--- /dev/null
+++ b/src/devices/machine/1mb5.h
@@ -0,0 +1,95 @@
+// license:BSD-3-Clause
+// copyright-holders:F. Ulivi
+/*********************************************************************
+
+ 1mb5.h
+
+ HP-8x I/O Translator chip (1MB5-0101)
+
+*********************************************************************/
+
+#ifndef MAME_MACHINE_1MB5_H
+#define MAME_MACHINE_1MB5_H
+
+#pragma once
+
+#define MCFG_1MB5_IRL_HANDLER(_devcb) \
+ devcb = &hp_1mb5_device::set_irl_handler(*device , DEVCB_##_devcb);
+
+#define MCFG_1MB5_HALT_HANDLER(_devcb) \
+ devcb = &hp_1mb5_device::set_halt_handler(*device , DEVCB_##_devcb);
+
+#define MCFG_1MB5_RESET_HANDLER(_devcb) \
+ devcb = &hp_1mb5_device::set_reset_handler(*device , DEVCB_##_devcb);
+
+#define MCFG_1MB5_INT_HANDLER(_devcb) \
+ devcb = &hp_1mb5_device::set_int_handler(*device , DEVCB_##_devcb);
+
+class hp_1mb5_device : public device_t
+{
+public:
+ // construction/destruction
+ hp_1mb5_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // static configuration helpers
+ template <class Object> static devcb_base &set_irl_handler(device_t &device, Object &&cb) { return downcast<hp_1mb5_device &>(device).m_irl_handler.set_callback(std::forward<Object>(cb)); }
+ template <class Object> static devcb_base &set_halt_handler(device_t &device, Object &&cb) { return downcast<hp_1mb5_device &>(device).m_halt_handler.set_callback(std::forward<Object>(cb)); }
+ template <class Object> static devcb_base &set_reset_handler(device_t &device, Object &&cb) { return downcast<hp_1mb5_device &>(device).m_reset_handler.set_callback(std::forward<Object>(cb)); }
+ template <class Object> static devcb_base &set_int_handler(device_t &device, Object &&cb) { return downcast<hp_1mb5_device &>(device).m_int_handler.set_callback(std::forward<Object>(cb)); }
+
+ // CPU access
+ DECLARE_READ8_MEMBER(cpu_r);
+ DECLARE_WRITE8_MEMBER(cpu_w);
+
+ // uC access
+ DECLARE_READ8_MEMBER(uc_r);
+ DECLARE_WRITE8_MEMBER(uc_w);
+
+ // Signals to CPU
+ DECLARE_READ_LINE_MEMBER(irl_r);
+ DECLARE_READ_LINE_MEMBER(halt_r);
+
+ // Signals to uC
+ DECLARE_READ_LINE_MEMBER(reset_r);
+ DECLARE_READ_LINE_MEMBER(int_r);
+
+ // Interrupt enable
+ void inten();
+
+ // Interrupt clearing
+ void clear_service();
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ devcb_write_line m_irl_handler;
+ devcb_write_line m_halt_handler;
+ devcb_write_line m_reset_handler;
+ devcb_write_line m_int_handler;
+
+ // Registers
+ uint8_t m_sr;
+ uint8_t m_cr;
+ uint8_t m_ib;
+ uint8_t m_ob;
+ bool m_ibf;
+ bool m_obf;
+ bool m_hlten;
+ bool m_service;
+ bool m_cint;
+ bool m_reset;
+ bool m_halt;
+
+ bool set_service(bool new_service);
+ bool update_halt();
+ bool set_reset(bool new_reset);
+ bool set_int(bool new_int);
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP_1MB5, hp_1mb5_device)
+
+#endif /* MAME_MACHINE_1MB5_H */
diff --git a/src/mame/drivers/hp80.cpp b/src/mame/drivers/hp80.cpp
index 4a0060726df..64c7d3d5d4d 100644
--- a/src/mame/drivers/hp80.cpp
+++ b/src/mame/drivers/hp80.cpp
@@ -19,6 +19,7 @@
#include "bus/hp80_optroms/hp80_optrom.h"
#include "softlist.h"
#include "machine/bankdev.h"
+#include "bus/hp80_io/hp80_io.h"
// Debugging
#define VERBOSE 1
@@ -72,7 +73,8 @@ static constexpr unsigned IRQ_KEYBOARD_BIT = 0;
static constexpr unsigned IRQ_TIMER0_BIT = 1;
static constexpr unsigned TIMER_COUNT = 4;
static constexpr unsigned IRQ_IOP0_BIT = IRQ_TIMER0_BIT + TIMER_COUNT;
-static constexpr unsigned IOP_COUNT = 0;
+// Maximum count of I/O processors (the same thing as count of I/O slots)
+static constexpr unsigned IOP_COUNT = 4;
static constexpr unsigned IRQ_BIT_COUNT = IRQ_IOP0_BIT + IOP_COUNT;
static constexpr unsigned NO_IRQ = IRQ_BIT_COUNT;
@@ -105,11 +107,17 @@ public:
DECLARE_READ8_MEMBER(clkdat_r);
DECLARE_WRITE8_MEMBER(clkdat_w);
DECLARE_WRITE8_MEMBER(rselec_w);
+ DECLARE_READ8_MEMBER(intrsc_r);
+ DECLARE_WRITE8_MEMBER(intrsc_w);
TIMER_DEVICE_CALLBACK_MEMBER(kb_scan);
TIMER_DEVICE_CALLBACK_MEMBER(vm_timer);
TIMER_DEVICE_CALLBACK_MEMBER(timer_update);
TIMER_DEVICE_CALLBACK_MEMBER(clk_busy_timer);
+
+ DECLARE_WRITE8_MEMBER(irl_w);
+ DECLARE_WRITE8_MEMBER(halt_w);
+
protected:
required_device<capricorn_cpu_device> m_cpu;
required_device<screen_device> m_screen;
@@ -124,6 +132,7 @@ protected:
required_ioport m_io_modkeys;
required_device_array<hp80_optrom_slot_device , 6> m_rom_drawers;
required_device<address_map_bank_device> m_rombank;
+ required_device_array<hp80_io_slot_device , IOP_COUNT> m_io_slots;
// Character generator
required_region_ptr<uint8_t> m_chargen;
@@ -137,11 +146,11 @@ protected:
uint8_t m_crt_read_byte;
uint8_t m_crt_write_byte;
bool m_global_int_en;
- uint16_t m_int_req;
uint16_t m_int_serv;
unsigned m_top_pending;
uint16_t m_int_acked;
uint16_t m_int_en;
+ uint8_t m_halt_lines;
// State of keyboard
ioport_value m_kb_state[ 3 ];
@@ -192,6 +201,7 @@ hp85_state::hp85_state(const machine_config &mconfig, device_type type, const ch
m_io_modkeys(*this, "MODKEYS"),
m_rom_drawers(*this , "drawer%u" , 1),
m_rombank(*this , "rombank"),
+ m_io_slots(*this , "slot%u" , 1),
m_chargen(*this , "chargen")
{
}
@@ -210,7 +220,6 @@ void hp85_state::machine_reset()
m_crt_ctl = BIT_MASK(CRT_CTL_POWERDN_BIT) | BIT_MASK(CRT_CTL_WIPEOUT_BIT);
m_crt_read_byte = 0;
m_crt_write_byte = 0;
- m_int_req = 0;
m_int_serv = 0;
m_top_pending = NO_IRQ;
m_int_acked = 0;
@@ -235,6 +244,8 @@ void hp85_state::machine_reset()
m_timer_idx = 0;
m_clk_busy = false;
update_irl();
+ m_halt_lines = 0;
+ m_cpu->set_input_line(INPUT_LINE_HALT , CLEAR_LINE);
// Load optional ROMs (if any)
// All entries in rombanks [01..FF] initially not present
@@ -245,6 +256,12 @@ void hp85_state::machine_reset()
}
// Clear RSELEC
m_rombank->set_bank(0xff);
+
+ // Mount I/O slots in address space
+ m_cpu->space(AS_PROGRAM).unmap_readwrite(0xff50 , 0xff5f);
+ for (auto& io : m_io_slots) {
+ io->install_read_write_handlers(m_cpu->space(AS_PROGRAM));
+ }
}
uint32_t hp85_state::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
@@ -307,13 +324,24 @@ static const uint8_t vector_table[] = {
0x08, // Timer 0
0x0a, // Timer 1
0x0c, // Timer 2
- 0x0e // Timer 3
+ 0x0e, // Timer 3
+ 0x10, // Slot 1
+ 0x10, // Slot 2
+ 0x10, // Slot 3
+ 0x10 // Slot 4
};
IRQ_CALLBACK_MEMBER(hp85_state::irq_callback)
{
logerror("IRQ ACK %u\n" , m_top_pending);
BIT_SET(m_int_acked , m_top_pending);
+ if (m_top_pending > IRQ_IOP0_BIT && m_top_pending < IRQ_BIT_COUNT) {
+ // Interrupts are disabled in all I/O translators of higher priority than
+ // the one being serviced
+ for (unsigned i = m_top_pending - 1; i >= IRQ_IOP0_BIT; i--) {
+ irq_en_w(i , false);
+ }
+ }
update_irl();
return vector_table[ m_top_pending ];
}
@@ -539,6 +567,30 @@ WRITE8_MEMBER(hp85_state::rselec_w)
m_rombank->set_bank(data);
}
+READ8_MEMBER(hp85_state::intrsc_r)
+{
+ if (m_top_pending >= IRQ_IOP0_BIT && m_top_pending < IRQ_BIT_COUNT && BIT(m_int_acked , m_top_pending)) {
+ return (uint8_t)m_io_slots[ m_top_pending - IRQ_IOP0_BIT ]->get_base_addr();
+ } else {
+ // Probably..
+ return 0xff;
+ }
+}
+
+WRITE8_MEMBER(hp85_state::intrsc_w)
+{
+ if (m_top_pending >= IRQ_IOP0_BIT && m_top_pending < IRQ_BIT_COUNT && BIT(m_int_acked , m_top_pending)) {
+ // Clear interrupt request in the slot being serviced
+ m_io_slots[ m_top_pending - IRQ_IOP0_BIT ]->clear_service();
+ }
+ for (auto& iop: m_io_slots) {
+ iop->inten();
+ }
+ for (unsigned i = IRQ_IOP0_BIT; i < (IRQ_IOP0_BIT + IOP_COUNT); i++) {
+ irq_en_w(i , true);
+ }
+}
+
// Outer index: key position [0..79] = r * 8 + c
// Inner index: SHIFT state (0 = no SHIFT, 1 = SHIFT)
static const uint8_t keyboard_table[ 80 ][ 2 ] = {
@@ -790,6 +842,24 @@ TIMER_DEVICE_CALLBACK_MEMBER(hp85_state::clk_busy_timer)
m_clk_busy = false;
}
+WRITE8_MEMBER(hp85_state::irl_w)
+{
+ //LOG("irl_w %u=%u\n" , offset , data);
+ irq_w(offset + IRQ_IOP0_BIT , data != 0);
+}
+
+WRITE8_MEMBER(hp85_state::halt_w)
+{
+ //LOG("halt_w %u=%u\n" , offset , data);
+ bool prev_halt = m_halt_lines != 0;
+ COPY_BIT(data != 0 , m_halt_lines , offset);
+ bool new_halt = m_halt_lines != 0;
+ if (prev_halt != new_halt) {
+ LOG("halt=%d hl=%x\n" , new_halt , m_halt_lines);
+ m_cpu->set_input_line(INPUT_LINE_HALT , new_halt);
+ }
+}
+
attotime hp85_state::time_to_video_mem_availability() const
{
if (BIT(m_crt_ctl , CRT_CTL_WIPEOUT_BIT) || BIT(m_crt_ctl , CRT_CTL_POWERDN_BIT)) {
@@ -880,6 +950,7 @@ void hp85_state::video_mem_write()
void hp85_state::irq_w(unsigned n_irq , bool state)
{
+ //LOG("irq_w %u=%d GIE=%d SRV=%03x ACK=%03x IE=%03x\n" , n_irq , state , m_global_int_en , m_int_serv , m_int_acked , m_int_en);
if (state && !BIT(m_int_serv , n_irq)) {
// Set service request
BIT_SET(m_int_serv , n_irq);
@@ -908,6 +979,7 @@ void hp85_state::update_int_bits()
void hp85_state::update_irl()
{
+ //LOG("irl GIE=%d top=%u ACK=%03x\n" , m_global_int_en , m_top_pending , m_int_acked);
m_cpu->set_input_line(0 , m_global_int_en && m_top_pending < IRQ_BIT_COUNT && !BIT(m_int_acked , m_top_pending));
}
@@ -1024,6 +1096,7 @@ static ADDRESS_MAP_START(cpu_mem_map , AS_PROGRAM , 8 , hp85_state)
AM_RANGE(0xff0a , 0xff0a) AM_READWRITE(clksts_r , clksts_w)
AM_RANGE(0xff0b , 0xff0b) AM_READWRITE(clkdat_r , clkdat_w)
AM_RANGE(0xff18 , 0xff18) AM_WRITE(rselec_w)
+ AM_RANGE(0xff40 , 0xff40) AM_READWRITE(intrsc_r , intrsc_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START(rombank_mem_map , AS_PROGRAM , 8 , hp85_state)
@@ -1042,7 +1115,7 @@ static MACHINE_CONFIG_START(hp85)
MCFG_ADDRESS_MAP_BANK_ENDIANNESS(ENDIANNESS_LITTLE)
MCFG_ADDRESS_MAP_BANK_DATABUS_WIDTH(8)
MCFG_ADDRESS_MAP_BANK_ADDRBUS_WIDTH(21)
- MCFG_ADDRESS_MAP_BANK_STRIDE(0x2000)
+ MCFG_ADDRESS_MAP_BANK_STRIDE(HP80_OPTROM_SIZE)
MCFG_SCREEN_ADD("screen" , RASTER)
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK / 2 , 312 , 0 , 256 , 256 , 0 , 192)
@@ -1085,6 +1158,20 @@ static MACHINE_CONFIG_START(hp85)
MCFG_DEVICE_ADD("drawer6", HP80_OPTROM_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(hp80_optrom_slot_device, NULL, false)
+ // I/O slots
+ MCFG_HP80_IO_SLOT_ADD("slot1" , 0)
+ MCFG_HP80_IO_IRL_CB(WRITE8(hp85_state , irl_w))
+ MCFG_HP80_IO_HALT_CB(WRITE8(hp85_state , halt_w))
+ MCFG_HP80_IO_SLOT_ADD("slot2" , 1)
+ MCFG_HP80_IO_IRL_CB(WRITE8(hp85_state , irl_w))
+ MCFG_HP80_IO_HALT_CB(WRITE8(hp85_state , halt_w))
+ MCFG_HP80_IO_SLOT_ADD("slot3" , 2)
+ MCFG_HP80_IO_IRL_CB(WRITE8(hp85_state , irl_w))
+ MCFG_HP80_IO_HALT_CB(WRITE8(hp85_state , halt_w))
+ MCFG_HP80_IO_SLOT_ADD("slot4" , 3)
+ MCFG_HP80_IO_IRL_CB(WRITE8(hp85_state , irl_w))
+ MCFG_HP80_IO_HALT_CB(WRITE8(hp85_state , halt_w))
+
MCFG_SOFTWARE_LIST_ADD("optrom_list" , "hp85_rom")
MACHINE_CONFIG_END