diff options
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 |
commit | 72dc8609aa7670702b493330c4b0c0668b093d11 (patch) | |
tree | b9bf6131ef91807a96dc75a9ff7a8deb8342d234 | |
parent | 3530de78ccba7aa1328da19cca31c64fc5c7a81e (diff) |
hp9825 & hp9845: refactored I/O sub-system. Added 98032 GPIO module. (#4353)
-rw-r--r-- | scripts/src/bus.lua | 2 | ||||
-rw-r--r-- | scripts/target/mame/mess.lua | 2 | ||||
-rw-r--r-- | src/devices/bus/hp9845_io/98032.cpp | 569 | ||||
-rw-r--r-- | src/devices/bus/hp9845_io/98032.h | 192 | ||||
-rw-r--r-- | src/devices/bus/hp9845_io/hp9845_io.cpp | 64 | ||||
-rw-r--r-- | src/devices/bus/hp9845_io/hp9845_io.h | 52 | ||||
-rw-r--r-- | src/mame/drivers/hp9825.cpp | 199 | ||||
-rw-r--r-- | src/mame/drivers/hp9845.cpp | 262 | ||||
-rw-r--r-- | src/mame/includes/hp9845.h | 42 | ||||
-rw-r--r-- | src/mame/machine/hp9845_printer.h | 17 | ||||
-rw-r--r-- | src/mame/machine/hp98x5_io_sys.cpp | 154 | ||||
-rw-r--r-- | src/mame/machine/hp98x5_io_sys.h | 67 |
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 |