From a7ee0a41e9bdbf267313ca1def3d923071aef6cf Mon Sep 17 00:00:00 2001 From: fulivi Date: Tue, 22 Nov 2016 09:51:28 +0100 Subject: [PATCH 1/2] hp9845: implemented 98034 module (HPIB interface) --- scripts/src/bus.lua | 5 +- src/devices/bus/hp9845_io/98034.cpp | 375 ++++++++++++++++++++++++ src/devices/bus/hp9845_io/98034.h | 85 ++++++ src/devices/bus/hp9845_io/98035.cpp | 2 +- src/devices/bus/hp9845_io/hp9845_io.cpp | 2 + src/devices/bus/hp9845_io/hp9845_io.h | 4 +- 6 files changed, 468 insertions(+), 5 deletions(-) create mode 100644 src/devices/bus/hp9845_io/98034.cpp create mode 100644 src/devices/bus/hp9845_io/98034.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 38fea58bf1f..30393418485 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -2919,8 +2919,9 @@ end if (BUSES["HP9845_IO"]~=null) then files { MAME_DIR .. "src/devices/bus/hp9845_io/hp9845_io.cpp", - MAME_DIR .. "src/devices/bus/hp9845_io/98035.cpp" - } + MAME_DIR .. "src/devices/bus/hp9845_io/98034.cpp", + MAME_DIR .. "src/devices/bus/hp9845_io/98035.cpp", + } end --------------------------------------------------- diff --git a/src/devices/bus/hp9845_io/98034.cpp b/src/devices/bus/hp9845_io/98034.cpp new file mode 100644 index 00000000000..9dfec3a35c5 --- /dev/null +++ b/src/devices/bus/hp9845_io/98034.cpp @@ -0,0 +1,375 @@ +// license:BSD-3-Clause +// copyright-holders: F. Ulivi +/********************************************************************* + + 98034.cpp + + 98034 module (HPIB interface) + + TODO: Implement Parallel Poll response + + The main reference for this module is: + HP 98034-90001, 98034 Installation and Service Manual + +*********************************************************************/ + +#include "98034.h" +#include "coreutil.h" + +// Debugging +#define VERBOSE 0 +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + +#define BIT_MASK(n) (1U << (n)) + +// Macros to clear/set single bits +#define BIT_CLR(w , n) ((w) &= ~BIT_MASK(n)) +#define BIT_SET(w , n) ((w) |= BIT_MASK(n)) + +hp98034_io_card::hp98034_io_card(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : hp9845_io_card_device(mconfig , HP98034_IO_CARD , "HP98034 card" , tag , owner , clock , "hp98034" , __FILE__), + m_cpu(*this , "np"), + m_sw1(*this , "sw1"), + m_ieee488(*this , IEEE488_TAG) +{ +} + +hp98034_io_card::~hp98034_io_card() +{ +} + +static INPUT_PORTS_START(hp98034_port) + MCFG_HP9845_IO_SC(7) + PORT_START("sw1") + PORT_DIPNAME(0x1f , 0x15 , "HPIB address") + PORT_DIPLOCATION("S1:1,2,3,4,5") + 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 , 0x00 , "Sys. controller") + PORT_DIPLOCATION("S1:6") + PORT_DIPSETTING(0x00 , DEF_STR(On)) + PORT_DIPSETTING(0x20 , DEF_STR(Off)) +INPUT_PORTS_END + +ioport_constructor hp98034_io_card::device_input_ports() const +{ + return INPUT_PORTS_NAME(hp98034_port); +} + +void hp98034_io_card::device_start() +{ + save_item(NAME(m_dc)); + save_item(NAME(m_idr)); + save_item(NAME(m_odr)); + save_item(NAME(m_force_flg)); + save_item(NAME(m_mode_reg)); + save_item(NAME(m_clr_hpib)); + save_item(NAME(m_ctrl_out)); + save_item(NAME(m_data_out)); +} + +void hp98034_io_card::device_reset() +{ + hp9845_io_card_device::device_reset(); + install_readwrite_handler(read16_delegate(FUNC(hp98034_io_card::reg_r) , this) , write16_delegate(FUNC(hp98034_io_card::reg_w) , this)); + + m_idr = 0; + m_odr = 0; + m_force_flg = false; + m_mode_reg = 0xff; + m_clr_hpib = false; + m_ctrl_out = 0; + m_data_out = 0; + update_dc(); +} + +READ16_MEMBER(hp98034_io_card::reg_r) +{ + uint16_t res = m_odr; + + if (offset == 1 || offset == 3) { + // Reading from R5 or R7 forces bits 4&5 to 1 + res |= 0x30; + } + + // Mode register + // Bits Value + // ========== + // 7-4 1 + // 3-2 ~offset + // 1-0 1 + m_mode_reg = (uint8_t)((offset << 2) ^ 0xff); + m_force_flg = true; + + update_flg(); + + LOG(("read R%u=%04x\n" , offset + 4 , res)); + return res; +} + +WRITE16_MEMBER(hp98034_io_card::reg_w) +{ + m_idr = (uint8_t)data; + + // Mode register + // Bits Value + // ========== + // 7-4 1 + // 3-2 ~offset + // 1 0 + // 0 1 + m_mode_reg = (uint8_t)((offset << 2) ^ 0xfd); + m_force_flg = true; + + update_flg(); + LOG(("write R%u=%04x\n" , offset + 4 , data)); +} + +WRITE8_MEMBER(hp98034_io_card::dc_w) +{ + if (data != m_dc) { + //LOG(("DC=%02x\n" , data)); + m_dc = data; + update_dc(); + } +} + +READ8_MEMBER(hp98034_io_card::dc_r) +{ + uint8_t res; + + if (m_force_flg) { + // Force DC3 low + res = 0xf7; + } else { + res = 0xff; + } + + return res; +} + +WRITE8_MEMBER(hp98034_io_card::hpib_data_w) +{ + m_data_out = data; + update_data_out(); +} + +WRITE8_MEMBER(hp98034_io_card::hpib_ctrl_w) +{ + m_ctrl_out = data; + update_ctrl_out(); +} + +READ8_MEMBER(hp98034_io_card::hpib_ctrl_r) +{ + uint8_t res = 0; + + if (!m_ieee488->dav_r()) { + BIT_SET(res , 0); + } + if (!m_ieee488->nrfd_r()) { + BIT_SET(res , 1); + } + if (!m_ieee488->ndac_r()) { + BIT_SET(res , 2); + } + if (!m_ieee488->ifc_r()) { + BIT_SET(res , 3); + } + if (!m_ieee488->atn_r()) { + BIT_SET(res , 4); + } + if (!m_ieee488->srq_r()) { + BIT_SET(res , 5); + } + if (!m_ieee488->ren_r()) { + BIT_SET(res , 6); + } + if (!m_ieee488->eoi_r()) { + BIT_SET(res , 7); + } + + return res; +} + +READ8_MEMBER(hp98034_io_card::hpib_data_r) +{ + return ~m_ieee488->dio_r(); +} + +READ8_MEMBER(hp98034_io_card::idr_r) +{ + return m_idr; +} + +WRITE8_MEMBER(hp98034_io_card::odr_w) +{ + m_odr = data; +} + +READ8_MEMBER(hp98034_io_card::mode_reg_r) +{ + return m_mode_reg; +} + +WRITE8_MEMBER(hp98034_io_card::mode_reg_clear_w) +{ + m_mode_reg = 0xff; + m_force_flg = false; + update_flg(); +} + +READ8_MEMBER(hp98034_io_card::switch_r) +{ + return m_sw1->read() | 0xc0; +} + +IRQ_CALLBACK_MEMBER(hp98034_io_card::irq_callback) +{ + int res = 0xff; + + if (irqline == 0 && !m_ieee488->ifc_r()) { + BIT_CLR(res, 1); + } + + return res; +} + +WRITE_LINE_MEMBER(hp98034_io_card::ieee488_ctrl_w) +{ + update_clr_hpib(); +} + +void hp98034_io_card::update_dc(void) +{ + irq_w(!BIT(m_dc , 0)); + sts_w(BIT(m_dc , 4)); + update_flg(); + update_clr_hpib(); +} + +void hp98034_io_card::update_flg(void) +{ + flg_w(BIT(m_dc , 3) && !m_force_flg); +} + +void hp98034_io_card::update_np_irq(void) +{ + m_cpu->set_input_line(0 , (!m_ieee488->ifc_r() || m_clr_hpib) && BIT(m_dc , HP_NANO_IE_DC)); +} + +void hp98034_io_card::update_data_out(void) +{ + if (m_clr_hpib) { + m_data_out = 0; + } + m_ieee488->dio_w(~m_data_out); +} + +void hp98034_io_card::update_ctrl_out(void) +{ + if (m_clr_hpib) { + m_ieee488->dav_w(1); + m_ieee488->nrfd_w(1); + m_ieee488->eoi_w(1); + m_ieee488->ndac_w(0); + } else { + m_ieee488->dav_w(BIT(m_dc , 2)); + m_ieee488->nrfd_w(BIT(m_dc , 1)); + m_ieee488->eoi_w(!BIT(m_ctrl_out , 4)); + m_ieee488->ndac_w(BIT(m_dc , 6)); + } + m_ieee488->srq_w(!BIT(m_ctrl_out , 0)); + m_ieee488->ren_w(!BIT(m_ctrl_out , 1)); + m_ieee488->atn_w(!BIT(m_ctrl_out , 2)); + m_ieee488->ifc_w(!BIT(m_ctrl_out , 3)); +} + +void hp98034_io_card::update_clr_hpib(void) +{ + m_clr_hpib = !m_ieee488->atn_r() && BIT(m_dc , 5); + update_data_out(); + update_ctrl_out(); + update_np_irq(); + LOG(("clr_hpib %d\n" , m_clr_hpib)); +} + +ROM_START(hp98034) + ROM_REGION(0x400 , "np" , 0) + ROM_LOAD("1816-1242.bin" , 0 , 0x400 , CRC(301a9f5f) SHA1(3d7c1ace38c4d3178fdbf764c044535d9f6ac94f)) +ROM_END + +static ADDRESS_MAP_START(np_program_map , AS_PROGRAM , 8 , hp98034_io_card) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0x000 , 0x3ff) AM_ROM AM_REGION("np" , 0) +ADDRESS_MAP_END + +static ADDRESS_MAP_START(np_io_map , AS_IO , 8 , hp98034_io_card) + ADDRESS_MAP_UNMAP_HIGH + AM_RANGE(0 , 0) AM_WRITE(hpib_data_w) + AM_RANGE(1 , 1) AM_WRITE(hpib_ctrl_w) + AM_RANGE(2 , 2) AM_READ(hpib_ctrl_r) + AM_RANGE(3 , 3) AM_READ(hpib_data_r) + AM_RANGE(4 , 4) AM_READ(idr_r) + AM_RANGE(5 , 5) AM_WRITE(odr_w) + AM_RANGE(6 , 6) AM_READWRITE(mode_reg_r , mode_reg_clear_w) + AM_RANGE(7 , 7) AM_READ(switch_r) +ADDRESS_MAP_END + +static MACHINE_CONFIG_FRAGMENT(hp98034) +// Clock for NP is generated by a RC oscillator. Manual says its typical frequency +// is around 2 MHz. + MCFG_CPU_ADD("np" , HP_NANOPROCESSOR , 2000000) + MCFG_CPU_PROGRAM_MAP(np_program_map) + MCFG_CPU_IO_MAP(np_io_map) + MCFG_HP_NANO_DC_CHANGED(WRITE8(hp98034_io_card , dc_w)) + MCFG_HP_NANO_READ_DC_CB(READ8(hp98034_io_card , dc_r)) + MCFG_CPU_IRQ_ACKNOWLEDGE_DRIVER(hp98034_io_card , irq_callback) + + MCFG_IEEE488_BUS_ADD() + MCFG_IEEE488_IFC_CALLBACK(WRITELINE(hp98034_io_card , ieee488_ctrl_w)) + MCFG_IEEE488_ATN_CALLBACK(WRITELINE(hp98034_io_card , ieee488_ctrl_w)) +MACHINE_CONFIG_END + +const tiny_rom_entry *hp98034_io_card::device_rom_region() const +{ + return ROM_NAME(hp98034); +} + +machine_config_constructor hp98034_io_card::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME(hp98034); +} + +// device type definition +const device_type HP98034_IO_CARD = &device_creator; diff --git a/src/devices/bus/hp9845_io/98034.h b/src/devices/bus/hp9845_io/98034.h new file mode 100644 index 00000000000..317259925b5 --- /dev/null +++ b/src/devices/bus/hp9845_io/98034.h @@ -0,0 +1,85 @@ +// license:BSD-3-Clause +// copyright-holders: F. Ulivi +/********************************************************************* + + 98034.h + + 98034 module (HPIB interface) + +*********************************************************************/ + +#pragma once + +#ifndef _98034_H_ +#define _98034_H_ + +#include "hp9845_io.h" +#include "cpu/nanoprocessor/nanoprocessor.h" +#include "bus/ieee488/ieee488.h" + +class hp98034_io_card : public hp9845_io_card_device +{ +public: + // construction/destruction + hp98034_io_card(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual ~hp98034_io_card(); + + // device-level overrides + virtual ioport_constructor device_input_ports() const override; + virtual void device_start() override; + virtual void device_reset() override; + virtual const tiny_rom_entry *device_rom_region() const override; + virtual machine_config_constructor device_mconfig_additions() const override; + + DECLARE_READ16_MEMBER(reg_r); + DECLARE_WRITE16_MEMBER(reg_w); + + DECLARE_WRITE8_MEMBER(dc_w); + DECLARE_READ8_MEMBER(dc_r); + + DECLARE_WRITE8_MEMBER(hpib_data_w); + DECLARE_WRITE8_MEMBER(hpib_ctrl_w); + DECLARE_READ8_MEMBER(hpib_ctrl_r); + DECLARE_READ8_MEMBER(hpib_data_r); + DECLARE_READ8_MEMBER(idr_r); + DECLARE_WRITE8_MEMBER(odr_w); + DECLARE_READ8_MEMBER(mode_reg_r); + DECLARE_WRITE8_MEMBER(mode_reg_clear_w); + DECLARE_READ8_MEMBER(switch_r); + + IRQ_CALLBACK_MEMBER(irq_callback); + + DECLARE_WRITE_LINE_MEMBER(ieee488_ctrl_w); + +private: + required_device m_cpu; + required_ioport m_sw1; + required_device m_ieee488; + + // DC lines + uint8_t m_dc; + + // Interface state + uint8_t m_idr; // Input Data Register + uint8_t m_odr; // Output Data Register + bool m_force_flg; + uint8_t m_mode_reg; + + // 488 bus state + bool m_clr_hpib; + uint8_t m_ctrl_out; + uint8_t m_data_out; + + void update_dc(void); + void update_flg(void); + void update_np_irq(void); + void update_data_out(void); + void update_ctrl_out(void); + void update_clr_hpib(void); + +}; + +// device type definition +extern const device_type HP98034_IO_CARD; + +#endif /* _98034_H_ */ diff --git a/src/devices/bus/hp9845_io/98035.cpp b/src/devices/bus/hp9845_io/98035.cpp index 28004e6d04f..7f5718b497c 100644 --- a/src/devices/bus/hp9845_io/98035.cpp +++ b/src/devices/bus/hp9845_io/98035.cpp @@ -153,7 +153,7 @@ hp98035_io_card::~hp98035_io_card() } static INPUT_PORTS_START(hp98035_port) - MCFG_HP9845_IO_SC + MCFG_HP9845_IO_SC(1) INPUT_PORTS_END ioport_constructor hp98035_io_card::device_input_ports() const diff --git a/src/devices/bus/hp9845_io/hp9845_io.cpp b/src/devices/bus/hp9845_io/hp9845_io.cpp index 1702c2ad4d6..9cbfceaf289 100644 --- a/src/devices/bus/hp9845_io/hp9845_io.cpp +++ b/src/devices/bus/hp9845_io/hp9845_io.cpp @@ -80,7 +80,9 @@ void hp9845_io_card_device::install_readwrite_handler(read16_delegate rhandler, } #include "98035.h" +#include "98034.h" SLOT_INTERFACE_START(hp9845_io_slot_devices) +SLOT_INTERFACE("98034_hpib" , HP98034_IO_CARD) SLOT_INTERFACE("98035_rtc" , HP98035_IO_CARD) SLOT_INTERFACE_END diff --git a/src/devices/bus/hp9845_io/hp9845_io.h b/src/devices/bus/hp9845_io/hp9845_io.h index a5c0f39b9b1..1c159fc862a 100644 --- a/src/devices/bus/hp9845_io/hp9845_io.h +++ b/src/devices/bus/hp9845_io/hp9845_io.h @@ -21,9 +21,9 @@ #define HP9845_IO_FIRST_SC 1 // Lowest SC used by I/O cards -#define MCFG_HP9845_IO_SC\ +#define MCFG_HP9845_IO_SC(_default_sc) \ PORT_START("SC") \ - PORT_CONFNAME(0xf , 0 , "Select Code") \ + PORT_CONFNAME(0xf , (_default_sc) - HP9845_IO_FIRST_SC , "Select Code") \ PORT_CONFSETTING(0 , "1")\ PORT_CONFSETTING(1 , "2")\ PORT_CONFSETTING(2 , "3")\ From 85aa483c376e3fe7ceaf1d64cdb6c170d222d7a7 Mon Sep 17 00:00:00 2001 From: fulivi Date: Tue, 22 Nov 2016 09:52:24 +0100 Subject: [PATCH 2/2] ieee488: a few optimizations to "state-changed" callbacks --- src/devices/bus/ieee488/ieee488.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/devices/bus/ieee488/ieee488.cpp b/src/devices/bus/ieee488/ieee488.cpp index 1b2f71c3f6a..385f3a8cd28 100644 --- a/src/devices/bus/ieee488/ieee488.cpp +++ b/src/devices/bus/ieee488/ieee488.cpp @@ -188,6 +188,7 @@ ieee488_device::daisy_entry::daisy_entry(device_t *device) void ieee488_device::set_signal(device_t *device, int signal, int state) { bool changed = false; + int old_state = get_signal(signal); if (device == this) { @@ -218,8 +219,13 @@ void ieee488_device::set_signal(device_t *device, int signal, int state) } } - if (changed) - { + if (!changed) { + return; + } + + state = get_signal(signal); + + if (old_state != state) { switch (signal) { case EOI: m_write_eoi(state); break; @@ -289,21 +295,18 @@ int ieee488_device::get_signal(int signal) { int state = m_line[signal]; - if (state) - { - daisy_entry *entry = m_device_list.first(); + daisy_entry *entry = m_device_list.first(); - while (entry) + while (state && entry) { if (!entry->m_line[signal]) - { - state = 0; - break; - } + { + state = 0; + break; + } entry = entry->next(); } - } return state; } @@ -352,7 +355,7 @@ uint8_t ieee488_device::get_data() daisy_entry *entry = m_device_list.first(); - while (entry) + while (data && entry) { data &= entry->m_dio;