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