summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author fulivi <fulivi@users.noreply.github.com>2018-12-04 15:10:58 +0100
committer Robert <Robbbert@users.noreply.github.com>2018-12-05 01:10:58 +1100
commit72dc8609aa7670702b493330c4b0c0668b093d11 (patch)
treeb9bf6131ef91807a96dc75a9ff7a8deb8342d234
parent3530de78ccba7aa1328da19cca31c64fc5c7a81e (diff)
hp9825 & hp9845: refactored I/O sub-system. Added 98032 GPIO module. (#4353)
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--scripts/target/mame/mess.lua2
-rw-r--r--src/devices/bus/hp9845_io/98032.cpp569
-rw-r--r--src/devices/bus/hp9845_io/98032.h192
-rw-r--r--src/devices/bus/hp9845_io/hp9845_io.cpp64
-rw-r--r--src/devices/bus/hp9845_io/hp9845_io.h52
-rw-r--r--src/mame/drivers/hp9825.cpp199
-rw-r--r--src/mame/drivers/hp9845.cpp262
-rw-r--r--src/mame/includes/hp9845.h42
-rw-r--r--src/mame/machine/hp9845_printer.h17
-rw-r--r--src/mame/machine/hp98x5_io_sys.cpp154
-rw-r--r--src/mame/machine/hp98x5_io_sys.h67
12 files changed, 1224 insertions, 398 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index c16acbe2dde..dc1092a27f1 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -3472,6 +3472,8 @@ if (BUSES["HP9845_IO"]~=null) then
files {
MAME_DIR .. "src/devices/bus/hp9845_io/hp9845_io.cpp",
MAME_DIR .. "src/devices/bus/hp9845_io/hp9845_io.h",
+ MAME_DIR .. "src/devices/bus/hp9845_io/98032.cpp",
+ MAME_DIR .. "src/devices/bus/hp9845_io/98032.h",
MAME_DIR .. "src/devices/bus/hp9845_io/98034.cpp",
MAME_DIR .. "src/devices/bus/hp9845_io/98034.h",
MAME_DIR .. "src/devices/bus/hp9845_io/98035.cpp",
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index 8c60f81af4e..c7a1e4cf60a 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -2248,6 +2248,8 @@ files {
MAME_DIR .. "src/mame/machine/hp9825_tape.h",
MAME_DIR .. "src/mame/machine/hp9845_printer.cpp",
MAME_DIR .. "src/mame/machine/hp9845_printer.h",
+ MAME_DIR .. "src/mame/machine/hp98x5_io_sys.cpp",
+ MAME_DIR .. "src/mame/machine/hp98x5_io_sys.h",
MAME_DIR .. "src/mame/video/hp48.cpp",
MAME_DIR .. "src/mame/drivers/hp49gp.cpp",
MAME_DIR .. "src/mame/drivers/hp9845.cpp",
diff --git a/src/devices/bus/hp9845_io/98032.cpp b/src/devices/bus/hp9845_io/98032.cpp
new file mode 100644
index 00000000000..c4838331b87
--- /dev/null
+++ b/src/devices/bus/hp9845_io/98032.cpp
@@ -0,0 +1,569 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 98032.cpp
+
+ 98032 module (GPIO interface)
+
+ Main reference for this module:
+ HP, 98032A 16-bit Interface Installation and Service Manual
+
+*********************************************************************/
+
+#include "emu.h"
+#include "98032.h"
+
+// Debugging
+#define VERBOSE 0
+#include "logmacro.h"
+
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)1U << n;
+ }
+
+ template<typename T> void BIT_CLR(T& w , unsigned n)
+ {
+ w &= ~BIT_MASK<T>(n);
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+// device type definition
+DEFINE_DEVICE_TYPE(HP98032_IO_CARD, hp98032_io_card_device, "hp98032" , "HP98032 card")
+DEFINE_DEVICE_TYPE(HP98032_GPIO_SLOT , hp98032_gpio_slot_device , "hp98032_gpio_slot" , "HP98032 GPIO slot")
+DEFINE_DEVICE_TYPE(HP98032_GPIO_LOOPBACK , hp98032_gpio_loopback_device , "hp98032_loopback" , "HP98032 loopback connector")
+
+// +----------------------+
+// |hp98032_io_card_device|
+// +----------------------+
+
+hp98032_io_card_device::hp98032_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : hp9845_io_card_device(mconfig , HP98032_IO_CARD , tag , owner , clock)
+ , m_gpio(*this , "gpio")
+{
+}
+
+hp98032_io_card_device::~hp98032_io_card_device()
+{
+}
+
+MACHINE_CONFIG_START(hp98032_io_card_device::device_add_mconfig)
+ HP98032_GPIO_SLOT(config , m_gpio , 0);
+ m_gpio->pflg_cb().set(FUNC(hp98032_io_card_device::pflg_w));
+ m_gpio->psts_cb().set(FUNC(hp98032_io_card_device::psts_w));
+ m_gpio->eir_cb().set(FUNC(hp98032_io_card_device::eir_w));
+MACHINE_CONFIG_END
+
+static INPUT_PORTS_START(hp98032_port)
+ MCFG_HP9845_IO_SC(2)
+INPUT_PORTS_END
+
+ioport_constructor hp98032_io_card_device::device_input_ports() const
+{
+ return INPUT_PORTS_NAME(hp98032_port);
+}
+
+void hp98032_io_card_device::device_start()
+{
+ save_item(NAME(m_output));
+ save_item(NAME(m_input));
+ save_item(NAME(m_int_en));
+ save_item(NAME(m_dma_en));
+ save_item(NAME(m_busy));
+ save_item(NAME(m_pready));
+ save_item(NAME(m_flag));
+ save_item(NAME(m_auto_ah));
+ save_item(NAME(m_eir));
+}
+
+void hp98032_io_card_device::device_reset()
+{
+ // m_output is not reset
+ // m_input is not reset
+ m_int_en = false;
+ m_dma_en = false;
+ m_busy = true; // Force reset
+ m_auto_ah = false;
+ set_busy(false);
+ update_irq();
+ update_dmar();
+ m_gpio->preset_w(1);
+ m_gpio->preset_w(0);
+}
+
+READ16_MEMBER(hp98032_io_card_device::reg_r)
+{
+ uint16_t res = 0;
+
+ switch (offset) {
+ case 0:
+ // R4
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_C)) {
+ latch_input_LSB();
+ }
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_B) &&
+ m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_A)) {
+ latch_input_MSB();
+ }
+ res = m_input & 0x00ff;
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_B)) {
+ res |= (m_input & 0xff00);
+ }
+ // Set direction to input
+ m_gpio->io_w(0);
+ if (m_auto_ah) {
+ start_hs();
+ }
+ break;
+
+ case 1:
+ // R5
+ BIT_SET(res , 5);
+ res |= (m_gpio->ext_status_r() & 3);
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_2)) {
+ BIT_SET(res , 2);
+ }
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_1)) {
+ BIT_SET(res , 3);
+ }
+ if (m_dma_en) {
+ BIT_SET(res , 6);
+ }
+ if (m_int_en) {
+ BIT_SET(res , 7);
+ }
+ break;
+
+ case 2:
+ // R6
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_B) &&
+ m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_C)) {
+ latch_input_LSB();
+ }
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_A)) {
+ latch_input_MSB();
+ }
+ res = m_input & 0xff00;
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_B)) {
+ res |= (m_input & 0x00ff);
+ }
+ m_dma_en = false;
+ update_irq();
+ update_dmar();
+ break;
+
+ case 3:
+ // R7: not mapped
+ default:
+ break;
+ }
+
+ LOG("rd R%u=%04x\n" , offset + 4 , res);
+ return res;
+}
+
+WRITE16_MEMBER(hp98032_io_card_device::reg_w)
+{
+ LOG("wr R%u=%04x\n" , offset + 4 , data);
+
+ switch (offset) {
+ case 0:
+ // R4
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_F)) {
+ m_output = data;
+ } else {
+ m_output = (m_output & 0xff00) | (data & 0x00ff);
+ }
+ m_gpio->output_w(m_output);
+ // Set direction to output
+ m_gpio->io_w(1);
+ if (m_auto_ah) {
+ start_hs();
+ }
+ break;
+
+ case 1:
+ // R5
+ m_gpio->ext_control_w(data & 3);
+ if (BIT(data , 5)) {
+ // Reset pulse
+ device_reset();
+ } else {
+ m_auto_ah = BIT(data , 4);
+ m_dma_en = BIT(data , 6);
+ m_int_en = BIT(data , 7);
+ update_irq();
+ update_dmar();
+ }
+ break;
+
+ case 2:
+ // R6
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_F)) {
+ m_output = data;
+ } else {
+ m_output = (m_output & 0x00ff) | (data & 0xff00);
+ }
+ m_gpio->output_w(m_output);
+ // Set direction to output
+ m_gpio->io_w(1);
+ if (m_auto_ah) {
+ start_hs();
+ }
+ m_dma_en = false;
+ update_irq();
+ update_dmar();
+ break;
+
+ case 3:
+ // R7
+ start_hs();
+ break;
+
+ default:
+ break;
+ }
+}
+
+WRITE_LINE_MEMBER(hp98032_io_card_device::pflg_w)
+{
+ bool prev_pready = m_pready;
+ m_pready = state;
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_4)) {
+ m_pready = !m_pready;
+ }
+ LOG("pready = %d\n" , m_pready);
+ if (!prev_pready && m_pready) {
+ // Going to ready state
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_9)) {
+ latch_input_MSB();
+ }
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_D)) {
+ latch_input_LSB();
+ }
+ } else if (prev_pready && !m_pready) {
+ // Going to not ready state
+ set_busy(false);
+ }
+ if (prev_pready != m_pready) {
+ update_flag();
+ }
+}
+
+WRITE_LINE_MEMBER(hp98032_io_card_device::psts_w)
+{
+ bool sts = !state;
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_5)) {
+ sts = !sts;
+ }
+ LOG("sts = %d\n" , sts);
+ sts_w(sts);
+}
+
+WRITE_LINE_MEMBER(hp98032_io_card_device::eir_w)
+{
+ m_eir = state;
+ LOG("eir = %d\n" , m_eir);
+ update_irq();
+}
+
+void hp98032_io_card_device::start_hs()
+{
+ set_busy(true);
+}
+
+void hp98032_io_card_device::set_busy(bool state)
+{
+ LOG("busy = %d\n" , state);
+ if (m_busy && !state) {
+ // BUSY -> !BUSY
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_8)) {
+ latch_input_MSB();
+ }
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_E)) {
+ latch_input_LSB();
+ }
+ }
+ if (m_busy != state) {
+ m_busy = state;
+ update_flag();
+ bool pctl = m_busy;
+ if (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_3)) {
+ pctl = !pctl;
+ }
+ LOG("pctl = %d\n" , pctl);
+ m_gpio->pctl_w(pctl);
+ }
+}
+
+void hp98032_io_card_device::update_flag()
+{
+ bool new_flag = !m_busy && (m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_6) || m_pready);
+ if (new_flag != m_flag) {
+ m_flag = new_flag;
+ LOG("flag = %d\n" , m_flag);
+ update_irq();
+ update_dmar();
+ flg_w(m_flag);
+ }
+}
+
+void hp98032_io_card_device::update_irq()
+{
+ bool irq = m_int_en && (m_eir || (!m_dma_en && m_flag));
+ LOG("irq = %d\n" , irq);
+ irq_w(irq);
+}
+
+void hp98032_io_card_device::update_dmar()
+{
+ bool dmar = m_gpio->is_jumper_present(hp98032_gpio_slot_device::JUMPER_7) && m_flag && m_dma_en;
+ LOG("dmar = %d\n" , dmar);
+ dmar_w(dmar);
+}
+
+void hp98032_io_card_device::latch_input_MSB()
+{
+ m_input = (m_input & 0x00ff) | (m_gpio->input_r() & 0xff00);
+}
+
+void hp98032_io_card_device::latch_input_LSB()
+{
+ m_input = (m_input & 0xff00) | (m_gpio->input_r() & 0x00ff);
+}
+
+// +------------------------+
+// |hp98032_gpio_slot_device|
+// +------------------------+
+
+hp98032_gpio_slot_device::hp98032_gpio_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig , HP98032_GPIO_SLOT , tag , owner , clock)
+ , device_slot_interface(mconfig , *this)
+ , m_pflg_handler(*this)
+ , m_psts_handler(*this)
+ , m_eir_handler(*this)
+{
+ option_reset();
+ option_add("loopback" , HP98032_GPIO_LOOPBACK);
+ set_default_option(nullptr);
+ set_fixed(false);
+}
+
+hp98032_gpio_slot_device::~hp98032_gpio_slot_device()
+{
+}
+
+uint16_t hp98032_gpio_slot_device::get_jumpers() const
+{
+ hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ if (card != nullptr) {
+ return card->get_jumpers();
+ } else {
+ return 0;
+ }
+}
+
+uint16_t hp98032_gpio_slot_device::input_r() const
+{
+ hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ if (card != nullptr) {
+ return card->input_r();
+ } else {
+ return 0;
+ }
+}
+
+uint8_t hp98032_gpio_slot_device::ext_status_r() const
+{
+ hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ if (card != nullptr) {
+ return card->ext_status_r();
+ } else {
+ return 0;
+ }
+}
+
+void hp98032_gpio_slot_device::output_w(uint16_t data)
+{
+ hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ if (card != nullptr) {
+ card->output_w(data);
+ }
+}
+
+void hp98032_gpio_slot_device::ext_control_w(uint8_t data)
+{
+ hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ if (card != nullptr) {
+ card->ext_control_w(data);
+ }
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_slot_device::pflg_w)
+{
+ m_pflg_handler(state);
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_slot_device::psts_w)
+{
+ m_psts_handler(state);
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_slot_device::eir_w)
+{
+ m_eir_handler(state);
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_slot_device::pctl_w)
+{
+ hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ if (card != nullptr) {
+ card->pctl_w(state);
+ }
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_slot_device::io_w)
+{
+ hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ if (card != nullptr) {
+ card->io_w(state);
+ }
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_slot_device::preset_w)
+{
+ hp98032_gpio_card_device *card = downcast<hp98032_gpio_card_device*>(get_card_device());
+ if (card != nullptr) {
+ card->preset_w(state);
+ }
+}
+
+void hp98032_gpio_slot_device::device_start()
+{
+ m_pflg_handler.resolve_safe();
+ m_psts_handler.resolve_safe();
+ m_eir_handler.resolve_safe();
+}
+
+void hp98032_gpio_slot_device::device_reset()
+{
+ // When nothing is connected to GPIO, set input signals to 0
+ if (get_card_device() == nullptr) {
+ m_pflg_handler(0);
+ m_psts_handler(0);
+ m_eir_handler(0);
+ }
+}
+
+// +------------------------+
+// |hp98032_gpio_card_device|
+// +------------------------+
+
+hp98032_gpio_card_device::hp98032_gpio_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)
+{
+}
+
+hp98032_gpio_card_device::~hp98032_gpio_card_device()
+{
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_card_device::pflg_w)
+{
+ hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(owner());
+ slot->pflg_w(state);
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_card_device::psts_w)
+{
+ hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(owner());
+ slot->psts_w(state);
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_card_device::eir_w)
+{
+ hp98032_gpio_slot_device *slot = downcast<hp98032_gpio_slot_device*>(owner());
+ slot->eir_w(state);
+}
+
+// +----------------------------+
+// |hp98032_gpio_loopback_device|
+// +----------------------------+
+
+hp98032_gpio_loopback_device::hp98032_gpio_loopback_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : hp98032_gpio_card_device(mconfig, HP98032_GPIO_LOOPBACK, tag, owner, clock)
+{
+}
+
+hp98032_gpio_loopback_device::~hp98032_gpio_loopback_device()
+{
+}
+
+uint16_t hp98032_gpio_loopback_device::get_jumpers() const
+{
+ return hp98032_gpio_slot_device::JUMPER_1 |
+ hp98032_gpio_slot_device::JUMPER_2 |
+ hp98032_gpio_slot_device::JUMPER_4 |
+ hp98032_gpio_slot_device::JUMPER_7 |
+ hp98032_gpio_slot_device::JUMPER_A |
+ hp98032_gpio_slot_device::JUMPER_B |
+ hp98032_gpio_slot_device::JUMPER_C |
+ hp98032_gpio_slot_device::JUMPER_F;
+}
+
+uint16_t hp98032_gpio_loopback_device::input_r() const
+{
+ return m_output;
+}
+
+uint8_t hp98032_gpio_loopback_device::ext_status_r() const
+{
+ uint8_t res = m_ext_control;
+ if (m_io) {
+ BIT_SET(res , 0);
+ }
+ return res;
+}
+
+void hp98032_gpio_loopback_device::output_w(uint16_t data)
+{
+ m_output = data;
+}
+
+void hp98032_gpio_loopback_device::ext_control_w(uint8_t data)
+{
+ m_ext_control = data;
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_loopback_device::pctl_w)
+{
+ pflg_w(state);
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_loopback_device::io_w)
+{
+ m_io = state;
+}
+
+WRITE_LINE_MEMBER(hp98032_gpio_loopback_device::preset_w)
+{
+ eir_w(state);
+}
+
+void hp98032_gpio_loopback_device::device_start()
+{
+}
+
+void hp98032_gpio_loopback_device::device_reset()
+{
+ psts_w(0);
+}
diff --git a/src/devices/bus/hp9845_io/98032.h b/src/devices/bus/hp9845_io/98032.h
new file mode 100644
index 00000000000..94013ca589f
--- /dev/null
+++ b/src/devices/bus/hp9845_io/98032.h
@@ -0,0 +1,192 @@
+// license:BSD-3-Clause
+// copyright-holders: F. Ulivi
+/*********************************************************************
+
+ 98032.h
+
+ 98032 module (GPIO interface)
+
+*********************************************************************/
+
+#ifndef MAME_BUS_HP9845_IO_98032_H
+#define MAME_BUS_HP9845_IO_98032_H
+
+#pragma once
+
+#include "hp9845_io.h"
+class hp98032_gpio_slot_device;
+
+class hp98032_io_card_device : public hp9845_io_card_device
+{
+public:
+ // construction/destruction
+ hp98032_io_card_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp98032_io_card_device();
+
+protected:
+ // device-level overrides
+ virtual void device_add_mconfig(machine_config &config) override;
+ virtual ioport_constructor device_input_ports() const override;
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual DECLARE_READ16_MEMBER(reg_r) override;
+ virtual DECLARE_WRITE16_MEMBER(reg_w) override;
+
+private:
+ required_device<hp98032_gpio_slot_device> m_gpio;
+
+ uint16_t m_output;
+ uint16_t m_input;
+ bool m_int_en;
+ bool m_dma_en;
+ bool m_busy; // U5B
+ bool m_pready;
+ bool m_flag;
+ bool m_auto_ah;
+ bool m_eir;
+
+ DECLARE_WRITE_LINE_MEMBER(pflg_w);
+ DECLARE_WRITE_LINE_MEMBER(psts_w);
+ DECLARE_WRITE_LINE_MEMBER(eir_w);
+
+ void start_hs();
+ void set_busy(bool state);
+ void update_flag();
+ void update_irq();
+ void update_dmar();
+ void latch_input_MSB();
+ void latch_input_LSB();
+};
+
+// The GPIO interface of HP98032 cards
+class hp98032_gpio_slot_device : public device_t,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ hp98032_gpio_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp98032_gpio_slot_device();
+
+ // Bits in jumper configuration
+ enum : uint16_t {
+ JUMPER_1 = (1U << 0), // Invert input data
+ JUMPER_2 = (1U << 1), // Invert output data
+ JUMPER_3 = (1U << 2), // Invert PCTL
+ JUMPER_4 = (1U << 3), // Invert PFLG
+ JUMPER_5 = (1U << 4), // Invert PSTS
+ JUMPER_6 = (1U << 5), // Pulse-mode HS
+ JUMPER_7 = (1U << 6), // DMA enable
+ JUMPER_8 = (1U << 7), // Latch input MSB when BUSY falls
+ JUMPER_9 = (1U << 8), // Latch input MSB when PREADY rises
+ JUMPER_A = (1U << 9), // Latch input MSB when reading R6
+ JUMPER_B = (1U << 10), // Word input mode
+ JUMPER_C = (1U << 11), // Latch input LSB when reading R4
+ JUMPER_D = (1U << 12), // Latch input LSB when PREADY rises
+ JUMPER_E = (1U << 13), // Latch input LSB when BUSY falls
+ JUMPER_F = (1U << 14) // Word output mode
+ };
+
+ // Get jumper configuration
+ uint16_t get_jumpers() const;
+ bool is_jumper_present(uint16_t mask) const { return (get_jumpers() & mask) != 0; }
+
+ // All I/O signals on 98032 GPIO port use negative logic. Data bits are inverted.
+ // Here we use positive logic & non-inverted data bits.
+
+ // Read input port
+ uint16_t input_r() const;
+
+ // Read extended status (2 bits)
+ uint8_t ext_status_r() const;
+
+ // Write to output port
+ void output_w(uint16_t data);
+
+ // Write to extended controls (2 bits)
+ void ext_control_w(uint8_t data);
+
+ // Input signal callbacks
+ auto pflg_cb() { return m_pflg_handler.bind(); }
+ auto psts_cb() { return m_psts_handler.bind(); }
+ auto eir_cb() { return m_eir_handler.bind(); }
+
+ // Write to input signals (for card devices)
+ DECLARE_WRITE_LINE_MEMBER(pflg_w);
+ DECLARE_WRITE_LINE_MEMBER(psts_w);
+ DECLARE_WRITE_LINE_MEMBER(eir_w);
+
+ // Write to output signals
+ DECLARE_WRITE_LINE_MEMBER(pctl_w);
+ DECLARE_WRITE_LINE_MEMBER(io_w);
+ DECLARE_WRITE_LINE_MEMBER(preset_w);
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+private:
+ devcb_write_line m_pflg_handler;
+ devcb_write_line m_psts_handler;
+ devcb_write_line m_eir_handler;
+
+};
+
+// A device connected to GPIO port of HP98032
+class hp98032_gpio_card_device : public device_t,
+ public device_slot_card_interface
+{
+public:
+ virtual uint16_t get_jumpers() const = 0;
+ virtual uint16_t input_r() const = 0;
+ virtual uint8_t ext_status_r() const = 0;
+ virtual void output_w(uint16_t data) = 0;
+ virtual void ext_control_w(uint8_t data) = 0;
+ virtual DECLARE_WRITE_LINE_MEMBER(pctl_w) = 0;
+ virtual DECLARE_WRITE_LINE_MEMBER(io_w) = 0;
+ virtual DECLARE_WRITE_LINE_MEMBER(preset_w) = 0;
+
+protected:
+ // construction/destruction
+ hp98032_gpio_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp98032_gpio_card_device();
+
+ DECLARE_WRITE_LINE_MEMBER(pflg_w);
+ DECLARE_WRITE_LINE_MEMBER(psts_w);
+ DECLARE_WRITE_LINE_MEMBER(eir_w);
+};
+
+// GPIO loopback connector for HP98032
+class hp98032_gpio_loopback_device : public hp98032_gpio_card_device
+{
+public:
+ // construction/destruction
+ hp98032_gpio_loopback_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ virtual ~hp98032_gpio_loopback_device();
+
+ virtual uint16_t get_jumpers() const override;
+ virtual uint16_t input_r() const override;
+ virtual uint8_t ext_status_r() const override;
+ virtual void output_w(uint16_t data) override;
+ virtual void ext_control_w(uint8_t data) override;
+ virtual DECLARE_WRITE_LINE_MEMBER(pctl_w) override;
+ virtual DECLARE_WRITE_LINE_MEMBER(io_w) override;
+ virtual DECLARE_WRITE_LINE_MEMBER(preset_w) override;
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+private:
+ uint16_t m_output;
+ uint8_t m_ext_control;
+ bool m_io;
+};
+
+// device type definitions
+DECLARE_DEVICE_TYPE(HP98032_IO_CARD, hp98032_io_card_device)
+DECLARE_DEVICE_TYPE(HP98032_GPIO_SLOT , hp98032_gpio_slot_device)
+DECLARE_DEVICE_TYPE(HP98032_GPIO_LOOPBACK , hp98032_gpio_loopback_device)
+
+#endif // MAME_BUS_HP9845_IO_98032_H
diff --git a/src/devices/bus/hp9845_io/hp9845_io.cpp b/src/devices/bus/hp9845_io/hp9845_io.cpp
index 61e4a90d721..a6a21015d25 100644
--- a/src/devices/bus/hp9845_io/hp9845_io.cpp
+++ b/src/devices/bus/hp9845_io/hp9845_io.cpp
@@ -4,15 +4,18 @@
hp9845_io.cpp
- I/O bus of HP9845 systems
+ I/O bus of HP9825/HP9845 systems
*********************************************************************/
#include "emu.h"
#include "hp9845_io.h"
+#include "98032.h"
+#include "98035.h"
+#include "98034.h"
// device type definition
-DEFINE_DEVICE_TYPE(HP9845_IO_SLOT, hp9845_io_slot_device, "hp9845_io_slot", "HP9845 I/O Slot")
+DEFINE_DEVICE_TYPE(HP9845_IO_SLOT, hp9845_io_slot_device, "hp98x5_io_slot", "HP98x5 I/O Slot")
// +---------------------+
// |hp9845_io_slot_device|
@@ -22,8 +25,15 @@ hp9845_io_slot_device::hp9845_io_slot_device(const machine_config &mconfig, cons
device_slot_interface(mconfig, *this),
m_irq_cb_func(*this),
m_sts_cb_func(*this),
- m_flg_cb_func(*this)
+ m_flg_cb_func(*this),
+ m_dmar_cb_func(*this)
{
+ option_reset();
+ option_add("98032_gpio" , HP98032_IO_CARD);
+ option_add("98034_hpib" , HP98034_IO_CARD);
+ option_add("98035_rtc" , HP98035_IO_CARD);
+ set_default_option(nullptr);
+ set_fixed(false);
}
hp9845_io_slot_device::~hp9845_io_slot_device()
@@ -35,6 +45,7 @@ void hp9845_io_slot_device::device_start()
m_irq_cb_func.resolve_safe();
m_sts_cb_func.resolve_safe();
m_flg_cb_func.resolve_safe();
+ m_dmar_cb_func.resolve_safe();
hp9845_io_card_device *card = dynamic_cast<hp9845_io_card_device*>(get_card_device());
@@ -43,19 +54,24 @@ void hp9845_io_slot_device::device_start()
}
}
-void hp9845_io_slot_device::irq_w(uint8_t sc , int state)
+WRITE_LINE_MEMBER(hp9845_io_slot_device::irq_w)
{
- m_irq_cb_func(sc , state , 0xff);
+ m_irq_cb_func(state);
}
-void hp9845_io_slot_device::sts_w(uint8_t sc , int state)
+WRITE_LINE_MEMBER(hp9845_io_slot_device::sts_w)
{
- m_sts_cb_func(sc , state , 0xff);
+ m_sts_cb_func(state);
}
-void hp9845_io_slot_device::flg_w(uint8_t sc , int state)
+WRITE_LINE_MEMBER(hp9845_io_slot_device::flg_w)
{
- m_flg_cb_func(sc , state , 0xff);
+ m_flg_cb_func(state);
+}
+
+WRITE_LINE_MEMBER(hp9845_io_slot_device::dmar_w)
+{
+ m_dmar_cb_func(state);
}
int hp9845_io_slot_device::get_rw_handlers(read16_delegate& rhandler , write16_delegate& whandler)
@@ -88,8 +104,7 @@ hp9845_io_card_device::hp9845_io_card_device(const machine_config &mconfig, devi
device_t(mconfig, type, tag, owner, clock),
device_slot_card_interface(mconfig, *this),
m_slot_dev(nullptr),
- m_select_code_port(*this , "SC"),
- m_my_sc(0)
+ m_select_code_port(*this , "SC")
{
}
@@ -97,37 +112,30 @@ hp9845_io_card_device::~hp9845_io_card_device()
{
}
-void hp9845_io_card_device::device_reset()
-{
- m_my_sc = get_sc();
-}
-
-void hp9845_io_card_device::irq_w(int state)
+WRITE_LINE_MEMBER(hp9845_io_card_device::irq_w)
{
if (m_slot_dev) {
- m_slot_dev->irq_w(m_my_sc , state);
+ m_slot_dev->irq_w(state);
}
}
-void hp9845_io_card_device::sts_w(int state)
+WRITE_LINE_MEMBER(hp9845_io_card_device::sts_w)
{
if (m_slot_dev) {
- m_slot_dev->sts_w(m_my_sc , state);
+ m_slot_dev->sts_w(state);
}
}
-void hp9845_io_card_device::flg_w(int state)
+WRITE_LINE_MEMBER(hp9845_io_card_device::flg_w)
{
if (m_slot_dev) {
- m_slot_dev->flg_w(m_my_sc , state);
+ m_slot_dev->flg_w(state);
}
}
-#include "98035.h"
-#include "98034.h"
-
-void hp9845_io_slot_devices(device_slot_interface &device)
+WRITE_LINE_MEMBER(hp9845_io_card_device::dmar_w)
{
- device.option_add("98034_hpib" , HP98034_IO_CARD);
- device.option_add("98035_rtc" , HP98035_IO_CARD);
+ if (m_slot_dev) {
+ m_slot_dev->dmar_w(state);
+ }
}
diff --git a/src/devices/bus/hp9845_io/hp9845_io.h b/src/devices/bus/hp9845_io/hp9845_io.h
index 4f18ab75939..7252ac25520 100644
--- a/src/devices/bus/hp9845_io/hp9845_io.h
+++ b/src/devices/bus/hp9845_io/hp9845_io.h
@@ -4,7 +4,7 @@
hp9845_io.h
- I/O bus of HP9845 systems
+ I/O bus of HP9825/HP9845 systems
*********************************************************************/
@@ -13,20 +13,6 @@
#pragma once
-
-#define MCFG_HP9845_IO_SLOT_ADD(_tag) \
- MCFG_DEVICE_ADD(_tag, HP9845_IO_SLOT, 0) \
- MCFG_DEVICE_SLOT_INTERFACE(hp9845_io_slot_devices, nullptr, false)
-
-#define MCFG_HP9845_IO_IRQ_CB(_devcb) \
- downcast<hp9845_io_slot_device &>(*device).set_irq_cb_func(DEVCB_##_devcb);
-
-#define MCFG_HP9845_IO_STS_CB(_devcb) \
- downcast<hp9845_io_slot_device &>(*device).set_sts_cb_func(DEVCB_##_devcb);
-
-#define MCFG_HP9845_IO_FLG_CB(_devcb) \
- downcast<hp9845_io_slot_device &>(*device).set_flg_cb_func(DEVCB_##_devcb);
-
#define HP9845_IO_FIRST_SC 1 // Lowest SC used by I/O cards
#define MCFG_HP9845_IO_SC(_default_sc) \
@@ -57,23 +43,26 @@ public:
virtual void device_start() override;
// Callback setups
- template <class Object> devcb_base &set_irq_cb_func(Object &&cb) { return m_irq_cb_func.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_sts_cb_func(Object &&cb) { return m_sts_cb_func.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_flg_cb_func(Object &&cb) { return m_flg_cb_func.set_callback(std::forward<Object>(cb)); }
+ auto irq() { return m_irq_cb_func.bind(); }
+ auto sts() { return m_sts_cb_func.bind(); }
+ auto flg() { return m_flg_cb_func.bind(); }
+ auto dmar() { return m_dmar_cb_func.bind(); }
- // irq/sts/flg signal handlers
- void irq_w(uint8_t sc , int state);
- void sts_w(uint8_t sc , int state);
- void flg_w(uint8_t sc , int state);
+ // irq/sts/flg/dmar signal handlers for card devices
+ DECLARE_WRITE_LINE_MEMBER(irq_w);
+ DECLARE_WRITE_LINE_MEMBER(sts_w);
+ DECLARE_WRITE_LINE_MEMBER(flg_w);
+ DECLARE_WRITE_LINE_MEMBER(dmar_w);
// getter for r/w handlers
// return value is SC (negative if no card is attached to slot)
int get_rw_handlers(read16_delegate& rhandler , write16_delegate& whandler);
private:
- devcb_write8 m_irq_cb_func;
- devcb_write8 m_sts_cb_func;
- devcb_write8 m_flg_cb_func;
+ devcb_write_line m_irq_cb_func;
+ devcb_write_line m_sts_cb_func;
+ devcb_write_line m_flg_cb_func;
+ devcb_write_line m_dmar_cb_func;
};
class hp9845_io_card_device : public device_t,
@@ -93,22 +82,17 @@ protected:
hp9845_io_card_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual ~hp9845_io_card_device();
- // device-level overrides
- virtual void device_reset() override;
-
hp9845_io_slot_device *m_slot_dev;
required_ioport m_select_code_port;
- uint8_t m_my_sc;
// card device handling
- void irq_w(int state);
- void sts_w(int state);
- void flg_w(int state);
+ DECLARE_WRITE_LINE_MEMBER(irq_w);
+ DECLARE_WRITE_LINE_MEMBER(sts_w);
+ DECLARE_WRITE_LINE_MEMBER(flg_w);
+ DECLARE_WRITE_LINE_MEMBER(dmar_w);
};
// device type definition
DECLARE_DEVICE_TYPE(HP9845_IO_SLOT, hp9845_io_slot_device)
-void hp9845_io_slot_devices(device_slot_interface &device);
-
#endif // MAME_BUS_HP9845_IO_HP9845_IO_H
diff --git a/src/mame/drivers/hp9825.cpp b/src/mame/drivers/hp9825.cpp
index 792e241c5b6..d639714e1ec 100644
--- a/src/mame/drivers/hp9825.cpp
+++ b/src/mame/drivers/hp9825.cpp
@@ -29,6 +29,8 @@
#include "cpu/hphybrid/hphybrid.h"
#include "machine/timer.h"
#include "machine/hp9825_tape.h"
+#include "machine/hp98x5_io_sys.h"
+#include "bus/hp9845_io/hp9845_io.h"
#include "imagedev/bitbngr.h"
#include "speaker.h"
#include "sound/beep.h"
@@ -43,6 +45,8 @@ constexpr unsigned KDP_CLOCK = MAIN_CLOCK / 4;
// Peripheral Addresses (PA)
constexpr uint8_t KDP_PA = 0;
constexpr uint8_t TAPE_PA = 1;
+constexpr uint8_t IO_SLOT_FIRST_PA = 2;
+constexpr uint8_t IO_SLOT_LAST_PA = 15;
// KDP clocks to print 1 line of dots (~33 ms)
// This value is semi-guessed.
@@ -77,6 +81,7 @@ public:
hp9825_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_cpu(*this , "cpu")
+ , m_io_sys(*this , "io_sys")
, m_cursor_timer(*this , "cursor_timer")
, m_tape(*this , "tape")
, m_io_key(*this , "KEY%u" , 0)
@@ -86,6 +91,7 @@ public:
, m_prt_timer(*this , "prt_timer")
, m_beeper(*this , "beeper")
, m_beep_timer(*this , "beep_timer")
+ , m_io_slot(*this, "slot%u", 0U)
, m_display(*this , "char_%u_%u" , 0U , 0U)
, m_run_light(*this , "run_light")
{
@@ -95,10 +101,12 @@ public:
protected:
virtual void machine_start() override;
+ virtual void device_reset() override;
virtual void machine_reset() override;
private:
required_device<hp_09825_67907_cpu_device> m_cpu;
+ required_device<hp98x5_io_sys_device> m_io_sys;
required_device<timer_device> m_cursor_timer;
required_device<hp9825_tape_device> m_tape;
required_ioport_array<4> m_io_key;
@@ -108,6 +116,7 @@ private:
required_device<timer_device> m_prt_timer;
required_device<beep_device> m_beeper;
required_device<timer_device> m_beep_timer;
+ required_device_array<hp9845_io_slot_device , 3> m_io_slot;
output_finder<32 , 7> m_display;
output_finder<> m_run_light;
@@ -121,16 +130,12 @@ private:
bool m_key_pressed;
bool m_autorepeating;
unsigned m_autorepeat_cnt;
- uint8_t m_irl_pending;
- uint8_t m_irh_pending;
- // FLG/STS handling
- uint8_t m_pa;
- uint16_t m_flg_status;
- uint16_t m_sts_status;
// Printer
uint8_t m_printer_mem[ 16 ];
uint8_t m_printer_idx;
unsigned m_printer_line; // 0: printer idle, 1..10: line being printed
+ // SC of slots
+ int m_slot_sc[ 3 ];
void cpu_io_map(address_map &map);
void cpu_mem_map(address_map &map);
@@ -146,18 +151,15 @@ private:
void kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx);
TIMER_DEVICE_CALLBACK_MEMBER(kb_scan);
- IRQ_CALLBACK_MEMBER(irq_callback);
- void update_irq();
- void set_irq(uint8_t sc , int state);
-
- DECLARE_WRITE8_MEMBER(pa_w);
- void update_flg_sts();
- void set_sts(uint8_t sc , int state);
- void set_flg(uint8_t sc , int state);
-
TIMER_DEVICE_CALLBACK_MEMBER(prt_timer);
TIMER_DEVICE_CALLBACK_MEMBER(beep_timer);
+
+ // Slot handling
+ void set_irq_slot(unsigned slot , int state);
+ void set_sts_slot(unsigned slot , int state);
+ void set_flg_slot(unsigned slot , int state);
+ void set_dmar_slot(unsigned slot , int state);
};
void hp9825_state::machine_start()
@@ -169,8 +171,26 @@ void hp9825_state::machine_start()
save_item(NAME(m_display_mem));
save_item(NAME(m_display_idx));
save_item(NAME(m_scancode));
- save_item(NAME(m_irl_pending));
- save_item(NAME(m_irh_pending));
+}
+
+void hp9825_state::device_reset()
+{
+ // First, unmap every r/w handler in 1..12 select codes
+ for (unsigned sc = IO_SLOT_FIRST_PA; sc < (IO_SLOT_LAST_PA + 1); sc++) {
+ m_cpu->space(AS_IO).unmap_readwrite(sc * 4 , sc * 4 + 3);
+ }
+
+ // Then, set r/w handlers of all installed I/O cards
+ int sc;
+ read16_delegate rhandler;
+ write16_delegate whandler;
+ for (unsigned i = 0; i < 3; i++) {
+ if ((sc = m_io_slot[ i ]->get_rw_handlers(rhandler , whandler)) >= 0) {
+ logerror("Install R/W handlers for slot %u @ SC = %d\n", i, sc);
+ m_cpu->space(AS_IO).install_readwrite_handler(sc * 4 , sc * 4 + 3 , rhandler , whandler);
+ }
+ m_slot_sc[ i ] = sc;
+ }
}
void hp9825_state::machine_reset()
@@ -185,12 +205,6 @@ void hp9825_state::machine_reset()
m_key_pressed = false;
m_autorepeating = false;
m_autorepeat_cnt = 0;
- m_irl_pending = 0;
- m_irh_pending = 0;
- update_irq();
- m_pa = 0;
- m_flg_status = 0;
- m_sts_status = 0;
m_printer_idx = 0;
m_printer_line = 0;
m_prt_timer->reset();
@@ -223,7 +237,7 @@ READ16_MEMBER(hp9825_state::kb_scancode_r)
if (m_shift_key->read()) {
BIT_SET(res , 7);
}
- set_irq(KDP_PA , false);
+ m_io_sys->set_irq(KDP_PA , false);
return res;
}
@@ -242,7 +256,7 @@ WRITE16_MEMBER(hp9825_state::disp_w)
READ16_MEMBER(hp9825_state::kdp_status_r)
{
uint16_t res = 8;
- if (BIT(m_irl_pending, KDP_PA)) {
+ if (m_io_sys->is_irq_pending(KDP_PA)) {
BIT_SET(res , 4);
}
if (m_printer_line) {
@@ -504,7 +518,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::kb_scan)
if (max_seq_len) {
m_scancode = max_seq_idx;
m_key_pressed = true;
- set_irq(KDP_PA , true);
+ m_io_sys->set_irq(KDP_PA , true);
}
}
@@ -518,7 +532,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::kb_scan)
}
if (m_autorepeating && BIT(~prev_cnt & m_autorepeat_cnt , 3)) {
// Repeat key every time bit 3 of autorepeat counter goes 0->1
- set_irq(KDP_PA , true);
+ m_io_sys->set_irq(KDP_PA , true);
}
} else {
m_autorepeating = false;
@@ -540,79 +554,6 @@ void hp9825_state::kb_scan_ioport(ioport_value pressed , ioport_port &port , uns
}
}
-IRQ_CALLBACK_MEMBER(hp9825_state::irq_callback)
-{
- if (irqline == HPHYBRID_IRL) {
- return m_irl_pending;
- } else {
- return m_irh_pending;
- }
-}
-
-void hp9825_state::update_irq()
-{
- m_cpu->set_input_line(HPHYBRID_IRL , m_irl_pending != 0);
- m_cpu->set_input_line(HPHYBRID_IRH , m_irh_pending != 0);
-}
-
-void hp9825_state::set_irq(uint8_t sc , int state)
-{
- unsigned bit_n = sc % 8;
-
- if (sc < 8) {
- if (state) {
- BIT_SET(m_irl_pending, bit_n);
- } else {
- BIT_CLR(m_irl_pending, bit_n);
- }
- } else {
- if (state) {
- BIT_SET(m_irh_pending, bit_n);
- } else {
- BIT_CLR(m_irh_pending, bit_n);
- }
- }
- update_irq();
-}
-
-WRITE8_MEMBER(hp9825_state::pa_w)
-{
- m_pa = data;
- update_flg_sts();
-}
-
-void hp9825_state::update_flg_sts()
-{
- bool sts = BIT(m_sts_status , m_pa);
- bool flg = BIT(m_flg_status , m_pa);
- m_cpu->status_w(sts);
- m_cpu->flag_w(flg);
-}
-
-void hp9825_state::set_sts(uint8_t sc , int state)
-{
- if (state) {
- BIT_SET(m_sts_status, sc);
- } else {
- BIT_CLR(m_sts_status, sc);
- }
- if (sc == m_pa) {
- update_flg_sts();
- }
-}
-
-void hp9825_state::set_flg(uint8_t sc , int state)
-{
- if (state) {
- BIT_SET(m_flg_status, sc);
- } else {
- BIT_CLR(m_flg_status, sc);
- }
- if (sc == m_pa) {
- update_flg_sts();
- }
-}
-
TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::prt_timer)
{
if (m_printer_line == 1 || m_printer_line == 9 || m_printer_line == 10) {
@@ -644,6 +585,34 @@ TIMER_DEVICE_CALLBACK_MEMBER(hp9825_state::beep_timer)
m_beeper->set_state(0);
}
+void hp9825_state::set_irq_slot(unsigned slot , int state)
+{
+ int sc = m_slot_sc[ slot ];
+ assert(sc >= 0);
+ m_io_sys->set_irq(uint8_t(sc) , state);
+}
+
+void hp9825_state::set_sts_slot(unsigned slot , int state)
+{
+ int sc = m_slot_sc[ slot ];
+ assert(sc >= 0);
+ m_io_sys->set_sts(uint8_t(sc) , state);
+}
+
+void hp9825_state::set_flg_slot(unsigned slot , int state)
+{
+ int sc = m_slot_sc[ slot ];
+ assert(sc >= 0);
+ m_io_sys->set_flg(uint8_t(sc) , state);
+}
+
+void hp9825_state::set_dmar_slot(unsigned slot , int state)
+{
+ int sc = m_slot_sc[ slot ];
+ assert(sc >= 0);
+ m_io_sys->set_dmar(uint8_t(sc) , state);
+}
+
MACHINE_CONFIG_START(hp9825_state::hp9825b)
HP_09825_67907(config , m_cpu , MAIN_CLOCK);
// Just guessing... settings borrowed from hp9845
@@ -651,8 +620,18 @@ MACHINE_CONFIG_START(hp9825_state::hp9825b)
m_cpu->set_relative_mode(false);
m_cpu->set_addrmap(AS_PROGRAM , &hp9825_state::cpu_mem_map);
m_cpu->set_addrmap(AS_IO , &hp9825_state::cpu_io_map);
- m_cpu->set_irq_acknowledge_callback(FUNC(hp9825_state::irq_callback));
- m_cpu->pa_changed_cb().set(FUNC(hp9825_state::pa_w));
+ m_cpu->set_irq_acknowledge_callback("io_sys" , FUNC(hp98x5_io_sys_device::irq_callback));
+ m_cpu->pa_changed_cb().set(m_io_sys , FUNC(hp98x5_io_sys_device::pa_w));
+
+ // Needed when 98035 RTC module is connected or time advances at about 1/4 the correct speed (NP misses a lot of 1kHz interrupts)
+ MCFG_QUANTUM_TIME(attotime::from_hz(5000));
+
+ HP98X5_IO_SYS(config , m_io_sys , 0);
+ m_io_sys->irl().set([this](int state) { m_cpu->set_input_line(HPHYBRID_IRL , state); });
+ m_io_sys->irh().set([this](int state) { m_cpu->set_input_line(HPHYBRID_IRH , state); });
+ m_io_sys->sts().set(m_cpu , FUNC(hp_09825_67907_cpu_device::status_w));
+ m_io_sys->flg().set(m_cpu , FUNC(hp_09825_67907_cpu_device::flag_w));
+ m_io_sys->dmar().set(m_cpu , FUNC(hp_09825_67907_cpu_device::dmar_w));
TIMER(config , m_cursor_timer , 0).configure_generic(timer_device::expired_delegate(FUNC(hp9825_state::cursor_blink) , this));
@@ -661,9 +640,9 @@ MACHINE_CONFIG_START(hp9825_state::hp9825b)
// Tape drive
HP9825_TAPE(config , m_tape , 0);
- m_tape->flg().set([this , sc = TAPE_PA](int state) { set_flg(sc , state); });
- m_tape->sts().set([this , sc = TAPE_PA](int state) { set_sts(sc , state); });
- m_tape->dmar().set(m_cpu , FUNC(hp_09825_67907_cpu_device::dmar_w));
+ m_tape->flg().set([this](int state) { m_io_sys->set_flg(TAPE_PA , state); });
+ m_tape->sts().set([this](int state) { m_io_sys->set_sts(TAPE_PA , state); });
+ m_tape->dmar().set([this](int state) { m_io_sys->set_dmar(TAPE_PA , state); });
// Printer
BITBANGER(config , m_prt_alpha_out , 0);
@@ -675,6 +654,16 @@ MACHINE_CONFIG_START(hp9825_state::hp9825b)
BEEP(config, m_beeper, BEEPER_FREQ).add_route(ALL_OUTPUTS, "mono", 1.00);
TIMER(config , m_beep_timer , 0).configure_generic(timer_device::expired_delegate(FUNC(hp9825_state::beep_timer) , this));
+ // I/O slots
+ for (unsigned slot = 0; slot < 3; slot++) {
+ auto& finder = m_io_slot[ slot ];
+ hp9845_io_slot_device& tmp( HP9845_IO_SLOT(config , finder , 0) );
+ tmp.irq().set([this , slot](int state) { set_irq_slot(slot , state); });
+ tmp.sts().set([this , slot](int state) { set_sts_slot(slot , state); });
+ tmp.flg().set([this , slot](int state) { set_flg_slot(slot , state); });
+ tmp.dmar().set([this , slot](int state) { set_dmar_slot(slot , state); });
+ }
+
config.set_default_layout(layout_hp9825);
MACHINE_CONFIG_END
diff --git a/src/mame/drivers/hp9845.cpp b/src/mame/drivers/hp9845.cpp
index 01c2caf375e..00a7b45d043 100644
--- a/src/mame/drivers/hp9845.cpp
+++ b/src/mame/drivers/hp9845.cpp
@@ -415,6 +415,7 @@ hp9845_base_state::hp9845_base_state(const machine_config &mconfig, device_type
driver_device(mconfig, type, tag),
m_lpu(*this, "lpu"),
m_ppu(*this, "ppu"),
+ m_io_sys(*this , "io_sys"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_gv_timer(*this, "gv_timer"),
@@ -465,17 +466,6 @@ void hp9845_base_state::machine_start()
void hp9845_base_state::device_reset()
{
- // FLG & STS are to be reset before sub-devices,
- // because the latter may set the former in their own reset functions
- m_flg_status = 0;
- m_sts_status = 0;
-}
-
-void hp9845_base_state::machine_reset()
-{
- m_lpu->halt_w(1);
- m_ppu->halt_w(0);
-
// First, unmap every r/w handler in 1..12 select codes
for (unsigned sc = IO_SLOT_FIRST_PA; sc < (IO_SLOT_LAST_PA + 1); sc++) {
m_ppu->space(AS_IO).unmap_readwrite(sc * 4 , sc * 4 + 3);
@@ -485,11 +475,19 @@ void hp9845_base_state::machine_reset()
int sc;
read16_delegate rhandler;
write16_delegate whandler;
- for (unsigned i = 0; 4 > i; ++i)
+ for (unsigned i = 0; 4 > i; ++i) {
if ((sc = m_io_slot[i]->get_rw_handlers(rhandler , whandler)) >= 0) {
logerror("Install R/W handlers for slot %u @ SC = %d\n", i, sc);
m_ppu->space(AS_IO).install_readwrite_handler(sc * 4 , sc * 4 + 3 , rhandler , whandler);
}
+ m_slot_sc[ i ] = sc;
+ }
+}
+
+void hp9845_base_state::machine_reset()
+{
+ m_lpu->halt_w(1);
+ m_ppu->halt_w(0);
// Some sensible defaults
m_video_load_mar = false;
@@ -502,11 +500,7 @@ void hp9845_base_state::machine_reset()
m_gv_int_en = false;
m_gv_dma_en = false;
- m_irl_pending = 0;
- m_irh_pending = 0;
- m_pa = 0;
-
- set_sts(GVIDEO_PA , true);
+ m_io_sys->set_sts(GVIDEO_PA , true);
memset(&m_kb_state[ 0 ] , 0 , sizeof(m_kb_state));
m_kb_scancode = 0x7f;
@@ -515,8 +509,6 @@ void hp9845_base_state::machine_reset()
m_beeper->set_state(0);
m_prt_irl = false;
-
- logerror("STS=%04x FLG=%04x\n" , m_sts_status , m_flg_status);
}
TIMER_DEVICE_CALLBACK_MEMBER(hp9845_base_state::gv_timer)
@@ -541,90 +533,6 @@ attotime hp9845_base_state::time_to_gv_mem_availability() const
}
}
-IRQ_CALLBACK_MEMBER(hp9845_base_state::irq_callback)
-{
- if (irqline == HPHYBRID_IRL) {
- //logerror("irq ack L %02x\n" , m_irl_pending);
- return m_irl_pending;
- } else {
- //logerror("irq ack H %02x\n" , m_irh_pending);
- return m_irh_pending;
- }
-}
-
-void hp9845_base_state::update_irq()
-{
- m_ppu->set_input_line(HPHYBRID_IRL , m_irl_pending != 0);
- m_ppu->set_input_line(HPHYBRID_IRH , m_irh_pending != 0);
-}
-
-WRITE8_MEMBER(hp9845_base_state::irq_w)
-{
- set_irq(uint8_t(offset) , data != 0);
-}
-
-void hp9845_base_state::set_irq(uint8_t sc , int state)
-{
- unsigned bit_n = sc % 8;
-
- if (sc < 8) {
- if (state) {
- BIT_SET(m_irl_pending, bit_n);
- } else {
- BIT_CLR(m_irl_pending, bit_n);
- }
- } else {
- if (state) {
- BIT_SET(m_irh_pending, bit_n);
- } else {
- BIT_CLR(m_irh_pending, bit_n);
- }
- }
- update_irq();
-}
-
-void hp9845_base_state::update_flg_sts()
-{
- bool sts = BIT(m_sts_status , m_pa);
- bool flg = BIT(m_flg_status , m_pa);
- m_ppu->status_w(sts);
- m_ppu->flag_w(flg);
-}
-
-WRITE8_MEMBER(hp9845_base_state::sts_w)
-{
- set_sts(uint8_t(offset) , data != 0);
-}
-
-void hp9845_base_state::set_sts(uint8_t sc , int state)
-{
- if (state) {
- BIT_SET(m_sts_status, sc);
- } else {
- BIT_CLR(m_sts_status, sc);
- }
- if (sc == m_pa) {
- update_flg_sts();
- }
-}
-
-WRITE8_MEMBER(hp9845_base_state::flg_w)
-{
- set_flg(uint8_t(offset) , data != 0);
-}
-
-void hp9845_base_state::set_flg(uint8_t sc , int state)
-{
- if (state) {
- BIT_SET(m_flg_status, sc);
- } else {
- BIT_CLR(m_flg_status, sc);
- }
- if (sc == m_pa) {
- update_flg_sts();
- }
-}
-
void hp9845_base_state::kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx)
{
while (pressed) {
@@ -697,7 +605,6 @@ TIMER_DEVICE_CALLBACK_MEMBER(hp9845_base_state::kb_scan)
if (max_seq_len) {
// Key pressed, store scancode & generate IRL
- //logerror("idx=%u msl=%d\n" , max_seq_idx , max_seq_len);
m_kb_scancode = max_seq_idx;
BIT_SET(m_kb_status, 0);
update_kb_prt_irq();
@@ -737,66 +644,46 @@ WRITE16_MEMBER(hp9845_base_state::kb_irq_clear_w)
void hp9845_base_state::update_kb_prt_irq()
{
bool state = BIT(m_kb_status , 0) || m_prt_irl;
- set_irq(0 , state);
-}
-
-TIMER_DEVICE_CALLBACK_MEMBER(hp9845_base_state::beeper_off)
-{
- m_beeper->set_state(0);
-}
-
-WRITE8_MEMBER(hp9845_base_state::pa_w)
-{
- if (data != m_pa) {
- m_pa = data;
- update_flg_sts();
- }
-}
-
-WRITE_LINE_MEMBER(hp9845_base_state::prt_irl_w)
-{
- m_prt_irl = state;
- update_kb_prt_irq();
-}
-
-WRITE_LINE_MEMBER(hp9845_base_state::prt_flg_w)
-{
- set_flg(PRINTER_PA , state);
-}
-
-WRITE_LINE_MEMBER(hp9845_base_state::prt_sts_w)
-{
- set_sts(PRINTER_PA , state);
+ m_io_sys->set_irq(0 , state);
}
-WRITE_LINE_MEMBER(hp9845_base_state::t14_irq_w)
+void hp9845_base_state::set_irq_slot(unsigned slot , int state)
{
- set_irq(T14_PA , state);
+ int sc = m_slot_sc[ slot ];
+ assert(sc >= 0);
+ m_io_sys->set_irq(uint8_t(sc) , state);
}
-WRITE_LINE_MEMBER(hp9845_base_state::t14_flg_w)
+void hp9845_base_state::set_sts_slot(unsigned slot , int state)
{
- set_flg(T14_PA , state);
+ int sc = m_slot_sc[ slot ];
+ assert(sc >= 0);
+ m_io_sys->set_sts(uint8_t(sc) , state);
}
-WRITE_LINE_MEMBER(hp9845_base_state::t14_sts_w)
+void hp9845_base_state::set_flg_slot(unsigned slot , int state)
{
- set_sts(T14_PA , state);
+ int sc = m_slot_sc[ slot ];
+ assert(sc >= 0);
+ m_io_sys->set_flg(uint8_t(sc) , state);
}
-WRITE_LINE_MEMBER(hp9845_base_state::t15_irq_w)
+void hp9845_base_state::set_dmar_slot(unsigned slot , int state)
{
- set_irq(T15_PA , state);
+ int sc = m_slot_sc[ slot ];
+ assert(sc >= 0);
+ m_io_sys->set_dmar(uint8_t(sc) , state);
}
-WRITE_LINE_MEMBER(hp9845_base_state::t15_flg_w)
+TIMER_DEVICE_CALLBACK_MEMBER(hp9845_base_state::beeper_off)
{
- set_flg(T15_PA , state);
+ m_beeper->set_state(0);
}
-WRITE_LINE_MEMBER(hp9845_base_state::t15_sts_w)
+WRITE_LINE_MEMBER(hp9845_base_state::prt_irl_w)
{
- set_sts(T15_PA , state);
+ m_prt_irl = state;
+ update_kb_prt_irq();
}
INPUT_CHANGED_MEMBER(hp9845_base_state::togglekey_changed)
@@ -1348,15 +1235,15 @@ void hp9845b_state::update_graphic_bits()
m_gv_fsm_state == GV_STAT_WAIT_DS_1 ||
m_gv_fsm_state == GV_STAT_WAIT_DS_2;
- set_flg(GVIDEO_PA , gv_ready);
+ m_io_sys->set_flg(GVIDEO_PA , gv_ready);
bool irq = m_gv_int_en && !m_gv_dma_en && gv_ready;
- set_irq(GVIDEO_PA , irq);
+ m_io_sys->set_irq(GVIDEO_PA , irq);
bool dmar = gv_ready && m_gv_dma_en;
- m_ppu->dmar_w(dmar);
+ m_io_sys->set_dmar(GVIDEO_PA , dmar);
}
// ***************
@@ -2775,15 +2662,15 @@ void hp9845c_state::update_graphic_bits()
m_gv_fsm_state == GV_STAT_WAIT_TRIG_1;
}
- set_flg(GVIDEO_PA , gv_ready);
+ m_io_sys->set_flg(GVIDEO_PA , gv_ready);
bool irq = m_gv_int_en && !m_gv_dma_en && gv_ready;
- set_irq(GVIDEO_PA , irq);
+ m_io_sys->set_irq(GVIDEO_PA , irq);
bool dmar = gv_ready && m_gv_dma_en;
- m_ppu->dmar_w(dmar);
+ m_io_sys->set_dmar(GVIDEO_PA , dmar);
}
void hp9845c_state::update_gcursor()
@@ -3621,15 +3508,15 @@ void hp9845t_state::update_graphic_bits()
// Fix for this problem is in commit 27004d00
// My apologies to Tony Duell for doubting at one point the correctness
// of his 98780A schematics.. :)
- set_flg(GVIDEO_PA , gv_ready);
+ m_io_sys->set_flg(GVIDEO_PA , gv_ready);
bool irq = m_gv_int_en && !m_gv_dma_en && gv_ready;
- set_irq(GVIDEO_PA , irq);
+ m_io_sys->set_irq(GVIDEO_PA , irq);
bool dmar = gv_ready && m_gv_dma_en;
- m_ppu->dmar_w(dmar);
+ m_io_sys->set_dmar(GVIDEO_PA , dmar);
}
void hp9845t_state::update_gcursor()
@@ -3730,10 +3617,10 @@ void hp9845_base_state::ppu_io_map(address_map &map)
map(HP_MAKE_IOADDR(GVIDEO_PA, 0), HP_MAKE_IOADDR(GVIDEO_PA, 3)).rw(FUNC(hp9845_base_state::graphic_r), FUNC(hp9845_base_state::graphic_w));
// PA = 14, IC = 0..3
// Left-hand side tape drive (T14)
- map(HP_MAKE_IOADDR(T14_PA, 0), HP_MAKE_IOADDR(T14_PA, 3)).rw("t14", FUNC(hp_taco_device::reg_r), FUNC(hp_taco_device::reg_w));
+ map(HP_MAKE_IOADDR(T14_PA, 0), HP_MAKE_IOADDR(T14_PA, 3)).rw(m_t14, FUNC(hp_taco_device::reg_r), FUNC(hp_taco_device::reg_w));
// PA = 15, IC = 0..3
// Right-hand side tape drive (T15)
- map(HP_MAKE_IOADDR(T15_PA, 0), HP_MAKE_IOADDR(T15_PA, 3)).rw("t15", FUNC(hp_taco_device::reg_r), FUNC(hp_taco_device::reg_w));
+ map(HP_MAKE_IOADDR(T15_PA, 0), HP_MAKE_IOADDR(T15_PA, 3)).rw(m_t15, FUNC(hp_taco_device::reg_r), FUNC(hp_taco_device::reg_w));
}
MACHINE_CONFIG_START(hp9845_base_state::hp9845_base)
@@ -3748,8 +3635,15 @@ MACHINE_CONFIG_START(hp9845_base_state::hp9845_base)
m_ppu->set_9845_boot_mode(true);
m_ppu->set_rw_cycles(6 , 6);
m_ppu->set_relative_mode(true);
- m_ppu->set_irq_acknowledge_callback(FUNC(hp9845_base_state::irq_callback));
- m_ppu->pa_changed_cb().set(FUNC(hp9845_base_state::pa_w));
+ m_ppu->set_irq_acknowledge_callback("io_sys" , FUNC(hp98x5_io_sys_device::irq_callback));
+ m_ppu->pa_changed_cb().set(m_io_sys , FUNC(hp98x5_io_sys_device::pa_w));
+
+ HP98X5_IO_SYS(config , m_io_sys , 0);
+ m_io_sys->irl().set([this](int state) { m_ppu->set_input_line(HPHYBRID_IRL , state); });
+ m_io_sys->irh().set([this](int state) { m_ppu->set_input_line(HPHYBRID_IRH , state); });
+ m_io_sys->sts().set(m_ppu , FUNC(hp_5061_3001_cpu_device::status_w));
+ m_io_sys->flg().set(m_ppu , FUNC(hp_5061_3001_cpu_device::flag_w));
+ m_io_sys->dmar().set(m_ppu , FUNC(hp_5061_3001_cpu_device::dmar_w));
// video hardware
MCFG_SCREEN_ADD("screen", RASTER)
@@ -3766,15 +3660,15 @@ MACHINE_CONFIG_START(hp9845_base_state::hp9845_base)
MCFG_TIMER_DRIVER_ADD("beep_timer" , hp9845_base_state , beeper_off);
- // Tape controller
- hp_taco_device &t15(HP_TACO(config , "t15" , 4000000));
- t15.irq().set(FUNC(hp9845_base_state::t15_irq_w));
- t15.flg().set(FUNC(hp9845_base_state::t15_flg_w));
- t15.sts().set(FUNC(hp9845_base_state::t15_sts_w));
- hp_taco_device &t14(HP_TACO(config , "t14" , 4000000));
- t14.irq().set(FUNC(hp9845_base_state::t14_irq_w));
- t14.flg().set(FUNC(hp9845_base_state::t14_flg_w));
- t14.sts().set(FUNC(hp9845_base_state::t14_sts_w));
+ // Tape drives
+ HP_TACO(config , m_t15 , 4000000);
+ m_t15->irq().set([this](int state) { m_io_sys->set_irq(T15_PA , state); });
+ m_t15->flg().set([this](int state) { m_io_sys->set_flg(T15_PA , state); });
+ m_t15->sts().set([this](int state) { m_io_sys->set_sts(T15_PA , state); });
+ HP_TACO(config , m_t14 , 4000000);
+ m_t14->irq().set([this](int state) { m_io_sys->set_irq(T14_PA , state); });
+ m_t14->flg().set([this](int state) { m_io_sys->set_flg(T14_PA , state); });
+ m_t14->sts().set([this](int state) { m_io_sys->set_sts(T14_PA , state); });
// In real machine there were 8 slots for LPU ROMs and 8 slots for PPU ROMs in
// right-hand side and left-hand side drawers, respectively.
@@ -3798,31 +3692,23 @@ MACHINE_CONFIG_START(hp9845_base_state::hp9845_base)
MCFG_DEVICE_SLOT_INTERFACE(hp_optrom_slot_devices, NULL, false)
// I/O slots
- MCFG_HP9845_IO_SLOT_ADD("slot0")
- MCFG_HP9845_IO_IRQ_CB(WRITE8(*this, hp9845_base_state , irq_w))
- MCFG_HP9845_IO_STS_CB(WRITE8(*this, hp9845_base_state , sts_w))
- MCFG_HP9845_IO_FLG_CB(WRITE8(*this, hp9845_base_state , flg_w))
- MCFG_HP9845_IO_SLOT_ADD("slot1")
- MCFG_HP9845_IO_IRQ_CB(WRITE8(*this, hp9845_base_state , irq_w))
- MCFG_HP9845_IO_STS_CB(WRITE8(*this, hp9845_base_state , sts_w))
- MCFG_HP9845_IO_FLG_CB(WRITE8(*this, hp9845_base_state , flg_w))
- MCFG_HP9845_IO_SLOT_ADD("slot2")
- MCFG_HP9845_IO_IRQ_CB(WRITE8(*this, hp9845_base_state , irq_w))
- MCFG_HP9845_IO_STS_CB(WRITE8(*this, hp9845_base_state , sts_w))
- MCFG_HP9845_IO_FLG_CB(WRITE8(*this, hp9845_base_state , flg_w))
- MCFG_HP9845_IO_SLOT_ADD("slot3")
- MCFG_HP9845_IO_IRQ_CB(WRITE8(*this, hp9845_base_state , irq_w))
- MCFG_HP9845_IO_STS_CB(WRITE8(*this, hp9845_base_state , sts_w))
- MCFG_HP9845_IO_FLG_CB(WRITE8(*this, hp9845_base_state , flg_w))
+ for (unsigned slot = 0; slot < 4; slot++) {
+ auto& finder = m_io_slot[ slot ];
+ hp9845_io_slot_device& tmp( HP9845_IO_SLOT(config , finder , 0) );
+ tmp.irq().set([this , slot](int state) { set_irq_slot(slot , state); });
+ tmp.sts().set([this , slot](int state) { set_sts_slot(slot , state); });
+ tmp.flg().set([this , slot](int state) { set_flg_slot(slot , state); });
+ tmp.dmar().set([this , slot](int state) { set_dmar_slot(slot , state); });
+ }
// LPU memory options
RAM(config, RAM_TAG).set_default_size("192K").set_extra_options("64K, 320K, 448K");
// Internal printer
- MCFG_DEVICE_ADD("printer" , HP9845_PRINTER , 0)
- MCFG_9845PRT_IRL_HANDLER(WRITELINE(*this, hp9845_base_state , prt_irl_w))
- MCFG_9845PRT_FLG_HANDLER(WRITELINE(*this, hp9845_base_state , prt_flg_w))
- MCFG_9845PRT_STS_HANDLER(WRITELINE(*this, hp9845_base_state , prt_sts_w))
+ hp9845_printer_device& prt{ HP9845_PRINTER(config , "printer" , 0) };
+ prt.irq().set(FUNC(hp9845_base_state::prt_irl_w));
+ prt.flg().set([this](int state) { m_io_sys->set_flg(PRINTER_PA , state); });
+ prt.sts().set([this](int state) { m_io_sys->set_sts(PRINTER_PA , state); });
MACHINE_CONFIG_END
MACHINE_CONFIG_START(hp9845b_state::hp9845b)
diff --git a/src/mame/includes/hp9845.h b/src/mame/includes/hp9845.h
index 18940182cd3..1be0c35adf1 100644
--- a/src/mame/includes/hp9845.h
+++ b/src/mame/includes/hp9845.h
@@ -16,6 +16,7 @@
#include "screen.h"
#include "machine/ram.h"
#include "machine/timer.h"
+#include "machine/hp98x5_io_sys.h"
class hp9845_base_state : public driver_device
{
@@ -26,8 +27,8 @@ public:
protected:
virtual void machine_start() override;
- virtual void machine_reset() override;
virtual void device_reset() override;
+ virtual void machine_reset() override;
TIMER_DEVICE_CALLBACK_MEMBER(gv_timer);
@@ -35,33 +36,13 @@ protected:
virtual DECLARE_WRITE16_MEMBER(graphic_w) = 0;
attotime time_to_gv_mem_availability() const;
- IRQ_CALLBACK_MEMBER(irq_callback);
- void update_irq();
- DECLARE_WRITE8_MEMBER(irq_w);
- void set_irq(uint8_t sc , int state);
- void update_flg_sts();
- DECLARE_WRITE8_MEMBER(sts_w);
- void set_sts(uint8_t sc , int state);
- DECLARE_WRITE8_MEMBER(flg_w);
- void set_flg(uint8_t sc , int state);
-
TIMER_DEVICE_CALLBACK_MEMBER(kb_scan);
DECLARE_READ16_MEMBER(kb_scancode_r);
DECLARE_READ16_MEMBER(kb_status_r);
DECLARE_WRITE16_MEMBER(kb_irq_clear_w);
TIMER_DEVICE_CALLBACK_MEMBER(beeper_off);
- DECLARE_WRITE8_MEMBER(pa_w);
-
DECLARE_WRITE_LINE_MEMBER(prt_irl_w);
- DECLARE_WRITE_LINE_MEMBER(prt_flg_w);
- DECLARE_WRITE_LINE_MEMBER(prt_sts_w);
- DECLARE_WRITE_LINE_MEMBER(t14_irq_w);
- DECLARE_WRITE_LINE_MEMBER(t14_flg_w);
- DECLARE_WRITE_LINE_MEMBER(t14_sts_w);
- DECLARE_WRITE_LINE_MEMBER(t15_irq_w);
- DECLARE_WRITE_LINE_MEMBER(t15_flg_w);
- DECLARE_WRITE_LINE_MEMBER(t15_sts_w);
void hp9845_base(machine_config &config);
void global_mem_map(address_map &map);
@@ -69,6 +50,7 @@ protected:
required_device<hp_5061_3001_cpu_device> m_lpu;
required_device<hp_5061_3001_cpu_device> m_ppu;
+ required_device<hp98x5_io_sys_device> m_io_sys;
required_device<screen_device> m_screen;
required_device<palette_device> m_palette;
required_device<timer_device> m_gv_timer;
@@ -88,6 +70,12 @@ protected:
void kb_scan_ioport(ioport_value pressed , ioport_port &port , unsigned idx_base , int& max_seq_len , unsigned& max_seq_idx);
void update_kb_prt_irq();
+ // Slot handling
+ void set_irq_slot(unsigned slot , int state);
+ void set_sts_slot(unsigned slot , int state);
+ void set_flg_slot(unsigned slot , int state);
+ void set_dmar_slot(unsigned slot , int state);
+
// Character generator
required_region_ptr<uint8_t> m_chargen;
@@ -134,15 +122,6 @@ protected:
bool m_gv_cursor_gc; // U8 (GS)
bool m_gv_cursor_fs; // U8 (GS)
- // Interrupt handling
- uint8_t m_irl_pending;
- uint8_t m_irh_pending;
-
- // FLG/STS handling
- uint8_t m_pa;
- uint16_t m_flg_status;
- uint16_t m_sts_status;
-
// State of keyboard
ioport_value m_kb_state[ 4 ];
uint8_t m_kb_scancode;
@@ -150,6 +129,9 @@ protected:
// Printer
bool m_prt_irl;
+
+ // SC of slots
+ int m_slot_sc[ 4 ];
};
#endif // MAME_INCLUDES_HP9845_H
diff --git a/src/mame/machine/hp9845_printer.h b/src/mame/machine/hp9845_printer.h
index c7752b24c03..1219a0af278 100644
--- a/src/mame/machine/hp9845_printer.h
+++ b/src/mame/machine/hp9845_printer.h
@@ -15,25 +15,16 @@
#include "imagedev/bitbngr.h"
-#define MCFG_9845PRT_IRL_HANDLER(_devcb) \
- downcast<hp9845_printer_device &>(*device).set_irl_handler(DEVCB_##_devcb);
-
-#define MCFG_9845PRT_FLG_HANDLER(_devcb) \
- downcast<hp9845_printer_device &>(*device).set_flg_handler(DEVCB_##_devcb);
-
-#define MCFG_9845PRT_STS_HANDLER(_devcb) \
- downcast<hp9845_printer_device &>(*device).set_sts_handler(DEVCB_##_devcb);
-
class hp9845_printer_device : public device_t
{
public:
// construction/destruction
hp9845_printer_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // configuration helpers
- template <class Object> devcb_base &set_irl_handler(Object &&cb) { return m_irl_handler.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_flg_handler(Object &&cb) { return m_flg_handler.set_callback(std::forward<Object>(cb)); }
- template <class Object> devcb_base &set_sts_handler(Object &&cb) { return m_sts_handler.set_callback(std::forward<Object>(cb)); }
+ // callbacks
+ auto irq() { return m_irl_handler.bind(); }
+ auto flg() { return m_flg_handler.bind(); }
+ auto sts() { return m_sts_handler.bind(); }
// device-level overrides
virtual const tiny_rom_entry *device_rom_region() const override;
diff --git a/src/mame/machine/hp98x5_io_sys.cpp b/src/mame/machine/hp98x5_io_sys.cpp
new file mode 100644
index 00000000000..855b48bc875
--- /dev/null
+++ b/src/mame/machine/hp98x5_io_sys.cpp
@@ -0,0 +1,154 @@
+// License:BSD-3-Clause
+// copyright-holders:F. Ulivi
+/*********************************************************************
+
+ hp98x5_io_sys.cpp
+
+ HP98x5 I/O sub-system
+
+*********************************************************************/
+
+#include "emu.h"
+#include "hp98x5_io_sys.h"
+#include "cpu/hphybrid/hphybrid.h"
+
+// Bit manipulation
+namespace {
+ template<typename T> constexpr T BIT_MASK(unsigned n)
+ {
+ return (T)1U << n;
+ }
+
+ template<typename T> void BIT_CLR(T& w , unsigned n)
+ {
+ w &= ~BIT_MASK<T>(n);
+ }
+
+ template<typename T> void BIT_SET(T& w , unsigned n)
+ {
+ w |= BIT_MASK<T>(n);
+ }
+}
+
+// Device type definition
+DEFINE_DEVICE_TYPE(HP98X5_IO_SYS, hp98x5_io_sys_device, "hp98x5_io_sys", "HP98x5 I/O sub-system")
+
+hp98x5_io_sys_device::hp98x5_io_sys_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+: device_t(mconfig , HP98X5_IO_SYS , tag , owner , clock)
+ , m_irl_handler(*this)
+ , m_irh_handler(*this)
+ , m_flg_handler(*this)
+ , m_sts_handler(*this)
+ , m_dmar_handler(*this)
+{
+}
+
+void hp98x5_io_sys_device::device_start()
+{
+ m_irl_handler.resolve_safe();
+ m_irh_handler.resolve_safe();
+ m_flg_handler.resolve_safe();
+ m_sts_handler.resolve_safe();
+ m_dmar_handler.resolve_safe();
+
+ save_item(NAME(m_irq_pending));
+ save_item(NAME(m_pa));
+ save_item(NAME(m_flg_status));
+ save_item(NAME(m_sts_status));
+ save_item(NAME(m_dmar_status));
+}
+
+void hp98x5_io_sys_device::device_reset()
+{
+ m_irq_pending = 0;
+ update_irq();
+ m_pa = 0;
+ m_flg_status = 0;
+ m_sts_status = 0;
+ update_flg_sts();
+ m_dmar_status = 0;
+ update_dmar();
+}
+
+IRQ_CALLBACK_MEMBER(hp98x5_io_sys_device::irq_callback)
+{
+ if (irqline == HPHYBRID_IRL) {
+ return m_irq_pending & 0xff;
+ } else {
+ return m_irq_pending >> 8;
+ }
+}
+
+WRITE8_MEMBER(hp98x5_io_sys_device::pa_w)
+{
+ m_pa = data;
+ update_flg_sts();
+}
+
+void hp98x5_io_sys_device::set_irq(uint8_t sc , int state)
+{
+ if (state) {
+ BIT_SET(m_irq_pending, sc);
+ } else {
+ BIT_CLR(m_irq_pending, sc);
+ }
+ update_irq();
+}
+
+void hp98x5_io_sys_device::set_sts(uint8_t sc , int state)
+{
+ if (state) {
+ BIT_SET(m_sts_status, sc);
+ } else {
+ BIT_CLR(m_sts_status, sc);
+ }
+ if (sc == m_pa) {
+ update_flg_sts();
+ }
+}
+
+void hp98x5_io_sys_device::set_flg(uint8_t sc , int state)
+{
+ if (state) {
+ BIT_SET(m_flg_status, sc);
+ } else {
+ BIT_CLR(m_flg_status, sc);
+ }
+ if (sc == m_pa) {
+ update_flg_sts();
+ }
+}
+
+void hp98x5_io_sys_device::set_dmar(uint8_t sc , int state)
+{
+ if (state) {
+ BIT_SET(m_dmar_status, sc);
+ } else {
+ BIT_CLR(m_dmar_status, sc);
+ }
+ update_dmar();
+}
+
+bool hp98x5_io_sys_device::is_irq_pending(uint8_t sc) const
+{
+ return BIT(m_irq_pending , sc);
+}
+
+void hp98x5_io_sys_device::update_irq()
+{
+ m_irl_handler((m_irq_pending & 0x00ff) != 0);
+ m_irh_handler((m_irq_pending & 0xff00) != 0);
+}
+
+void hp98x5_io_sys_device::update_flg_sts()
+{
+ bool sts = BIT(m_sts_status , m_pa);
+ bool flg = BIT(m_flg_status , m_pa);
+ m_sts_handler(sts);
+ m_flg_handler(flg);
+}
+
+void hp98x5_io_sys_device::update_dmar()
+{
+ m_dmar_handler(m_dmar_status != 0);
+}
diff --git a/src/mame/machine/hp98x5_io_sys.h b/src/mame/machine/hp98x5_io_sys.h
new file mode 100644
index 00000000000..3254393d80d
--- /dev/null
+++ b/src/mame/machine/hp98x5_io_sys.h
@@ -0,0 +1,67 @@
+// License:BSD-3-Clause
+// copyright-holders:F. Ulivi
+/*********************************************************************
+
+ hp98x5_io_sys.h
+
+ HP98x5 I/O sub-system
+
+*********************************************************************/
+
+#ifndef MAME_MACHINE_HP98X5_IO_SYS_H
+#define MAME_MACHINE_HP98X5_IO_SYS_H
+
+#pragma once
+
+class hp98x5_io_sys_device : public device_t
+{
+public:
+ // construction/destruction
+ hp98x5_io_sys_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ auto irl() { return m_irl_handler.bind(); }
+ auto irh() { return m_irh_handler.bind(); }
+ auto sts() { return m_sts_handler.bind(); }
+ auto flg() { return m_flg_handler.bind(); }
+ auto dmar() { return m_dmar_handler.bind(); }
+
+ IRQ_CALLBACK_MEMBER(irq_callback);
+ DECLARE_WRITE8_MEMBER(pa_w);
+
+ void set_irq(uint8_t sc , int state);
+ void set_sts(uint8_t sc , int state);
+ void set_flg(uint8_t sc , int state);
+ void set_dmar(uint8_t sc , int state);
+
+ bool is_irq_pending(uint8_t sc) const;
+private:
+ devcb_write_line m_irl_handler;
+ devcb_write_line m_irh_handler;
+ devcb_write_line m_flg_handler;
+ devcb_write_line m_sts_handler;
+ devcb_write_line m_dmar_handler;
+
+ // Interrupt handling
+ uint16_t m_irq_pending;
+
+ // FLG/STS handling
+ uint8_t m_pa;
+ uint16_t m_flg_status;
+ uint16_t m_sts_status;
+
+ // DMAR handling
+ uint16_t m_dmar_status;
+
+ void update_irq();
+ void update_flg_sts();
+ void update_dmar();
+};
+
+// device type definition
+DECLARE_DEVICE_TYPE(HP98X5_IO_SYS, hp98x5_io_sys_device)
+
+#endif // MAME_MACHINE_HP98X5_IO_SYS_H