From 22ba8d40ddb2b1e61d812bf59a38d9f9c805299f Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sun, 17 Jun 2018 08:55:51 +0200 Subject: Add HP9122 floppy drive (#3657) * Revert "Revert "Add 9122c floppy (#3647)"" This reverts commit 0aa81fc184b225547091a10f4accb8f3ae7064da. * Address pull request comments Signed-off-by: Sven Schnelle * MR#3657: address comments Signed-off-by: Sven Schnelle * MR#3657: address MR comments Signed-off-by: Sven Schnelle * MR#3657: address MR comments Signed-off-by: Sven Schnelle --- scripts/src/bus.lua | 2 + scripts/src/machine.lua | 14 + src/devices/bus/ieee488/hp9122c.cpp | 383 ++++++++++++ src/devices/bus/ieee488/hp9122c.h | 151 +++++ src/devices/bus/ieee488/ieee488.cpp | 2 + src/devices/machine/i8291a.cpp | 1160 +++++++++++++++++++++++++++++++++++ src/devices/machine/i8291a.h | 408 ++++++++++++ src/mame/drivers/hp9k_3xx.cpp | 7 +- 8 files changed, 2124 insertions(+), 3 deletions(-) create mode 100644 src/devices/bus/ieee488/hp9122c.cpp create mode 100644 src/devices/bus/ieee488/hp9122c.h create mode 100644 src/devices/machine/i8291a.cpp create mode 100644 src/devices/machine/i8291a.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index f5be91e7475..c67ee9c9805 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -914,6 +914,8 @@ if (BUSES["IEEE488"]~=null) then MAME_DIR .. "src/devices/bus/ieee488/hardbox.h", MAME_DIR .. "src/devices/bus/ieee488/shark.cpp", MAME_DIR .. "src/devices/bus/ieee488/shark.h", + MAME_DIR .. "src/devices/bus/ieee488/hp9122c.cpp", + MAME_DIR .. "src/devices/bus/ieee488/hp9122c.h", MAME_DIR .. "src/devices/bus/ieee488/hp9895.cpp", MAME_DIR .. "src/devices/bus/ieee488/hp9895.h", MAME_DIR .. "src/devices/bus/ieee488/remote488.cpp", diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 0f8dc41aa06..204972c198e 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -3542,3 +3542,17 @@ if (MACHINES["Z80DAISY"]~=null) then MAME_DIR .. "src/devices/machine/z80daisy_generic.h", } end + +--------------------------------------------------- +-- +--@src/devices/machine/i8291a.h,MACHINES["I8291A"] = true +--------------------------------------------------- + +if (MACHINES["I8291A"]~=null) then + files { + MAME_DIR .. "src/devices/machine/i8291a.cpp", + MAME_DIR .. "src/devices/machine/i8291a.h", + } +end + + diff --git a/src/devices/bus/ieee488/hp9122c.cpp b/src/devices/bus/ieee488/hp9122c.cpp new file mode 100644 index 00000000000..94c52a7512f --- /dev/null +++ b/src/devices/bus/ieee488/hp9122c.cpp @@ -0,0 +1,383 @@ +// license:BSD-3-Clause +// copyright-holders: Sven Schnelle +/********************************************************************* + + hp9122c.cpp + + HP9122c dual floppy disk drive + +*********************************************************************/ + +#include "emu.h" +#include "hp9122c.h" +#include "cpu/m6809/m6809.h" +#include "machine/i8291a.h" +#include "machine/wd_fdc.h" + +DEFINE_DEVICE_TYPE(HP9122C, hp9122c_device, "hp9122c", "HP9122C Dual High density disk drive") + +hp9122c_device::hp9122c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t{mconfig, HP9122C, tag, owner, clock}, + device_ieee488_interface{mconfig, *this}, + m_cpu{*this , "cpu"}, + m_i8291a{*this, "i8291a"}, + m_fdc{*this, "mb8876"}, + m_floppy{*this, "floppy%u", 0}, + m_hpib_addr{*this , "ADDRESS"}, + m_testmode{*this, "TESTMODE"}, + m_intsel{3}, + m_fdc_irq{false}, + m_i8291a_irq{false}, + m_fdc_drq{false}, + m_i8291a_drq{false}, + m_cpuirq{false}, + m_cpufirq{false}, + m_index_int{false}, + m_ds0{false}, + m_ds1{false} +{ +} + +static INPUT_PORTS_START(hp9122c_port) + PORT_START("ADDRESS") + PORT_CONFNAME(0x1f, 0x00 , "HPIB address") + PORT_CONFSETTING(0, "0") + PORT_CONFSETTING(1, "1") + PORT_CONFSETTING(2, "2") + PORT_CONFSETTING(3, "3") + PORT_CONFSETTING(4, "4") + PORT_CONFSETTING(5, "5") + PORT_CONFSETTING(6, "6") + PORT_CONFSETTING(7, "7") + PORT_CONFSETTING(7, "8") + PORT_CONFSETTING(7, "9") + PORT_CONFSETTING(7, "10") + PORT_CONFSETTING(7, "11") + PORT_CONFSETTING(7, "12") + PORT_CONFSETTING(7, "13") + PORT_CONFSETTING(7, "14") + PORT_CONFSETTING(7, "15") + + PORT_START("TESTMODE") + PORT_CONFNAME(0x01, 0x00, "Testmode") + PORT_CONFSETTING(0, DEF_STR(Off)) + PORT_CONFSETTING(1, DEF_STR(On)) + +INPUT_PORTS_END + +ioport_constructor hp9122c_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(hp9122c_port); +} + +void hp9122c_device::device_start() +{ + for (auto &floppy : m_floppy) + floppy->get_device()->setup_index_pulse_cb(floppy_image_device::index_pulse_cb(&hp9122c_device::index_pulse_cb, this)); + + save_item(NAME(m_intsel)); + save_item(NAME(m_fdc_irq)); + save_item(NAME(m_fdc_drq)); + save_item(NAME(m_i8291a_irq)); + save_item(NAME(m_i8291a_drq)); + save_item(NAME(m_cpuirq)); + save_item(NAME(m_cpufirq)); + save_item(NAME(m_index_int)); + save_item(NAME(m_ds0)); + save_item(NAME(m_ds1)); +} + +void hp9122c_device::device_reset() +{ + m_fdc_irq = false; + m_fdc_drq = false; + m_i8291a_irq = false; + m_i8291a_drq = false; + m_cpuirq = false; + m_cpufirq = false; + m_ds0 = false; + m_ds1 = false; + m_index_int = false; +} + +void hp9122c_device::ieee488_eoi(int state) +{ + m_i8291a->eoi_w(state); +} + +void hp9122c_device::ieee488_dav(int state) +{ + m_i8291a->dav_w(state); +} + +void hp9122c_device::ieee488_nrfd(int state) +{ + m_i8291a->nrfd_w(state); +} + +void hp9122c_device::ieee488_ndac(int state) +{ + m_i8291a->ndac_w(state); +} + +void hp9122c_device::ieee488_ifc(int state) +{ + m_i8291a->ifc_w(state); +} + +void hp9122c_device::ieee488_srq(int state) +{ + m_i8291a->srq_w(state); +} + +void hp9122c_device::ieee488_atn(int state) +{ + m_i8291a->atn_w(state); +} + +void hp9122c_device::ieee488_ren(int state) +{ + m_i8291a->ren_w(state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_eoi_w) +{ + m_bus->eoi_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_dav_w) +{ + m_bus->dav_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_nrfd_w) +{ + m_bus->nrfd_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_ndac_w) +{ + m_bus->ndac_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_ifc_w) +{ + m_bus->ifc_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_srq_w) +{ + m_bus->srq_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_atn_w) +{ + m_bus->atn_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_ren_w) +{ + m_bus->ren_w(this, state); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_int_w) +{ + m_i8291a_irq = state; + update_intsel(); +} + +WRITE_LINE_MEMBER(hp9122c_device::i8291a_dreq_w) +{ + m_i8291a_drq = state; + update_intsel(); +} + +WRITE_LINE_MEMBER(hp9122c_device::fdc_intrq_w) +{ + m_fdc_irq = state; + update_intsel(); +} + +WRITE_LINE_MEMBER(hp9122c_device::fdc_drq_w) +{ + m_fdc_drq = state; + update_intsel(); +} + +void hp9122c_device::update_intsel() +{ + bool irq = false, firq = false; + + switch (m_intsel & 3) { + case 0: + /* fdc int connected */ + irq = m_fdc_drq; + firq = m_fdc_irq; + break; + case 1: + /* i8291a ints connected */ + irq = m_i8291a_drq; + firq = m_i8291a_irq; + break; + case 2: + irq = m_index_int; + firq = false; + break; + + case 3: + irq = false; + firq = false; + break; + } + + if (m_cpufirq != firq) + m_cpu->set_input_line(M6809_FIRQ_LINE, firq ? ASSERT_LINE : CLEAR_LINE); + + if (m_cpuirq != irq) + m_cpu->set_input_line(M6809_IRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE); + + m_cpuirq = irq; + m_cpufirq = firq; +} + +READ8_MEMBER(hp9122c_device::i8291a_dio_r) +{ + return m_bus->read_dio(); +} + +WRITE8_MEMBER(hp9122c_device::i8291a_dio_w) +{ + m_bus->dio_w(this, data); +} + +READ8_MEMBER(hp9122c_device::status_r) +{ + uint8_t ret = REG_STATUS_DUAL|REG_STATUS_DISKCHG; + auto addr = m_hpib_addr->read(); + + if (!m_testmode->read()) + ret |= 0x10; + + ret |= ((addr & 0x08) << 3) | (addr & 0x07); + + floppy_image_device *floppy = nullptr; + if (m_ds0) + floppy = m_floppy[0]->get_device(); + if (m_ds1) + floppy = m_floppy[1]->get_device(); + + if (floppy) { + auto variant = floppy->get_variant(); + if (variant == floppy_image::DSDD || variant == floppy_image::SSDD) + ret |= REG_STATUS_LOW_DENSITY; + } + + return ret; +} + +WRITE8_MEMBER(hp9122c_device::cmd_w) +{ + floppy_image_device *floppy0 = m_floppy[0]->get_device(); + floppy_image_device *floppy1 = m_floppy[1]->get_device(); + + m_ds0 = !(data & REG_CNTL_DS0) && floppy0; + m_ds1 = !(data & REG_CNTL_DS1) && floppy1; + + if (m_ds0) { + floppy0->mon_w(0); + floppy0->ss_w(!(data & REG_CNTL_HEADSEL)); + m_fdc->set_floppy(floppy0); + } else if (m_ds1) { + floppy1->mon_w(0); + floppy1->ss_w(!(data & REG_CNTL_HEADSEL)); + m_fdc->set_floppy(floppy1); + } + + if (data & REG_CNTL_CLOCK_SEL) + m_fdc->set_clock(XTAL(8'000'000)/4); + else + m_fdc->set_clock(XTAL(8'000'000)/8); + + m_intsel = ((data & REG_CNTL_INTSEL0) >> 7) | ((data & REG_CNTL_INTSEL1) >> 2); + update_intsel(); +} + +void hp9122c_device::index_pulse_cb(floppy_image_device *floppy, int state) +{ + m_fdc->index_callback(floppy, state); + + if (state) + m_index_int = true; + update_intsel(); + +} + +WRITE8_MEMBER(hp9122c_device::clridx_w) +{ + m_index_int = false; + update_intsel(); +} + +ROM_START(hp9122c) + ROM_REGION(0x4000 , "cpu" , 0) + ROM_LOAD("09122-15515.bin" , 0x0000, 0x4000 , CRC(d385e488) SHA1(93b2015037d76cc68b6252df03d6f184104605b9)) +ROM_END + +static void hp9122c_floppies(device_slot_interface &device) +{ + device.option_add("35dd" , FLOPPY_35_DD); + device.option_add("35hd" , FLOPPY_35_HD); +} + +static const floppy_format_type hp9122c_floppy_formats[] = { + FLOPPY_MFI_FORMAT, + FLOPPY_TD0_FORMAT, + nullptr +}; + +const tiny_rom_entry *hp9122c_device::device_rom_region() const +{ + return ROM_NAME(hp9122c); +} + +void hp9122c_device::cpu_map(address_map &map) +{ + map(0x0000, 0x0800).ram(); + map(0x2000, 0x2003).rw(m_fdc, FUNC(mb8876_device::read), FUNC(mb8876_device::write)).mirror(0x1ff4); + map(0x4000, 0x4007).m("i8291a", FUNC(i8291a_device::map)).mirror(0x1ff8); + map(0x6000, 0x7fff).rw(FUNC(hp9122c_device::status_r), FUNC(hp9122c_device::cmd_w)); + map(0x8000, 0x8001).w(FUNC(hp9122c_device::clridx_w)); + map(0xc000, 0xffff).rom().region("cpu", 0); +} + +MACHINE_CONFIG_START(hp9122c_device::device_add_mconfig) + MCFG_DEVICE_ADD("cpu" , MC6809 , XTAL(8'000'000)) + MCFG_DEVICE_PROGRAM_MAP(cpu_map) + + // without this flag, 'DMA' transfer via SYNC instruction + // will not work + MCFG_QUANTUM_PERFECT_CPU("cpu") + + MCFG_DEVICE_ADD("mb8876", MB8876, 8_MHz_XTAL / 4) + MCFG_WD_FDC_INTRQ_CALLBACK(WRITELINE(*this, hp9122c_device, fdc_intrq_w)) + MCFG_WD_FDC_DRQ_CALLBACK(WRITELINE(*this,hp9122c_device, fdc_drq_w)) + + MCFG_DEVICE_ADD("i8291a", I8291A, XTAL(2'000'000)) + + MCFG_I8291A_EOI_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_eoi_w)) + MCFG_I8291A_DAV_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_dav_w)) + MCFG_I8291A_NRFD_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_nrfd_w)) + MCFG_I8291A_NDAC_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_ndac_w)) + MCFG_I8291A_SRQ_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_srq_w)) + MCFG_I8291A_DIO_WRITE_CB(WRITE8(*this, hp9122c_device, i8291a_dio_w)) + MCFG_I8291A_DIO_READ_CB(READ8(*this, hp9122c_device, i8291a_dio_r)) + MCFG_I8291A_INT_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_int_w)) + MCFG_I8291A_DREQ_WRITE_CB(WRITELINE(*this, hp9122c_device, i8291a_dreq_w)) + + MCFG_FLOPPY_DRIVE_ADD("floppy0" , hp9122c_floppies , "35hd" , hp9122c_floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + MCFG_SLOT_FIXED(true) + MCFG_FLOPPY_DRIVE_ADD("floppy1" , hp9122c_floppies , "35hd" , hp9122c_floppy_formats) + MCFG_FLOPPY_DRIVE_SOUND(true) + MCFG_SLOT_FIXED(true) +MACHINE_CONFIG_END diff --git a/src/devices/bus/ieee488/hp9122c.h b/src/devices/bus/ieee488/hp9122c.h new file mode 100644 index 00000000000..3ff815f697f --- /dev/null +++ b/src/devices/bus/ieee488/hp9122c.h @@ -0,0 +1,151 @@ +// license:BSD-3-Clause +// copyright-holders: Sven Schnelle +/********************************************************************* + + hp9122c.h + + HP9122C floppy/hard disk drive + +*********************************************************************/ + +#ifndef MAME_BUS_IEEE488_HP9122C_H +#define MAME_BUS_IEEE488_HP9122C_H + +#pragma once + +#include "ieee488.h" +#include "cpu/m6809/m6809.h" +#include "machine/i8291a.h" +#include "machine/wd_fdc.h" +#include "imagedev/floppy.h" +#include "machine/fdc_pll.h" + +class hp9122c_device : public device_t, + public device_ieee488_interface +{ +public: + // construction/destruction + hp9122c_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +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; + + // device_ieee488_interface overrides + virtual void ieee488_eoi(int state) override; + virtual void ieee488_dav(int state) override; + virtual void ieee488_nrfd(int state) override; + virtual void ieee488_ndac(int state) override; + virtual void ieee488_ifc(int state) override; + virtual void ieee488_srq(int state) override; + virtual void ieee488_atn(int state) override; + virtual void ieee488_ren(int state) override; + +private: + + + /* Control register bits: + * 0 - Head select + * 1 - unused + * 2 - FDC Clock selector - 0 - 1Mhz, 1 - 2Mhz + * 3 - IntSel1 + * 4 - DS1# + * 5 - DS0# + * 6 - LED + * 7 - IntSel0 + * + * Intsel: + * * - FIRQ IRQ + * 0 - FDCIRQ FDCOrg + * 1 - HPIBINT HPIBDReq + * 2 - GND IndexInt + * 3 - GND GND + */ + + constexpr static int REG_CNTL_HEADSEL = 1 << 0; + constexpr static int REG_CNTL_CLOCK_SEL = 1 << 2; + constexpr static int REG_CNTL_INTSEL1 = 1 << 3; + constexpr static int REG_CNTL_DS1 = 1 << 4; + constexpr static int REG_CNTL_DS0 = 1 << 5; + constexpr static int REG_CNTL_LED = 1 << 6; + constexpr static int REG_CNTL_INTSEL0 = 1 << 7; + + /* Status register bits: + * 0 - Addr0 + * 1 - Addr1 + * 2 - Addr2 + * 3 - Dual(H)/Single(L) + * 4 - T(L) + * 5 - Diskchg# + * 6 - Addr3 + * 7 - density indicatior: H - DD, L - HD + */ + + constexpr static int REG_STATUS_DUAL = 1 << 3; + constexpr static int REG_STATUS_TEST = 1 << 4; + constexpr static int REG_STATUS_DISKCHG = 1 << 5; + constexpr static int REG_STATUS_LOW_DENSITY = 1 << 7; + + DECLARE_WRITE_LINE_MEMBER(i8291a_eoi_w); + DECLARE_WRITE_LINE_MEMBER(i8291a_dav_w); + DECLARE_WRITE_LINE_MEMBER(i8291a_nrfd_w); + DECLARE_WRITE_LINE_MEMBER(i8291a_ndac_w); + DECLARE_WRITE_LINE_MEMBER(i8291a_ifc_w); + DECLARE_WRITE_LINE_MEMBER(i8291a_srq_w); + DECLARE_WRITE_LINE_MEMBER(i8291a_atn_w); + DECLARE_WRITE_LINE_MEMBER(i8291a_ren_w); + + DECLARE_READ8_MEMBER(i8291a_dio_r); + DECLARE_WRITE8_MEMBER(i8291a_dio_w); + + DECLARE_WRITE_LINE_MEMBER(i8291a_int_w); + DECLARE_WRITE_LINE_MEMBER(i8291a_dreq_w); + + DECLARE_WRITE_LINE_MEMBER(fdc_intrq_w); + DECLARE_WRITE_LINE_MEMBER(fdc_drq_w); + + DECLARE_WRITE8_MEMBER(cmd_w); + DECLARE_READ8_MEMBER(status_r); + DECLARE_WRITE8_MEMBER(clridx_w); + // Floppy drive interface + + DECLARE_READ8_MEMBER(fdc_read); + DECLARE_WRITE8_MEMBER(fdc_write); + + void cpu_map(address_map &map); + + required_device m_cpu; + required_device m_i8291a; + required_device m_fdc; + required_device_array m_floppy; + + required_ioport m_hpib_addr; + required_ioport m_testmode; + + void index_pulse_cb(floppy_image_device *floppy, int state); + int m_intsel; + void update_intsel(void); + + bool m_fdc_irq; + bool m_i8291a_irq; + bool m_fdc_drq; + bool m_i8291a_drq; + + bool m_cpuirq; + bool m_cpufirq; + + bool m_index_int; + + bool m_ds0; + bool m_ds1; +}; + +// device type definition +DECLARE_DEVICE_TYPE(HP9122C, hp9122c_device) + +#endif // MAME_BUS_IEEE488_HP9122C_H diff --git a/src/devices/bus/ieee488/ieee488.cpp b/src/devices/bus/ieee488/ieee488.cpp index fac55803e9d..9241d5670ac 100644 --- a/src/devices/bus/ieee488/ieee488.cpp +++ b/src/devices/bus/ieee488/ieee488.cpp @@ -423,10 +423,12 @@ void cbm_ieee488_devices(device_slot_interface &device) //------------------------------------------------- // slot devices +#include "hp9122c.h" #include "hp9895.h" void hp_ieee488_devices(device_slot_interface &device) { + device.option_add("hp9122c", HP9122C); device.option_add("hp9895", HP9895); } diff --git a/src/devices/machine/i8291a.cpp b/src/devices/machine/i8291a.cpp new file mode 100644 index 00000000000..ebdac02962b --- /dev/null +++ b/src/devices/machine/i8291a.cpp @@ -0,0 +1,1160 @@ +// license:BSD-3-Clause +// copyright-holders: Sven Schnelle +/********************************************************************* + + i8291a.cpp + + Intel 8291A GPIB controller + + *********************************************************************/ + +#include "emu.h" + + +#include "i8291a.h" + +#define LOG_STATE (LOG_GENERAL << 1) +#define LOG_REG (LOG_STATE << 1) +#define LOG_INT (LOG_REG << 1) +#define LOG_CMD (LOG_INT << 1) + +#define VERBOSE 0 + +#include "logmacro.h" +DEFINE_DEVICE_TYPE(I8291A, i8291a_device, "i8291a", "Intel I8291A GPIB Talker/Listener") + +ALLOW_SAVE_TYPE(i8291a_device::listener_state); +ALLOW_SAVE_TYPE(i8291a_device::talker_state); +ALLOW_SAVE_TYPE(i8291a_device::talker_primary_state); +ALLOW_SAVE_TYPE(i8291a_device::listener_primary_state); +ALLOW_SAVE_TYPE(i8291a_device::parallel_poll_state); +ALLOW_SAVE_TYPE(i8291a_device::device_trigger_state); +ALLOW_SAVE_TYPE(i8291a_device::device_clear_state); +ALLOW_SAVE_TYPE(i8291a_device::talker_serial_poll_state); +ALLOW_SAVE_TYPE(i8291a_device::serial_poll_state); +ALLOW_SAVE_TYPE(i8291a_device::remote_local_state); +ALLOW_SAVE_TYPE(i8291a_device::source_handshake_state); +ALLOW_SAVE_TYPE(i8291a_device::acceptor_handshake_state); + +i8291a_device::i8291a_device(const machine_config &mconfig, const char *tag, + device_t *owner, uint32_t clock) : + device_t{mconfig, I8291A, tag, owner, clock}, + m_int_write_func{*this}, + m_dreq_write_func{*this}, + m_trig_write_func{*this}, + m_eoi_write_func{*this}, + m_dav_write_func{*this}, + m_nrfd_write_func{*this}, + m_ndac_write_func{*this}, + m_srq_write_func{*this}, + m_dio_write_func{*this}, + m_dio_read_func{*this} +{ +} + +void i8291a_device::device_reset() +{ + m_pon = true; + m_ints1 = 0; + m_ints2 = 0; + m_auxa = 0; + m_auxb = 0; + m_spoll_mode = 0; + m_address_status &= ~REG_ADDRESS_STATUS_EOI; + m_rdy = true; + m_nba = false; + m_send_eoi = false; + m_ist = false; + m_eoi = false; + m_ifc = false; + m_srq = false; + m_dav = false; + m_ndac = false; + m_nrfd = false; + m_atn = false; + m_ren = false; + update_state(m_t_state, talker_state::TIDS); + update_state(m_tp_state, talker_primary_state::TPIS); + update_state(m_tsp_state, talker_serial_poll_state::SPIS); + update_state(m_l_state, listener_state::LIDS); + update_state(m_rl_state, remote_local_state::LOCS); + update_state(m_pp_state, parallel_poll_state::PPIS); + update_state(m_dc_state, device_clear_state::DCIS); + update_state(m_dt_state, device_trigger_state::DTIS); + update_state(m_sh_state, source_handshake_state::SIDS); + update_state(m_ah_state, acceptor_handshake_state::AIDS); +} + +void i8291a_device::device_start() +{ + m_int_write_func.resolve_safe(); + m_dreq_write_func.resolve_safe(); + m_dav_write_func.resolve_safe(); + m_nrfd_write_func.resolve_safe(); + m_ndac_write_func.resolve_safe(); + m_eoi_write_func.resolve_safe(); + m_srq_write_func.resolve_safe(); + m_dio_read_func.resolve_safe(0xff); + m_dio_write_func.resolve_safe(); + + save_item(NAME(m_din)); + save_item(NAME(m_dout)); + save_item(NAME(m_ints1)); + save_item(NAME(m_ints2)); + save_item(NAME(m_ie1)); + save_item(NAME(m_ie2)); + save_item(NAME(m_address0)); + save_item(NAME(m_address1)); + save_item(NAME(m_eos)); + save_item(NAME(m_spoll_mode)); + save_item(NAME(m_address_mode)); + save_item(NAME(m_address_status)); + save_item(NAME(m_cpt)); + save_item(NAME(m_auxa)); + save_item(NAME(m_auxb)); + save_item(NAME(m_atn)); + save_item(NAME(m_ren)); + save_item(NAME(m_nrfd)); + save_item(NAME(m_ndac)); + save_item(NAME(m_dav)); + save_item(NAME(m_srq)); + save_item(NAME(m_ifc)); + save_item(NAME(m_eoi)); + save_item(NAME(m_dio)); + save_item(NAME(m_nrfd_out)); + save_item(NAME(m_ndac_out)); + save_item(NAME(m_dav_out)); + save_item(NAME(m_srq_out)); + save_item(NAME(m_eoi_out)); + save_item(NAME(m_pon)); + save_item(NAME(m_rdy)); + save_item(NAME(m_lpe)); + save_item(NAME(m_ist)); + save_item(NAME(m_rtl)); + save_item(NAME(m_apt_flag)); + save_item(NAME(m_cpt_flag)); + save_item(NAME(m_din_flag)); + save_item(NAME(m_nba)); + save_item(NAME(m_pp_sense)); + save_item(NAME(m_pp_line)); + save_item(NAME(m_send_eoi)); + save_item(NAME(m_intr_out)); + save_item(NAME(m_dreq_out)); + save_item(NAME(m_sh_state)); + save_item(NAME(m_ah_state)); + save_item(NAME(m_t_state)); + save_item(NAME(m_tp_state)); + save_item(NAME(m_tsp_state)); + save_item(NAME(m_l_state)); + save_item(NAME(m_lp_state)); + save_item(NAME(m_rl_state)); + save_item(NAME(m_sp_state)); + save_item(NAME(m_pp_state)); + save_item(NAME(m_dc_state)); + save_item(NAME(m_dt_state)); +} + +READ8_MEMBER(i8291a_device::din_r) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, m_din); + if (!machine().side_effects_disabled()) { + m_din_flag = false; + m_ints1 &= ~REG_INTS1_BI; + update_int(); + run_fsm(); + } + return m_din; +} + +void i8291a_device::update_int() +{ + bool dreq = ((m_ie2 & REG_IE2_DMAO) && (m_ints1 & REG_INTS1_BO)) | + ((m_ie2 & REG_IE2_DMAI) && (m_ints1 & REG_INTS1_BI)); + + if (m_dreq_out != dreq) { + LOGMASKED(LOG_INT, "%s: dreq %s\n", __FUNCTION__, dreq ? "true" : "false"); + m_dreq_write_func(dreq); + m_dreq_out = dreq; + } + + bool intr = false; + + if (m_ints1 & m_ie1) + intr = true; + + if ((m_ints2 & m_ie2) & 0x0f) + intr = true; + + if (intr) { + m_ints2 |= REG_INTS2_INT; + m_address0 |= REG_ADDRESS0_INT; + } else { + m_ints2 &= ~REG_INTS2_INT; + m_address0 &= ~REG_ADDRESS0_INT; + } + + if (m_intr_out != intr) { + LOGMASKED(LOG_INT, "%s: intr %s\n", __FUNCTION__, intr ? "true" : "false"); + m_int_write_func(intr); + m_intr_out = intr; + } +} + +READ8_MEMBER(i8291a_device::ints1_r) +{ + uint8_t ret = m_ints1; + + if (!machine().side_effects_disabled()) { + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, ret); + m_ints1 = 0; + update_int(); + } + return ret; +} + +READ8_MEMBER(i8291a_device::ints2_r) +{ + uint8_t ret = m_ints2; + + if (!machine().side_effects_disabled()) { + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, ret); + m_ints2 = 0; + update_int(); + } + return ret; +} + +READ8_MEMBER(i8291a_device::spoll_stat_r) +{ + LOGMASKED(LOG_REG, "%s\n", __FUNCTION__); + return 0; +} + +READ8_MEMBER(i8291a_device::addr_stat_r) +{ + LOGMASKED(LOG_REG, "%s = %02X\n", __FUNCTION__, m_address_status); + return m_address_status; +} + +READ8_MEMBER(i8291a_device::cpt_r) +{ + LOGMASKED(LOG_REG, "%s\n", __FUNCTION__); + return m_cpt; +} + +READ8_MEMBER(i8291a_device::addr0_r) +{ + //LOGMASKED(LOG_REG, "%s = %02X\n", __FUNCTION__, m_address0); + return m_address0; +} + +READ8_MEMBER(i8291a_device::addr1_r) +{ + LOGMASKED(LOG_REG, "%s = %02X\n", __FUNCTION__, m_address1); + return m_address1; +} + +WRITE8_MEMBER(i8291a_device::dout_w) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, data); + if (m_nba) + return; + m_dout = data; + m_nba = true; + run_fsm(); +} + +WRITE8_MEMBER(i8291a_device::ie1_w) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, data); + m_ie1 = data; + run_fsm(); +} + +WRITE8_MEMBER(i8291a_device::ie2_w) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, data); + m_ie2 = data; + run_fsm(); +} + +WRITE8_MEMBER(i8291a_device::spoll_mode_w) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, data); + m_spoll_mode = data; + run_fsm(); +} + +WRITE8_MEMBER(i8291a_device::addr_mode_w) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, data); + m_address_mode = data & 3; + run_fsm(); +} + +WRITE8_MEMBER(i8291a_device::aux_mode_w) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, data); + switch (data >> 5) { + case 0: + switch (data) { + case AUXCMD_IMMEDIATE_EXEC_PON: + LOGMASKED(LOG_REG, "AUXCMD_IMMEDIATE_EXEC_PON\n"); + m_pon = 0; + m_rdy = 1; + break; + + case AUXCMD_CLEAR_PP: + LOGMASKED(LOG_REG, "AUXCMD_CLEAR_PP\n"); + m_ist = false; + break; + + case AUXCMD_CHIP_RESET: + LOGMASKED(LOG_REG, "AUXCMD_CHIP_RESET\n"); + device_reset(); + break; + + case AUXCMD_FINISH_HANDSHAKE: + LOGMASKED(LOG_REG, "AUXCMD_FINISH_HANDSHAKE\n"); + break; + + case AUXCMD_TRIGGER: + LOGMASKED(LOG_REG, "AUXCMD_TRIGGER\n"); + update_state(m_dt_state, device_trigger_state::DTAS); + break; + + case AUXCMD_CLEAR_RTL: + LOGMASKED(LOG_REG, "AUXCMD_CLEAR_RTL\n"); + m_rtl = false; + break; + + case AUXCMD_SET_RTL: + LOGMASKED(LOG_REG, "AUXCMD_SET_RTL\n"); + m_rtl = true; + break; + + case AUXCMD_SET_PP: + LOGMASKED(LOG_REG, "AUXCMD_SET_PP\n"); + m_ist = true; + break; + + case AUXCMD_SEND_EOI: + LOGMASKED(LOG_REG, "AUXCMD_SEND_EOI\n"); + m_send_eoi = true; + break; + + case AUXCMD_NON_VALID_SA: + LOGMASKED(LOG_REG, "AUXCMD_NON_VALID_SA\n"); + m_apt_flag = false; + break; + + case AUXCMD_VALID_SA: + LOGMASKED(LOG_REG, "AUXCMD_VALID_SA: APT %d\n", m_apt_flag); + if (m_tp_state == talker_primary_state::TPAS) + update_state(m_t_state, talker_state::TADS); + + if (m_lp_state == listener_primary_state::LPAS) { + update_state(m_l_state, listener_state::LADS); + if ((m_address_mode & 3) != 1 && m_lp_state == listener_primary_state::LPAS) { + if (m_rl_state == remote_local_state::LOCS && !m_rtl) + update_state(m_rl_state, remote_local_state::REMS); + if (m_rl_state == remote_local_state::LWLS) + update_state(m_rl_state, remote_local_state::RWLS); + } + } + + m_cpt_flag = false; + m_apt_flag = false; + break; + + case AUXCMD_PON: + LOGMASKED(LOG_REG, "AUXCMD_PON\n"); + device_reset(); + break; + } + case 1: + /* preset internal clock counter */ + break; + case 4: + LOGMASKED(LOG_REG, "AUXA = %02X\n", data & 0x1f); + /* AUXA write */ + m_auxa = data; + break; + case 5: + LOGMASKED(LOG_REG, "AUXB = %02X\n", data & 0x1f); + m_auxb = data; + break; + case 3: + LOGMASKED(LOG_REG, "PPOLL %s (line %d)\n", (data & 0x10) ? "disable" : "enable", data & 7); + m_lpe = !!!(data & 0x10); + m_pp_sense = data & 0x08; + m_pp_line = data & 7; + break; + default: + break; + + } + run_fsm(); +} + +WRITE8_MEMBER(i8291a_device::addr01_w) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, data); + if (data & REG_ADDRESS01_ARS) + m_address1 = data & ~REG_ADDRESS01_ARS; + else + m_address0 = data & ~REG_ADDRESS01_ARS; + run_fsm(); +} + +WRITE8_MEMBER(i8291a_device::eos_w) +{ + LOGMASKED(LOG_REG, "%s: %02X\n", __FUNCTION__, data); + m_eos = data; + run_fsm(); +} + +WRITE_LINE_MEMBER(i8291a_device::nrfd_w) +{ + m_nrfd = !state; + run_fsm(); +} + +WRITE_LINE_MEMBER(i8291a_device::ndac_w) +{ + m_ndac = !state; + run_fsm(); +} + +WRITE_LINE_MEMBER(i8291a_device::dav_w) +{ + m_dav = !state; + run_fsm(); +} + +WRITE_LINE_MEMBER(i8291a_device::eoi_w) +{ + m_eoi = !state; + run_fsm(); +} + +WRITE_LINE_MEMBER(i8291a_device::srq_w) +{ + m_srq = !state; + run_fsm(); +} + +WRITE_LINE_MEMBER(i8291a_device::ifc_w) +{ + m_ifc = !state; + run_fsm(); +} + +WRITE_LINE_MEMBER(i8291a_device::atn_w) +{ + m_atn = !state; + run_fsm(); +} + +WRITE_LINE_MEMBER(i8291a_device::ren_w) +{ + m_ren = !state; + run_fsm(); +} + +void i8291a_device::set_dav(bool state) +{ + if (m_dav_out == state) { + m_dav_out = !state; + m_dav_write_func(m_dav_out); + } +} + +void i8291a_device::set_nrfd(bool state) +{ + if (m_nrfd_out == state) { + m_nrfd_out = !state; + m_nrfd_write_func(m_nrfd_out); + } +} + +void i8291a_device::set_ndac(bool state) +{ + if (m_ndac_out == state) { + m_ndac_out = !state; + m_ndac_write_func(m_ndac_out); + } +} + +void i8291a_device::set_eoi(bool state) +{ + if (m_eoi_out == state) { + m_eoi_out = !state; + m_eoi_write_func(m_eoi_out); + } +} + +void i8291a_device::set_srq(bool state) +{ + if (m_srq_out == state) { + m_srq_out = !state; + m_srq_write_func(m_srq_out); + } +} + +void i8291a_device::run_sh_fsm() +{ + + if (m_pon || m_atn || !(m_t_state == talker_state::TACS || m_t_state == talker_state::SPAS)) { + update_state(m_sh_state, source_handshake_state::SIDS); + } + + switch (m_sh_state) { + case source_handshake_state::SIDS: + m_dio_write_func(0xff); + set_eoi(false); + m_nba = false; + if (m_t_state == talker_state::TACS || m_t_state == talker_state::SPAS) { + update_state(m_sh_state, source_handshake_state::SGNS); + m_ints1 |= REG_INTS1_BO; + } + break; + + case source_handshake_state::SGNS: + set_dav(false); + + if (m_nba) { + update_state(m_sh_state, source_handshake_state::SDYS); + m_ints1 &= ~REG_INTS1_BO; + } + break; + + case source_handshake_state::SDYS: + if (!m_nrfd) + update_state(m_sh_state, source_handshake_state::STRS); + break; + + case source_handshake_state::STRS: + m_nba = false; + m_dio_write_func(~m_dout); + set_eoi(m_send_eoi); + + set_dav(true); + if (!m_ndac) { + m_send_eoi = false; + m_ints1 |= REG_INTS1_BO; + update_state(m_sh_state, source_handshake_state::SGNS); + } + break; + } +} + +void i8291a_device::handle_command() +{ + if (m_din <= 0x1f) { + switch (m_din) { + case IFCMD_DCL: + LOGMASKED(LOG_CMD, "DCL\n"); + update_state(m_dc_state, device_clear_state::DCAS); + break; + case IFCMD_GTL: + LOGMASKED(LOG_CMD, "GTL\n"); + if (m_l_state == listener_state::LADS) + update_state(m_rl_state, remote_local_state::LWLS); + if (m_rl_state == remote_local_state::REMS && + m_l_state == listener_state::LADS && m_rtl) + update_state(m_rl_state, remote_local_state::LOCS); + break; + case IFCMD_SDC: + LOGMASKED(LOG_CMD, "SDC\n"); + if (m_l_state == listener_state::LADS) + update_state(m_dc_state, device_clear_state::DCAS); + break; + case IFCMD_GET: + LOGMASKED(LOG_CMD, "GET\n"); + break; + case IFCMD_LLO: + LOGMASKED(LOG_CMD, "LLO\n"); + if (m_rl_state == remote_local_state::LOCS) + update_state(m_rl_state, remote_local_state::LWLS); + if (m_rl_state == remote_local_state::REMS) + update_state(m_rl_state, remote_local_state::RWLS); + break; + case IFCMD_SPE: + LOGMASKED(LOG_CMD, "SPE\n"); + update_state(m_tsp_state, talker_serial_poll_state::SPMS); + break; + case IFCMD_SPD: + LOGMASKED(LOG_CMD, "SPD\n"); + update_state(m_tsp_state, talker_serial_poll_state::SPIS); + break; + case 0: + break; + default: + LOG("unhandled message: %02X\n", m_din); + if (m_auxb & REG_AUXB_CPT_ENABLE) { + m_cpt_flag = m_din; + m_ints1 |= REG_INTS1_CPT; + } + break; + } + } else if (m_din >= 0x20 && m_din <= 0x3f) { + bool addr_matched = false; + LOGMASKED(LOG_CMD, "MLA%d - mode %d, my addr0 %s%s%02x addr1 %s%s%02x\n", m_din & 0x1f, + m_address_mode & 3, + (m_address0 & REG_ADDRESS_DT) ? "DT " : "", + (m_address0 & REG_ADDRESS_DL) ? "DL " : "", + m_address0 & 0x1f, + (m_address1 & REG_ADDRESS_DT) ? "DT " : "", + (m_address1 & REG_ADDRESS_DL) ? "DL " : "", + m_address1 & 0x1f); + + if ((m_din & 0x1f) == (m_address0 & 0x1f) && !(m_address0 & REG_ADDRESS_DL)) { + LOGMASKED(LOG_CMD, "Address 0 matched (mode %02X)\n", m_address_mode); + m_address_status &= ~REG_ADDRESS_STATUS_MJMN; + addr_matched = true; + } + + if ((m_address_mode & 3) != 2 && (m_din & 0x1f) == (m_address1 & 0x1f) && !(m_address1 & REG_ADDRESS_DL)) { + LOGMASKED(LOG_CMD, "Address 1 matched (mode %02X)\n", m_address_mode); + m_address_status |= REG_ADDRESS_STATUS_MJMN; + addr_matched = true; + } + + if (addr_matched) { + update_state(m_lp_state, listener_primary_state::LPAS); + if (addr_matched && (m_address_mode & 3) == 1 && m_l_state == listener_state::LIDS) + update_state(m_l_state, listener_state::LADS); + } else { + update_state(m_lp_state, listener_primary_state::LPIS); + update_state(m_l_state, listener_state::LIDS); + m_address_status &= ~(REG_ADDRESS_STATUS_MJMN); + } + + if (addr_matched && (m_address_mode & 3) == 1 && m_rl_state == remote_local_state::LWLS) + update_state(m_rl_state, remote_local_state::RWLS); + } else if (m_din >= 0x40 && m_din <= 0x5f) { + bool addr_matched = false; + + LOGMASKED(LOG_CMD, "MTA%d\n", m_din & 0x1f); + + if ((m_din & 0x1f) == (m_address0 & 0x1f) && !(m_address0 & REG_ADDRESS_DT)) { + LOGMASKED(LOG_STATE, "Address 0 matched (mode %02X)\n", m_address_mode); + m_address_status &= ~REG_ADDRESS_STATUS_MJMN; + addr_matched = true; + } + + if ((m_address_mode & 3) != 2 && (m_din & 0x1f) == (m_address1 & 0x1f) && !(m_address1 & REG_ADDRESS_DT)) { + LOGMASKED(LOG_STATE, "Address 1 matched (mode %02X)\n", m_address_mode); + m_address_status |= REG_ADDRESS_STATUS_MJMN; + addr_matched = true; + } + + if (addr_matched) { + update_state(m_tp_state, talker_primary_state::TPAS); + if ((m_address_mode & 3) == 1 && m_t_state == talker_state::TIDS) + update_state(m_t_state, talker_state::TADS); + } else { + update_state(m_tp_state, talker_primary_state::TPIS); + update_state(m_t_state, talker_state::TIDS); + } + + } else if (m_din >= 0x60 && m_din <= 0x7f) { + LOGMASKED(LOG_CMD, "MSA%d\n", m_din & 0x1f); + if ((m_address_mode & 3) == 2 && m_t_state == talker_state::TIDS) + update_state(m_t_state, talker_state::TADS); + + if ((m_address_mode & 3) != 1 && m_rl_state == remote_local_state::LWLS) + update_state(m_rl_state, remote_local_state::RWLS); + + if ((m_address_mode & 3) == 3) { + /* In address mode 3, MSA is passed to host for verification */ + m_ints1 |= REG_INTS1_APT; + m_cpt = m_din; + m_apt_flag = true; + } + } +} + +void i8291a_device::run_ah_fsm() +{ + bool f2 = m_atn || m_l_state == listener_state::LACS || m_l_state == listener_state::LADS; + + if ((m_pon || !f2) && m_ah_state != acceptor_handshake_state::AIDS) { + LOGMASKED(LOG_STATE, "reset AH: pon %d f2 %d\n", m_pon, f2); + update_state(m_ah_state, acceptor_handshake_state::AIDS); + set_nrfd(false); + set_ndac(false); + return; + } + + switch (m_ah_state) { + case acceptor_handshake_state::AIDS: + if (f2 && !m_pon) + update_state(m_ah_state, acceptor_handshake_state::ANRS); + break; + case acceptor_handshake_state::ANRS: + set_nrfd(true); + set_ndac(true); + m_cpt_flag = false; + m_apt_flag = false; + //LOG("m_rdy: %d m_cpt_flag: %d m_apt_flag: %d, m_din_flag %d\n", m_rdy, m_cpt_flag, m_apt_flag, m_din_flag); + if (m_atn || m_rdy) + update_state(m_ah_state, acceptor_handshake_state::ACRS); + break; + + case acceptor_handshake_state::ACRS: + set_nrfd(false); + if (m_dav) + update_state(m_ah_state, acceptor_handshake_state::ADYS); + break; + case acceptor_handshake_state::ADYS: + if (!m_dav) { + update_state(m_ah_state, acceptor_handshake_state::ACRS); + } else { + update_state(m_ah_state, acceptor_handshake_state::ACDS); + } + break; + case acceptor_handshake_state::ACDS: + + if (!m_rdy) { + update_state(m_ah_state, acceptor_handshake_state::AWNS); + break; + } + m_din = ~m_dio_read_func(); + set_nrfd(true); + + if (m_atn) { + /* Received command */ + m_din &= ~0x80; // TODO: parity + handle_command(); + if (!m_cpt_flag && !m_apt_flag) + update_state(m_ah_state, acceptor_handshake_state::AWNS); + } else { + /* Received data */ + m_din_flag = true; + m_ints1 |= REG_INTS1_BI; + if (m_eoi) + m_ints1 |= REG_INTS1_END; + // TODO: END on EOS + } + break; + case acceptor_handshake_state::AWNS: + set_ndac(false); + // TODO: T3 delay, rdy holdoff + + if (!m_dav) + update_state(m_ah_state, acceptor_handshake_state::ANRS); + break; + } +} + +void i8291a_device::run_t_fsm() +{ + switch (m_t_state) { + case talker_state::TIDS: + m_address_status &= ~REG_ADDRESS_STATUS_TA; + break; + + case talker_state::TADS: + m_address_status |= REG_ADDRESS_STATUS_TA; + if (!m_atn) { + if (m_tsp_state == talker_serial_poll_state::SPMS) + update_state(m_t_state, talker_state::SPAS); + else + update_state(m_t_state, talker_state::TACS); + } + + if (m_tp_state == talker_primary_state::TPIS) + update_state(m_t_state, talker_state::TIDS); + break; + // TODO: F4 function + case talker_state::TACS: + m_address_status |= REG_ADDRESS_STATUS_TA; + if (m_atn) + update_state(m_t_state, talker_state::TADS); // TODO: T2 delay + break; + + case talker_state::SPAS: + if (m_atn) + update_state(m_t_state, talker_state::TADS); // TODO: T2 delay + break; + } +} + +void i8291a_device::run_tp_fsm() +{ + switch (m_tp_state) { + case talker_primary_state::TPIS: + m_address_status &= ~REG_ADDRESS_STATUS_TPAS; + break; + case talker_primary_state::TPAS: + m_address_status |= REG_ADDRESS_STATUS_TPAS; + break; + } +} + +void i8291a_device::run_tsp_fsm() +{ + if (m_pon || m_ifc) + update_state(m_tsp_state, talker_serial_poll_state::SPIS); + + switch (m_tsp_state) { + case talker_serial_poll_state::SPIS: + break; + case talker_serial_poll_state::SPMS: + break; + } +} + +void i8291a_device::run_l_fsm() +{ + switch (m_l_state) { + case listener_state::LIDS: + m_address_status &= ~REG_ADDRESS_STATUS_LA; + break; + case listener_state::LADS: + m_address_status |= REG_ADDRESS_STATUS_LA; + if (m_lp_state == listener_primary_state::LPIS) + update_state(m_l_state, listener_state::LIDS); + break; + case listener_state::LACS: + break; + } +} + +void i8291a_device::run_dc_fsm() +{ + switch (m_dc_state) { + case device_clear_state::DCIS: + break; + case device_clear_state::DCAS: + m_ints1 |= REG_INTS1_DEC; + update_state(m_dc_state, device_clear_state::DCIS); + break; + } +} + +void i8291a_device::run_dt_fsm() +{ + switch (m_dt_state) { + case device_trigger_state::DTIS: + break; + case device_trigger_state::DTAS: + m_trig_write_func(true); + m_trig_write_func(false); + update_state(m_dt_state, device_trigger_state::DTIS); + break; + } +} + +void i8291a_device::run_pp_fsm() +{ + if (m_pon) + update_state(m_pp_state, parallel_poll_state::PPIS); + + switch (m_pp_state) { + case parallel_poll_state::PPIS: + if (m_lpe && !m_pon) + update_state(m_pp_state, parallel_poll_state::PPSS); + break; + + case parallel_poll_state::PPSS: + if (!m_lpe) { + update_state(m_pp_state, parallel_poll_state::PPIS); + break; + } + + if (m_atn && m_eoi) + update_state(m_pp_state, parallel_poll_state::PPAS); + break; + + case parallel_poll_state::PPAS: + if (!m_atn || !m_eoi) { + m_dio_write_func(0xff); + update_state(m_pp_state, parallel_poll_state::PPSS); + break; + } + if (m_ist == m_pp_sense) + m_dio_write_func(~(1 << m_pp_line)); + else + m_dio_write_func(0xff); + break; + } +} + +void i8291a_device::run_sp_fsm() +{ + switch (m_sp_state) { + case serial_poll_state::APRS: + break; + case serial_poll_state::NPRS: + break; + case serial_poll_state::SRQS: + break; + } +} + +void i8291a_device::run_rl_fsm() +{ + if (m_pon || !m_ren) + update_state(m_rl_state, remote_local_state::LOCS); + + switch (m_rl_state) { + case remote_local_state::LOCS: + break; + case remote_local_state::LWLS: + break; + case remote_local_state::REMS: + break; + case remote_local_state::RWLS: + break; + } +} + +void i8291a_device::run_lp_fsm() +{ + switch (m_lp_state) { + case listener_primary_state::LPIS: + m_address_status &= ~REG_ADDRESS_STATUS_LPAS; + break; + case listener_primary_state::LPAS: + m_address_status |= REG_ADDRESS_STATUS_LPAS; + break; + } +} + +void i8291a_device::run_fsm() +{ + if (m_ignore_ext_signals) + return; + m_ignore_ext_signals = true; + do { + m_state_changed = false; + + auto m_l_state_old = m_l_state; + auto m_t_state_old = m_t_state; + auto m_rl_state_old = m_rl_state; + run_sh_fsm(); + run_ah_fsm(); + run_t_fsm(); + run_tp_fsm(); + run_tsp_fsm(); + run_l_fsm(); + run_lp_fsm(); + run_dc_fsm(); + run_dt_fsm(); + run_sp_fsm(); + run_pp_fsm(); + run_rl_fsm(); + + if ((m_t_state_old == talker_state::TIDS && m_t_state == talker_state::TADS) || + (m_t_state_old == talker_state::TADS && m_t_state == talker_state::TIDS) || + (m_l_state_old == listener_state::LIDS && m_l_state == listener_state::LADS) || + (m_l_state_old == listener_state::LADS && m_l_state == listener_state::LIDS)) + m_ints2 |= REG_INTS2_ADSC; + + if ((m_rl_state_old == remote_local_state::LOCS && m_rl_state == remote_local_state::REMS) || + (m_rl_state_old == remote_local_state::REMS && m_rl_state == remote_local_state::LOCS) || + (m_rl_state_old == remote_local_state::LWLS && m_rl_state == remote_local_state::RWLS) || + (m_rl_state_old == remote_local_state::RWLS && m_rl_state == remote_local_state::LWLS)) + m_ints2 |= REG_INTS2_REMC; + + if ((m_rl_state_old == remote_local_state::LOCS && m_rl_state == remote_local_state::LWLS) || + (m_rl_state_old == remote_local_state::REMS && m_rl_state == remote_local_state::RWLS) || + (m_rl_state_old == remote_local_state::LWLS && m_rl_state == remote_local_state::LOCS) || + (m_rl_state_old == remote_local_state::RWLS && m_rl_state == remote_local_state::REMS)) + m_ints2 |= REG_INTS2_REMC; + + m_rdy = !m_apt_flag && !m_cpt_flag && !m_din_flag; + update_int(); + } while (m_state_changed); + m_ignore_ext_signals = false; +} + + +const char *i8291a_device::get_state_name(device_clear_state state) +{ + switch (state) { + case device_clear_state::DCIS: + return "DICS"; + case device_clear_state::DCAS: + return "DCAS"; + } + return "Unknown"; +} + +const char *i8291a_device::get_state_name(device_trigger_state state) +{ + switch (state) { + case device_trigger_state::DTIS: + return "DTIS"; + case device_trigger_state::DTAS: + return "DTAS"; + } + return "Unknown"; +} + + +const char *i8291a_device::get_state_name(parallel_poll_state state) +{ + switch (state){ + case parallel_poll_state::PPIS: + return "PPIS"; + case parallel_poll_state::PPSS: + return "PPSS"; + case parallel_poll_state::PPAS: + return "PPAS"; + } + return "Unknown"; +} + + +const char *i8291a_device::get_state_name(serial_poll_state state) +{ + switch (state) { + case serial_poll_state::APRS: + return "APRS"; + case serial_poll_state::NPRS: + return "NPRS"; + case serial_poll_state::SRQS: + return "SRQS"; + } + return "Unknown"; +} + +const char *i8291a_device::get_state_name(remote_local_state state) +{ + switch (state) { + case remote_local_state::LOCS: + return "LOCS"; + case remote_local_state::LWLS: + return "LWLS"; + case remote_local_state::REMS: + return "REMS"; + case remote_local_state::RWLS: + return "RWLS"; + } + return "Unknown"; +} + +const char *i8291a_device::get_state_name(listener_primary_state state) +{ + switch (state) { + case listener_primary_state::LPIS: + return "LPIS"; + case listener_primary_state::LPAS: + return "LPAS"; + } + return "Unknown"; +} + +const char *i8291a_device::get_state_name(source_handshake_state state) +{ + switch (state) { + case source_handshake_state::SIDS: + return "SIDS"; + case source_handshake_state::SGNS: + return "SGNS"; + case source_handshake_state::SDYS: + return "SDYS"; + case source_handshake_state::STRS: + return "STRS"; + } + return "Unknown"; +} + + +const char *i8291a_device::get_state_name(acceptor_handshake_state state) +{ + switch (state) { + case acceptor_handshake_state::AIDS: + return "AIDS"; + case acceptor_handshake_state::ANRS: + return "ANRS"; + case acceptor_handshake_state::ACRS: + return "ACRS"; + case acceptor_handshake_state::ADYS: + return "ADYS"; + case acceptor_handshake_state::ACDS: + return "ACDS"; + case acceptor_handshake_state::AWNS: + return "AWNS"; + } + return "Unknown"; +} + +const char *i8291a_device::get_state_name(talker_state state) +{ + switch (state) { + case talker_state::TIDS: + return "TIDS"; + case talker_state::TADS: + return "TADS"; + case talker_state::TACS: + return "TACS"; + case talker_state::SPAS: + return "SPAS"; + } + return "Unknown"; +} + +const char *i8291a_device::get_state_name(talker_primary_state state) +{ + switch (state) { + case talker_primary_state::TPIS: + return "TPIS"; + case talker_primary_state::TPAS: + return "TPAS"; + } + return "Unknown"; +} + + +const char *i8291a_device::get_state_name(listener_state state) +{ + switch (state) { + case listener_state::LIDS: + return "LIDS"; + case listener_state::LADS: + return "LADS"; + case listener_state::LACS: + return "LACS"; + } + return "Unknown"; +} + +const char *i8291a_device::get_state_name(talker_serial_poll_state state) +{ + switch (state) { + case talker_serial_poll_state::SPIS: + return "SPIS"; + case talker_serial_poll_state::SPMS: + return "SPMS"; + } + return "Unknown"; +} + +void i8291a_device::map(address_map &map) +{ + map(0x00, 0x00).rw(FUNC(i8291a_device::din_r), FUNC(i8291a_device::dout_w)); + map(0x01, 0x01).rw(FUNC(i8291a_device::ints1_r), FUNC(i8291a_device::ie1_w)); + map(0x02, 0x02).rw(FUNC(i8291a_device::ints2_r), FUNC(i8291a_device::ie2_w)); + map(0x03, 0x03).rw(FUNC(i8291a_device::spoll_stat_r), FUNC(i8291a_device::spoll_mode_w)); + map(0x04, 0x04).rw(FUNC(i8291a_device::addr_stat_r), FUNC(i8291a_device::addr_mode_w)); + map(0x05, 0x05).rw(FUNC(i8291a_device::cpt_r), FUNC(i8291a_device::aux_mode_w)); + map(0x06, 0x06).rw(FUNC(i8291a_device::addr0_r), FUNC(i8291a_device::addr01_w)); + map(0x07, 0x07).rw(FUNC(i8291a_device::addr1_r), FUNC(i8291a_device::eos_w)); + +} + +template void i8291a_device::update_state(T &name, T state) +{ + if (name != state) { + m_state_changed = true; + LOGMASKED(LOG_STATE, "%s: %s -> %s\n", __FUNCTION__, + get_state_name(name), + get_state_name(state)); + name = state; + } +} diff --git a/src/devices/machine/i8291a.h b/src/devices/machine/i8291a.h new file mode 100644 index 00000000000..d607ff8f051 --- /dev/null +++ b/src/devices/machine/i8291a.h @@ -0,0 +1,408 @@ +// license:BSD-3-Clause +// copyright-holders: Sven Schnelle +/********************************************************************* + + i8291a.h + + I8291A GPIB controller + +*********************************************************************/ + +#ifndef MAME_MACHINE_I8291A_H +#define MAME_MACHINE_I8291A_H + + +#pragma once + + +#define MCFG_I8291A_INT_WRITE_CB(_write) \ + downcast(*device).set_int_write_cb(DEVCB_##_write); + +#define MCFG_I8291A_DREQ_WRITE_CB(_write) \ + downcast(*device).set_dreq_write_cb(DEVCB_##_write); + +#define MCFG_I8291A_TRIG_WRITE_CB(_write) \ + downcast(*device).set_trig_write_cb(DEVCB_##_write); + +#define MCFG_I8291A_DIO_READ_CB(_read) \ + downcast(*device).set_dio_read_cb(DEVCB_##_read); + +#define MCFG_I8291A_DIO_WRITE_CB(_write) \ + downcast(*device).set_dio_write_cb(DEVCB_##_write); + +#define MCFG_I8291A_EOI_WRITE_CB(_write) \ + downcast(*device).set_eoi_write_cb(DEVCB_##_write); + +#define MCFG_I8291A_DAV_WRITE_CB(_write) \ + downcast(*device).set_dav_write_cb(DEVCB_##_write); + +#define MCFG_I8291A_NRFD_WRITE_CB(_write) \ + downcast(*device).set_nrfd_write_cb(DEVCB_##_write); + +#define MCFG_I8291A_NDAC_WRITE_CB(_write) \ + downcast(*device).set_ndac_write_cb(DEVCB_##_write); + +#define MCFG_I8291A_SRQ_WRITE_CB(_write) \ + downcast(*device).set_srq_write_cb(DEVCB_##_write); + + +class i8291a_device : public device_t +{ +public: + // construction/destruction + i8291a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template devcb_base& set_int_write_cb(Object &&cb) + { return m_int_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_dreq_write_cb(Object &&cb) + { return m_dreq_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_trig_write_cb(Object &&cb) + { return m_trig_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_eoi_write_cb(Object &&cb) + { return m_eoi_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_dav_write_cb(Object &&cb) + { return m_dav_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_nrfd_write_cb(Object &&cb) + { return m_nrfd_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_ndac_write_cb(Object &&cb) + { return m_ndac_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_srq_write_cb(Object &&cb) + { return m_srq_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_dio_write_cb(Object &&cb) + { return m_dio_write_func.set_callback(std::forward(cb)); } + + template devcb_base& set_dio_read_cb(Object &&cb) + { return m_dio_read_func.set_callback(std::forward(cb)); } + + // Signal inputs + DECLARE_WRITE_LINE_MEMBER(reset_w); + DECLARE_WRITE_LINE_MEMBER(dack_w); + + // GPIB port + DECLARE_WRITE_LINE_MEMBER(eoi_w); + DECLARE_WRITE_LINE_MEMBER(dav_w); + DECLARE_WRITE_LINE_MEMBER(nrfd_w); + DECLARE_WRITE_LINE_MEMBER(ndac_w); + DECLARE_WRITE_LINE_MEMBER(ifc_w); + DECLARE_WRITE_LINE_MEMBER(srq_w); + DECLARE_WRITE_LINE_MEMBER(atn_w); + DECLARE_WRITE_LINE_MEMBER(ren_w); + DECLARE_WRITE8_MEMBER(dio_w); + + // register r/w functions + + DECLARE_WRITE8_MEMBER(dout_w); + DECLARE_WRITE8_MEMBER(ie1_w); + DECLARE_WRITE8_MEMBER(ie2_w); + DECLARE_WRITE8_MEMBER(spoll_mode_w); + DECLARE_WRITE8_MEMBER(addr_mode_w); + DECLARE_WRITE8_MEMBER(aux_mode_w); + DECLARE_WRITE8_MEMBER(addr01_w); + DECLARE_WRITE8_MEMBER(eos_w); + + DECLARE_READ8_MEMBER(din_r); + DECLARE_READ8_MEMBER(ints1_r); + DECLARE_READ8_MEMBER(ints2_r); + DECLARE_READ8_MEMBER(spoll_stat_r); + DECLARE_READ8_MEMBER(addr_stat_r); + DECLARE_READ8_MEMBER(cpt_r); + DECLARE_READ8_MEMBER(addr0_r); + DECLARE_READ8_MEMBER(addr1_r); + void map(address_map &map); + +private: + + // signal output + devcb_write_line m_int_write_func; + devcb_write_line m_dreq_write_func; + devcb_write_line m_trig_write_func; + devcb_write_line m_eoi_write_func; + devcb_write_line m_dav_write_func; + devcb_write_line m_nrfd_write_func; + devcb_write_line m_ndac_write_func; + devcb_write_line m_srq_write_func; + + devcb_write8 m_dio_write_func; + devcb_read8 m_dio_read_func; + + void set_dav(bool state); + void set_nrfd(bool state); + void set_ndac(bool state); + void set_eoi(bool state); + void set_srq(bool state); + + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + void update_int(); + void handle_command(); + void run_fsm(); + void run_sh_fsm(); + void run_ah_fsm(); + void run_dt_fsm(); + void run_dc_fsm(); + void run_l_fsm(); + void run_lp_fsm(); + void run_t_fsm(); + void run_tp_fsm(); + void run_tsp_fsm(); + void run_sp_fsm(); + void run_pp_fsm(); + void run_rl_fsm(); + + // registers + + uint8_t m_din; + uint8_t m_dout; + uint8_t m_ints1; + uint8_t m_ints2; + uint8_t m_ie1; + uint8_t m_ie2; + uint8_t m_address0; + uint8_t m_address1; + uint8_t m_eos; + uint8_t m_spoll_mode; + uint8_t m_address_mode; + uint8_t m_address_status; + uint8_t m_cpt; + + uint8_t m_auxa; + uint8_t m_auxb; + + bool m_atn; + bool m_ren; + bool m_nrfd; + bool m_ndac; + bool m_dav; + bool m_srq; + bool m_ifc; + bool m_eoi; + uint8_t m_dio; + + bool m_nrfd_out; + bool m_ndac_out; + bool m_dav_out; + bool m_srq_out; + bool m_eoi_out; + + // internal signals + + bool m_pon; + bool m_rdy; + bool m_lpe; + bool m_ist; + bool m_rtl; + bool m_apt_flag; + bool m_cpt_flag; + bool m_din_flag; + bool m_nba; + + bool m_pp_sense; + uint8_t m_pp_line; + + bool m_send_eoi; + + static constexpr int REG_INTS1_BI = 1 << 0; + static constexpr int REG_INTS1_BO = 1 << 1; + static constexpr int REG_INTS1_ERR = 1 << 2; + static constexpr int REG_INTS1_DEC = 1 << 3; + static constexpr int REG_INTS1_END = 1 << 4; + static constexpr int REG_INTS1_GET = 1 << 5; + static constexpr int REG_INTS1_APT = 1 << 6; + static constexpr int REG_INTS1_CPT = 1 << 7; + + static constexpr int REG_INTS2_ADSC = 1 << 0; + static constexpr int REG_INTS2_REMC = 1 << 1; + static constexpr int REG_INTS2_LLOC = 1 << 2; + static constexpr int REG_INTS2_SPC = 1 << 3; + static constexpr int REG_INTS2_REM = 1 << 4; + static constexpr int REG_INTS2_LLO = 1 << 5; + static constexpr int REG_INTS2_SPAS = 1 << 6; + static constexpr int REG_INTS2_INT = 1 << 7; + + static constexpr int REG_IE2_DMAI = 1 << 4; + static constexpr int REG_IE2_DMAO = 1 << 5; + + static constexpr int REG_ADDRESS01_ARS = 1 << 7; + static constexpr int REG_ADDRESS0_INT = 1 << 7; + static constexpr int REG_ADDRESS_DT = 1 << 6; + static constexpr int REG_ADDRESS_DL = 1 << 5; + + static constexpr int REG_ADDRESS_STATUS_MJMN = 1 << 0; + static constexpr int REG_ADDRESS_STATUS_TA = 1 << 1; + static constexpr int REG_ADDRESS_STATUS_LA = 1 << 2; + static constexpr int REG_ADDRESS_STATUS_TPAS = 1 << 3; + static constexpr int REG_ADDRESS_STATUS_LPAS = 1 << 4; + static constexpr int REG_ADDRESS_STATUS_EOI = 1 << 5; + static constexpr int REG_ADDRESS_STATUS_LON = 1 << 6; + static constexpr int REG_ADDRESS_STATUS_TON = 1 << 7; + + static constexpr int REG_AUXB_CPT_ENABLE = 1 << 0; + static constexpr int REG_AUXB_EOI_SPAS_ENABLE = 1 << 1; + static constexpr int REG_AUXB_HS_TRANSFER = 1 << 2; + static constexpr int REG_AUXB_INT_ACTIVE_LOW = 1 << 3; + static constexpr int REG_AUXB_RFD_HOLDOFF_GET_DEC = 1 << 4; + + static constexpr int REG_AUXA_RFD_HOLDOFF_DATA = 1 << 0; + static constexpr int REG_AUXA_RFD_HOLDOFF_END = 1 << 1; + static constexpr int REG_AUXA_END_ON_EOS = 1 << 2; + static constexpr int REG_AUXA_EOI_ON_EOS = 1 << 3; + static constexpr int REG_AUXA_EOS_8BIT = 1 << 4; + + // AUX CMDs + static constexpr int AUXCMD_IMMEDIATE_EXEC_PON = 0; + static constexpr int AUXCMD_CLEAR_PP = 1; + static constexpr int AUXCMD_CHIP_RESET = 2; + static constexpr int AUXCMD_FINISH_HANDSHAKE = 3; + static constexpr int AUXCMD_TRIGGER = 4; + static constexpr int AUXCMD_CLEAR_RTL = 5; + static constexpr int AUXCMD_SEND_EOI = 6; + static constexpr int AUXCMD_NON_VALID_SA = 7; + static constexpr int AUXCMD_PON = 8; + static constexpr int AUXCMD_SET_PP = 9; + static constexpr int AUXCMD_SET_RTL = 13; + static constexpr int AUXCMD_VALID_SA = 15; + + // Interface commands + // TODO: stolen from tms9914, move to common header file. PHI also defines this + + static constexpr uint8_t IFCMD_MASK = 0x7f; // Mask of valid bits in if. commands + static constexpr uint8_t IFCMD_ACG_MASK = 0x70; // Mask of ACG commands + static constexpr uint8_t IFCMD_ACG_VALUE = 0x00; // Value of ACG commands + static constexpr uint8_t IFCMD_UCG_MASK = 0x70; // Mask of UCG commands + static constexpr uint8_t IFCMD_UCG_VALUE = 0x10; // Value of UCG commands + static constexpr uint8_t IFCMD_GROUP_MASK = 0x60; // Mask of group id + static constexpr uint8_t IFCMD_LAG_VALUE = 0x20; // Value of LAG commands + static constexpr uint8_t IFCMD_TAG_VALUE = 0x40; // Value of TAG commands + static constexpr uint8_t IFCMD_SCG_VALUE = 0x60; // Value of SCG commands + static constexpr uint8_t IFCMD_GTL = 0x01; // Go to local + static constexpr uint8_t IFCMD_SDC = 0x04; // Selected device clear + static constexpr uint8_t IFCMD_GET = 0x08; // Group execute trigger + static constexpr uint8_t IFCMD_TCT = 0x09; // Take control + static constexpr uint8_t IFCMD_LLO = 0x11; // Local lock-out + static constexpr uint8_t IFCMD_DCL = 0x14; // Device clear + static constexpr uint8_t IFCMD_SPE = 0x18; // Serial poll enable + static constexpr uint8_t IFCMD_SPD = 0x19; // Serial poll disable + static constexpr uint8_t IFCMD_UNL = 0x3f; // Unlisten + static constexpr uint8_t IFCMD_UNT = 0x5f; // Untalk + + enum class source_handshake_state : uint8_t { + SIDS, + SGNS, + SDYS, + STRS + }; + + enum class acceptor_handshake_state : uint8_t { + AIDS, + ANRS, + ACRS, + AWNS, + ADYS, + ACDS + }; + + enum class talker_state : uint8_t { + TIDS, + TADS, + SPAS, + TACS + }; + + enum class talker_primary_state : uint8_t { + TPIS, + TPAS + }; + + enum class listener_primary_state : uint8_t { + LPIS, + LPAS + }; + + enum class talker_serial_poll_state : uint8_t { + SPIS, + SPMS + }; + + enum class serial_poll_state : uint8_t { + NPRS, + SRQS, + APRS + }; + + enum class listener_state : uint8_t { + LIDS, + LADS, + LACS + }; + + enum class remote_local_state : uint8_t { + LOCS, + REMS, + RWLS, + LWLS + }; + + enum class parallel_poll_state : uint8_t { + PPIS, + PPSS, + PPAS + }; + + enum class device_clear_state : uint8_t { + DCIS, + DCAS + }; + + enum class device_trigger_state : uint8_t { + DTIS, + DTAS + }; + + static const char *get_state_name(acceptor_handshake_state state); + static const char *get_state_name(source_handshake_state state); + static const char *get_state_name(talker_state state); + static const char *get_state_name(talker_primary_state state); + static const char *get_state_name(talker_serial_poll_state state); + static const char *get_state_name(listener_state state); + static const char *get_state_name(listener_primary_state state); + static const char *get_state_name(device_clear_state state); + static const char *get_state_name(device_trigger_state state); + static const char *get_state_name(parallel_poll_state state); + static const char *get_state_name(serial_poll_state state); + static const char *get_state_name(remote_local_state state); + + template void update_state(T &name, T state); + + source_handshake_state m_sh_state; + acceptor_handshake_state m_ah_state; + talker_state m_t_state; + talker_primary_state m_tp_state; + talker_serial_poll_state m_tsp_state; + listener_state m_l_state; + listener_primary_state m_lp_state; + remote_local_state m_rl_state; + serial_poll_state m_sp_state; + parallel_poll_state m_pp_state; + device_clear_state m_dc_state; + device_trigger_state m_dt_state; + bool m_state_changed; + bool m_ignore_ext_signals; + bool m_intr_out; + bool m_dreq_out; +}; + +// device type definition +DECLARE_DEVICE_TYPE(I8291A, i8291a_device) + +#endif // MAME_MACHINE_I8291A_H diff --git a/src/mame/drivers/hp9k_3xx.cpp b/src/mame/drivers/hp9k_3xx.cpp index fdb8ba069d8..f0fc0e96168 100644 --- a/src/mame/drivers/hp9k_3xx.cpp +++ b/src/mame/drivers/hp9k_3xx.cpp @@ -480,7 +480,7 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k310) MCFG_TMS9914_ATN_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_atn_w)) MCFG_TMS9914_REN_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_ren_w)) - MCFG_IEEE488_SLOT_ADD("ieee0", 0, hp_ieee488_devices, "hp9895") + MCFG_IEEE488_SLOT_ADD("ieee0", 0, hp_ieee488_devices, "hp9122c") MCFG_IEEE488_SLOT_ADD("ieee_rem", 0, remote488_devices, nullptr) MCFG_IEEE488_BUS_ADD() @@ -512,7 +512,8 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k320) MCFG_HP_HIL_SLOT_ADD(MLC_TAG, "hil1", hp_hil_devices, "hp_46021a") MCFG_DEVICE_ADD(PTM6840_TAG, PTM6840, 250000) // from oscillator module next to the 6840 - MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 250000.0f, 250000.0f) + MCFG_PTM6840_EXTERNAL_CLOCKS(250000.0f, 0.0f, 250000.0f) + MCFG_PTM6840_O3_CB(WRITELINE(PTM6840_TAG, ptm6840_device , set_c2)) SPEAKER(config, "mono").front_center(); MCFG_DEVICE_ADD(SN76494_TAG, SN76494, SN76494_CLOCK) @@ -537,7 +538,7 @@ MACHINE_CONFIG_START(hp9k3xx_state::hp9k320) MCFG_TMS9914_ATN_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_atn_w)) MCFG_TMS9914_REN_WRITE_CB(WRITELINE(IEEE488_TAG, ieee488_device, host_ren_w)) - MCFG_IEEE488_SLOT_ADD("ieee0", 0, hp_ieee488_devices, "hp9895") + MCFG_IEEE488_SLOT_ADD("ieee0", 0, hp_ieee488_devices, "hp9122c") MCFG_IEEE488_SLOT_ADD("ieee_rem", 0, remote488_devices, nullptr) MCFG_IEEE488_BUS_ADD() -- cgit v1.2.3