summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Nigel Barnes <ngbarnes@gmail.com>2025-11-18 20:47:15 +0000
committer Nigel Barnes <ngbarnes@gmail.com>2025-11-18 20:47:15 +0000
commitb223b6d110f35c117b239df6bf51e8ec4faa0ffe (patch)
treed7d7575b831c0105478461066610046ebad99b37
parent01e433d5f45f13dd7ce95dac06e3016727265057 (diff)
machine/82c100.cpp: New 82C100 IBM PS/2 Model 30 and Super XT device.
machine/82c606.cpp: New 82C606 CHIPSpak Multifunction Controller device. machine/psion_asic7.cpp: New Psion ASIC7 device.
-rw-r--r--scripts/src/machine.lua27
-rw-r--r--src/devices/machine/82c100.cpp434
-rw-r--r--src/devices/machine/82c100.h146
-rw-r--r--src/devices/machine/82c606.cpp311
-rw-r--r--src/devices/machine/82c606.h105
-rw-r--r--src/devices/machine/psion_asic7.cpp175
-rw-r--r--src/devices/machine/psion_asic7.h72
7 files changed, 1270 insertions, 0 deletions
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index 4440d44b95f..adc663e9236 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -631,6 +631,30 @@ end
---------------------------------------------------
--
+--@src/devices/machine/82c100.h,MACHINES["82C100"] = true
+---------------------------------------------------
+
+if (MACHINES["82C100"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/82c100.cpp",
+ MAME_DIR .. "src/devices/machine/82c100.h",
+ }
+end
+
+---------------------------------------------------
+--
+--@src/devices/machine/82c606.h,MACHINES["82C606"] = true
+---------------------------------------------------
+
+if (MACHINES["82C606"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/machine/82c606.cpp",
+ MAME_DIR .. "src/devices/machine/82c606.h",
+ }
+end
+
+---------------------------------------------------
+--
--@src/devices/machine/adc0804.h,MACHINES["ADC0804"] = true
---------------------------------------------------
@@ -2954,6 +2978,7 @@ end
--@src/devices/machine/psion_asic3.h,MACHINES["PSION_ASIC"] = true
--@src/devices/machine/psion_asic4.h,MACHINES["PSION_ASIC"] = true
--@src/devices/machine/psion_asic5.h,MACHINES["PSION_ASIC"] = true
+--@src/devices/machine/psion_asic7.h,MACHINES["PSION_ASIC"] = true
--@src/devices/machine/psion_asic9.h,MACHINES["PSION_ASIC"] = true
---------------------------------------------------
@@ -2969,6 +2994,8 @@ if (MACHINES["PSION_ASIC"]~=null) then
MAME_DIR .. "src/devices/machine/psion_asic4.h",
MAME_DIR .. "src/devices/machine/psion_asic5.cpp",
MAME_DIR .. "src/devices/machine/psion_asic5.h",
+ MAME_DIR .. "src/devices/machine/psion_asic7.cpp",
+ MAME_DIR .. "src/devices/machine/psion_asic7.h",
MAME_DIR .. "src/devices/machine/psion_asic9.cpp",
MAME_DIR .. "src/devices/machine/psion_asic9.h",
}
diff --git a/src/devices/machine/82c100.cpp b/src/devices/machine/82c100.cpp
new file mode 100644
index 00000000000..f88ef8bda47
--- /dev/null
+++ b/src/devices/machine/82c100.cpp
@@ -0,0 +1,434 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Chips 82C100 IBM PS/2 Model 30 and Super XT
+
+ TODO:
+ - EMS Page Registers
+ - Keyboard NMI's maybe have issues
+
+**********************************************************************/
+
+#include "emu.h"
+#include "82c100.h"
+
+#include "multibyte.h"
+
+
+#define VERBOSE 0
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(F82C100, f82c100_device, "82c100", "82C100 PS/2 Model 30 and Super XT")
+
+
+f82c100_device::f82c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, F82C100, tag, owner, clock)
+ , m_maincpu(*this, finder_base::DUMMY_TAG)
+ , m_dma8237(*this, "dma8237")
+ , m_pic8259(*this, "pic8259")
+ , m_pit8254(*this, "pit8254")
+ , m_ppi8255(*this, "ppi8255")
+ , m_intr_callback(*this)
+ , m_nmi_callback(*this)
+ , m_in_memr_callback(*this, 0)
+ , m_out_memw_callback(*this)
+ , m_in_ior_callback(*this, 0)
+ , m_out_iow_callback(*this)
+ , m_out_dack_callback(*this)
+ , m_tc_callback(*this)
+ , m_spkdata_callback(*this)
+ , m_clock2(0)
+{
+}
+
+
+void f82c100_device::map(address_map &map)
+{
+ map(0x0000, 0x000f).rw(m_dma8237, FUNC(am9517a_device::read), FUNC(am9517a_device::write));
+ map(0x0020, 0x0021).rw(m_pic8259, FUNC(pic8259_device::read), FUNC(pic8259_device::write));
+ map(0x0022, 0x0023).rw(FUNC(f82c100_device::config_r), FUNC(f82c100_device::config_w));
+ map(0x0040, 0x0043).rw(m_pit8254, FUNC(pit8254_device::read), FUNC(pit8254_device::write));
+ map(0x0060, 0x0063).rw(m_ppi8255, FUNC(i8255_device::read), FUNC(i8255_device::write));
+ map(0x0072, 0x0072).rw(FUNC(f82c100_device::nmi_control_r), FUNC(f82c100_device::nmi_control_w));
+ map(0x007e, 0x007e).rw(FUNC(f82c100_device::nmi_status_r), FUNC(f82c100_device::nmi_status_w));
+ map(0x007f, 0x007f).rw(FUNC(f82c100_device::pwr_control_r), FUNC(f82c100_device::pwr_control_w));
+ map(0x0080, 0x0083).nopr().w(FUNC(f82c100_device::dma_page_w));
+ map(0x00a0, 0x00af).w(FUNC(f82c100_device::nmi_control_w));
+}
+
+
+void f82c100_device::device_add_mconfig(machine_config &config)
+{
+ AM9517A(config, m_dma8237, clock() / 2);
+ m_dma8237->out_hreq_callback().set(m_dma8237, FUNC(am9517a_device::hack_w));
+ m_dma8237->out_eop_callback().set([this](int state) { m_tc_callback(state); });
+ m_dma8237->in_memr_callback().set([this](offs_t offset) { return m_in_memr_callback((m_dma_page[m_dma_channel] << 16) + offset); });
+ m_dma8237->out_memw_callback().set([this](offs_t offset, u8 data) { m_out_memw_callback((m_dma_page[m_dma_channel] << 16) + offset, data); });
+ m_dma8237->in_ior_callback<0>().set([this]() { return m_in_ior_callback[0](); });
+ m_dma8237->in_ior_callback<1>().set([this]() { return m_in_ior_callback[1](); });
+ m_dma8237->in_ior_callback<2>().set([this]() { return m_in_ior_callback[2](); });
+ m_dma8237->in_ior_callback<3>().set([this]() { return m_in_ior_callback[3](); });
+ m_dma8237->out_iow_callback<0>().set([this](uint8_t data) { m_out_iow_callback[0](data); });
+ m_dma8237->out_iow_callback<1>().set([this](uint8_t data) { m_out_iow_callback[1](data); });
+ m_dma8237->out_iow_callback<2>().set([this](uint8_t data) { m_out_iow_callback[2](data); });
+ m_dma8237->out_iow_callback<3>().set([this](uint8_t data) { m_out_iow_callback[3](data); });
+ m_dma8237->out_dack_callback<0>().set([this](int state) { set_dack(0, state); });
+ m_dma8237->out_dack_callback<1>().set([this](int state) { set_dack(1, state); });
+ m_dma8237->out_dack_callback<2>().set([this](int state) { set_dack(2, state); });
+ m_dma8237->out_dack_callback<3>().set([this](int state) { set_dack(3, state); });
+
+ PIC8259(config, m_pic8259);
+ m_pic8259->out_int_callback().set([this](int state) { m_intr_callback(state); });
+
+ PIT8254(config, m_pit8254);
+ m_pit8254->set_clk<0>(clock() / 12.0);
+ m_pit8254->out_handler<0>().set(m_pic8259, FUNC(pic8259_device::ir0_w));
+ m_pit8254->set_clk<2>(clock() / 12.0);
+ m_pit8254->out_handler<2>().set(FUNC(f82c100_device::pit8253_out2_changed));
+
+ I8255A(config, m_ppi8255);
+ m_ppi8255->in_pa_callback().set(FUNC(f82c100_device::ppi_porta_r));
+ m_ppi8255->out_pa_callback().set([this](u8 data) { logerror("POST %d\n", data); });
+ m_ppi8255->out_pb_callback().set(FUNC(f82c100_device::ppi_portb_w));
+ m_ppi8255->in_pc_callback().set(FUNC(f82c100_device::ppi_portc_r));
+}
+
+
+void f82c100_device::device_start()
+{
+ m_maincpu->space(AS_PROGRAM).install_read_tap(0x08, 0x0b, "nmi_vector", [this](offs_t offset, u16 &data, u16 mem_mask)
+ {
+ // Substitute NMI vector
+ if (BIT(m_cfg_regs[0x4b], 6))
+ {
+ data = get_u16le(&m_cfg_regs[0x3c + offset]); // Index 44H - 47H
+ }
+ });
+
+ save_item(NAME(m_cfg_regs));
+ save_item(NAME(m_cfg_indx));
+ save_item(NAME(m_nmi_enable));
+ save_item(NAME(m_nmi_status));
+ save_item(NAME(m_pwr_control));
+ save_item(NAME(m_nmi_control));
+ save_item(NAME(m_dma_page));
+ save_item(NAME(m_dma_channel));
+ save_item(NAME(m_ppi_portb));
+ save_item(NAME(m_scan_code));
+}
+
+void f82c100_device::device_reset()
+{
+ for (int i = 0; i < 256; i++)
+ m_cfg_regs[i] = 0;
+
+ m_cfg_regs[0x40] = 0x01;
+ m_cfg_regs[0x43] = 0x30;
+ m_cfg_regs[0x48] = 0x01;
+
+ m_cfg_indx = 0;
+
+ m_nmi_enable = true;
+ m_nmi_status = 0;
+ m_pwr_control = 0;
+ m_nmi_control = 0;
+
+ for (int i = 0; i < 4; i++)
+ m_dma_page[i] = 0;
+ m_dma_channel = 0;
+
+ m_spkdata = 0;
+ m_pit_out2 = 1;
+
+ // keyboard interface
+ m_kbclklo = 0;
+ m_kbclk = 1;
+ m_kbdata = 0;
+}
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+u8 f82c100_device::config_r(offs_t offset)
+{
+ u8 data = 0x00;
+
+ switch (offset & 1)
+ {
+ case 0:
+ data = m_cfg_indx;
+ break;
+ case 1:
+ data = m_cfg_regs[m_cfg_indx];
+ break;
+ }
+
+ return data;
+}
+
+void f82c100_device::config_w(offs_t offset, u8 data)
+{
+ switch (offset & 1)
+ {
+ case 0:
+ m_cfg_indx = data;
+ break;
+ case 1:
+ m_cfg_regs[m_cfg_indx] = data;
+ LOG("CR[%02x] = %02x\n", m_cfg_indx, data);
+
+ if (m_cfg_indx == 0x40) // Clock/Mode Size
+ {
+ m_maincpu->set_unscaled_clock(BIT(data, 7) ? m_clock2 / 3 : clock() / 3);
+ }
+ break;
+ }
+}
+
+
+void f82c100_device::pit8253_out2_changed(int state)
+{
+ m_pit_out2 = state;
+ m_spkdata_callback(m_spkdata & m_pit_out2);
+}
+
+void f82c100_device::set_spkrdata(int state)
+{
+ m_spkdata = state;
+ m_spkdata_callback(m_spkdata & m_pit_out2);
+}
+
+
+u8 f82c100_device::ppi_porta_r()
+{
+ // Keyboard Scan Code
+ return m_scan_code;
+}
+
+void f82c100_device::ppi_portb_w(u8 data)
+{
+ // b0 TMR2GTSPK - Timer 2 Gate Speaker
+ // b1 SPKDATA - Speaker Data
+ // b2 Reserved
+ // b3 Read High/Low Switches
+ // b4 nPCKEn - Parity Check Enable
+ // b5 nIOCHKEN - I/O Channel Check Enable
+ // b6 nKBCLKLO - Keyboard Clock Low
+ // b7 nKBEN - Keyboard enable/clear
+ m_ppi_portb = data;
+ //logerror("ppi_portb_w: %02x\n", data);
+
+ m_pit8254->write_gate2(BIT(data, 0));
+
+ set_spkrdata(BIT(data, 1));
+
+ m_kbclklo = !BIT(data, 6);
+
+ if (BIT(data, 7))
+ {
+ m_scan_code = 0x00;
+ m_scan_bit = 0;
+ m_pic8259->ir1_w(CLEAR_LINE);
+
+ if (BIT(m_nmi_control, 6))
+ m_nmi_callback(ASSERT_LINE);
+ }
+}
+
+u8 f82c100_device::ppi_portc_r()
+{
+ // b0-3 High/Low Switches
+ // b4 Reserved
+ // b5 Timer Channel 2 Out
+ // b6 I/O Channel Check
+ // b7 RAM Parity Check
+ u8 data = 0x00;
+
+ if (BIT(m_ppi_portb, 3))
+ data |= (m_cfg_regs[0x43] >> 4) & 0x0f;
+ else
+ data |= m_cfg_regs[0x43] & 0x0f;
+
+ data |= m_pit_out2 << 5;
+
+ return data;
+}
+
+
+void f82c100_device::update_nmi()
+{
+ //logerror("update_nmi: %d status %02x\n", m_nmi_enable, m_nmi_status);
+ if (m_nmi_enable && (m_nmi_status != 0x00))
+ m_nmi_callback(ASSERT_LINE);
+ else
+ m_nmi_callback(CLEAR_LINE);
+}
+
+u8 f82c100_device::nmi_control_r()
+{
+ // b0 Reserved
+ // b1 FDC Power Control
+ // b2 Sleep Clock ON/OFF
+ // b3 Enable RTC NMI
+ // b4 Enable Keyboard Data NMI
+ // b5 Enable Suspend NMI
+ // b6 Enable Keyboard Clear NMI
+ // b7 Reserved
+ return m_nmi_control;
+}
+
+void f82c100_device::nmi_control_w(u8 data)
+{
+ //logerror("nmi_control_w: %02x\n", data);
+ m_nmi_control = data;
+}
+
+u8 f82c100_device::nmi_status_r()
+{
+ // b0 Keyboard Data
+ // b1 Reserved
+ // b2 RTC NMI
+ // b3 Suspend NMI
+ // b4 Keyboard Clear
+ // b5 PERR - Parity Error
+ // b6 IOCHK - I/O Channel Check
+ // b7 Reserved
+ return m_nmi_status;
+}
+
+void f82c100_device::nmi_status_w(u8 data)
+{
+ m_nmi_status = data;
+ update_nmi();
+}
+
+u8 f82c100_device::pwr_control_r()
+{
+ // b0 Reserved
+ // b1 Request Power Off
+ // b2 Reserved
+ // b3 Software Controlled Reset
+ // b4 Reserved
+ // b5 Reserved
+ // b6 External Power
+ // b7 Low Battery
+ return m_pwr_control;
+}
+
+void f82c100_device::pwr_control_w(u8 data)
+{
+ m_pwr_control = data;
+
+ // Request Power Off
+ if (BIT(data, 1))
+ {
+ m_nmi_status |= 0x08; // set Suspend NMI
+ update_nmi();
+ }
+}
+
+void f82c100_device::nmi_mask_w(u8 data)
+{
+ // b7 NMI Enable
+ m_nmi_enable = BIT(data, 7);
+
+ if (!m_nmi_enable)
+ {
+ m_nmi_status &= ~0x08; // clear Suspend NMI
+ m_nmi_status &= ~0x04; // clear RTC NMI
+ }
+ update_nmi();
+}
+
+void f82c100_device::npnmi_w(int state)
+{
+ // TODO: unknown NMI status mask, maybe 0x02?
+
+ update_nmi();
+}
+
+void f82c100_device::rtcnmi_w(int state)
+{
+ if (state && m_nmi_enable)
+ m_nmi_status |= 0x04; // set RTC NMI
+ else
+ m_nmi_status &= ~0x04; // clear RTC NMI
+
+ update_nmi();
+}
+
+void f82c100_device::pwrnmi_w(int state)
+{
+ if (state && m_nmi_enable && BIT(m_cfg_regs[0x4b], 5))
+ m_nmi_status |= 0x08; // set Suspend NMI
+ else
+ m_nmi_status &= ~0x08; // clear Suspend NMI
+
+ update_nmi();
+}
+
+void f82c100_device::set_dack(u8 channel, int state)
+{
+ if (!state) m_dma_channel = channel;
+
+ m_out_dack_callback[channel](state);
+}
+
+void f82c100_device::dma_page_w(offs_t offset, u8 data)
+{
+ switch(offset % 4)
+ {
+ case 1:
+ m_dma_page[2] = data;
+ break;
+ case 2:
+ m_dma_page[3] = data;
+ break;
+ case 3:
+ m_dma_page[0] = m_dma_page[1] = data;
+ break;
+ }
+}
+
+
+int f82c100_device::kbclk_r()
+{
+ if (m_kbclklo)
+ return 0;
+ else
+ return 1; // pulled high externally
+}
+
+int f82c100_device::kbdata_r()
+{
+ if (!BIT(m_ppi_portb, 7)) // nKBEN
+ return 1; // pulled high externally
+ else
+ return 1;
+}
+
+void f82c100_device::kbclk_w(int state)
+{
+ // TODO: this is crude but functional, implement start bit detection
+ if (!state && m_kbclk)
+ {
+ m_scan_bit++;
+ m_scan_code = (m_scan_code >> 1) | (m_kbdata << 7);
+
+ if (m_scan_bit == 9) // 8 data bits + start bit
+ {
+ m_pic8259->ir1_w(ASSERT_LINE);
+ }
+ }
+ m_kbclk = state;
+}
+
+void f82c100_device::kbdata_w(int state)
+{
+ m_kbdata = state;
+}
diff --git a/src/devices/machine/82c100.h b/src/devices/machine/82c100.h
new file mode 100644
index 00000000000..425b5a3522a
--- /dev/null
+++ b/src/devices/machine/82c100.h
@@ -0,0 +1,146 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Chips 82C100 IBM PS/2 Model 30 and Super XT
+
+**********************************************************************/
+
+#ifndef MAME_MACHINE_82C100_H
+#define MAME_MACHINE_82C100_H
+
+#pragma once
+
+#include "machine/am9517a.h"
+#include "machine/i8255.h"
+#include "machine/pic8259.h"
+#include "machine/pit8253.h"
+
+
+class f82c100_device : public device_t
+{
+public:
+ // construction/destruction
+ f82c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ template <typename X>
+ f82c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, X &&clock2)
+ : f82c100_device(mconfig, tag, owner, clock)
+ {
+ set_clock2(std::forward<X>(clock2));
+ }
+
+ void set_clock2(uint32_t clock) { m_clock2 = clock; }
+ void set_clock2(const XTAL &xtal) { set_clock2(xtal.value()); }
+
+ void map(address_map &map) ATTR_COLD;
+
+ template <typename T> void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
+
+ // cpu interface
+ auto intr() { return m_intr_callback.bind(); }
+ auto nmi() { return m_nmi_callback.bind(); }
+
+ // dma and interrupt controller interface
+ auto memr() { return m_in_memr_callback.bind(); }
+ auto memw() { return m_out_memw_callback.bind(); }
+ template <unsigned C> auto ior() { return m_in_ior_callback[C].bind(); }
+ template <unsigned C> auto iow() { return m_out_iow_callback[C].bind(); }
+ template <unsigned C> auto dack() { return m_out_dack_callback[C].bind(); }
+ auto tc() { return m_tc_callback.bind(); }
+ void irq1_w(int state) { m_pic8259->ir1_w(state); }
+ void irq2_w(int state) { m_pic8259->ir2_w(state); }
+ void irq3_w(int state) { m_pic8259->ir3_w(state); }
+ void irq4_w(int state) { m_pic8259->ir4_w(state); }
+ void irq5_w(int state) { m_pic8259->ir5_w(state); }
+ void irq6_w(int state) { m_pic8259->ir6_w(state); }
+ void irq7_w(int state) { m_pic8259->ir7_w(state); }
+ void drq1_w(int state) { m_dma8237->dreq1_w(state); }
+ void drq2_w(int state) { m_dma8237->dreq2_w(state); }
+ void drq3_w(int state) { m_dma8237->dreq3_w(state); }
+ void npnmi_w(int state);
+ void rtcnmi_w(int state);
+ void pwrnmi_w(int state);
+
+ IRQ_CALLBACK_MEMBER(inta_cb) { return m_pic8259->acknowledge(); }
+
+ // keyboard and speaker interface
+ auto spkdata() { return m_spkdata_callback.bind(); }
+ void kbclk_w(int state);
+ void kbdata_w(int state);
+ int kbclk_r();
+ int kbdata_r();
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ u8 config_r(offs_t offset);
+ void config_w(offs_t offset, u8 data);
+
+ void pit8253_out2_changed(int state);
+ void set_spkrdata(int state);
+
+ u8 ppi_porta_r();
+ void ppi_portb_w(u8 data);
+ u8 ppi_portc_r();
+
+ void update_nmi();
+
+ u8 nmi_control_r();
+ void nmi_control_w(u8 data);
+ u8 nmi_status_r();
+ void nmi_status_w(u8 data);
+ u8 pwr_control_r();
+ void pwr_control_w(u8 data);
+ void nmi_mask_w(u8 data);
+ void set_dack(u8 channel, int state);
+ void dma_page_w(offs_t offset, u8 data);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<am9517a_device> m_dma8237;
+ required_device<pic8259_device> m_pic8259;
+ required_device<pit8254_device> m_pit8254;
+ required_device<i8255_device> m_ppi8255;
+
+ devcb_write_line m_intr_callback;
+ devcb_write_line m_nmi_callback;
+
+ devcb_read8 m_in_memr_callback;
+ devcb_write8 m_out_memw_callback;
+ devcb_read8::array<4> m_in_ior_callback;
+ devcb_write8::array<4> m_out_iow_callback;
+ devcb_write_line::array<4> m_out_dack_callback;
+ devcb_write_line m_tc_callback;
+ devcb_write_line m_spkdata_callback;
+
+ u32 m_clock2;
+
+ u8 m_cfg_regs[256] { 0x00 };
+ u8 m_cfg_indx;
+
+ u8 m_ppi_portb;
+ int m_pit_out2;
+ int m_spkdata;
+
+ bool m_nmi_enable;
+ u8 m_nmi_control;
+ u8 m_nmi_status;
+ u8 m_pwr_control;
+ u8 m_dma_page[4];
+ u8 m_dma_channel;
+
+ int m_kbclklo;
+ int m_kbclk;
+ int m_kbdata;
+ int m_scan_bit;
+ u8 m_scan_code;
+};
+
+
+DECLARE_DEVICE_TYPE(F82C100, f82c100_device)
+
+#endif // MAME_MACHINE_82C100_H
diff --git a/src/devices/machine/82c606.cpp b/src/devices/machine/82c606.cpp
new file mode 100644
index 00000000000..855e3ca4088
--- /dev/null
+++ b/src/devices/machine/82c606.cpp
@@ -0,0 +1,311 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Chips 82C606 CHIPSpak Multifunction Controller
+
+**********************************************************************/
+
+#include "emu.h"
+#include "82c606.h"
+
+
+#define VERBOSE 0
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(P82C606, p82c606_device, "82c606", "82C606 CHIPSpak Multifunction Controller")
+
+
+p82c606_device::p82c606_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, P82C606, tag, owner, clock)
+ , m_maincpu(*this, finder_base::DUMMY_TAG)
+ , m_rtc(*this, "rtc")
+ , m_cmos_ram(*this, "cmos_ram", 0x40, ENDIANNESS_LITTLE)
+ , m_nvram(*this, "nvram")
+ , m_lpt(*this, "parallel")
+ , m_serial(*this, "serial%u", 1U)
+ , m_irq3_callback(*this)
+ , m_irq4_callback(*this)
+ , m_irq5_callback(*this)
+ , m_irq7_callback(*this)
+ , m_txd1_callback(*this)
+ , m_dtr1_callback(*this)
+ , m_rts1_callback(*this)
+ , m_txd2_callback(*this)
+ , m_dtr2_callback(*this)
+ , m_rts2_callback(*this)
+{
+}
+
+
+void p82c606_device::device_add_mconfig(machine_config &config)
+{
+ // serial ports
+ NS16450(config, m_serial[0], clock());
+ m_serial[0]->out_int_callback().set(FUNC(p82c606_device::int_select<S1>));
+ m_serial[0]->out_tx_callback().set([this](int state) { m_txd1_callback(state); });
+ m_serial[0]->out_dtr_callback().set([this](int state) { m_dtr1_callback(state); });
+ m_serial[0]->out_rts_callback().set([this](int state) { m_rts1_callback(state); });
+
+ NS16450(config, m_serial[1], clock());
+ m_serial[1]->out_int_callback().set(FUNC(p82c606_device::int_select<S2>));
+ m_serial[1]->out_tx_callback().set([this](int state) { m_txd2_callback(state); });
+ m_serial[1]->out_dtr_callback().set([this](int state) { m_dtr2_callback(state); });
+ m_serial[1]->out_rts_callback().set([this](int state) { m_rts2_callback(state); });
+
+ // parallel port
+ PC_LPT(config, m_lpt);
+ m_lpt->irq_handler().set(FUNC(p82c606_device::int_select<PP>));
+
+ // rtc
+ MC146818(config, m_rtc, 32.768_kHz_XTAL);
+ m_rtc->irq().set(FUNC(p82c606_device::int_select<RC>));
+ m_rtc->set_binary(true);
+ NVRAM(config, m_nvram, nvram_device::DEFAULT_ALL_0);
+}
+
+
+void p82c606_device::device_start()
+{
+ address_space &io_space = m_maincpu->space(AS_IO);
+
+ // CHIPSpak configuration
+ io_space.install_write_tap(0x2fa, 0x2fb, 0x100, "chipspak6", [this](offs_t offset, u16 &data, u16 mem_mask) { chipspak_w(offset, data & 0xff); });
+
+ // register defaults
+ const u8 cfg_regs_defaults[] = { 0x00, 0x00, 0x00, 0xb0, 0xfe, 0xbe, 0x9e, 0x80, 0xec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ for (int i = 0; i < std::size(cfg_regs_defaults); i++)
+ {
+ m_cfg_regs[i] = cfg_regs_defaults[i];
+ }
+
+ m_nvram->set_base(m_cmos_ram, 0x40);
+
+ save_item(NAME(m_cmos_addr));
+ save_item(NAME(m_cfg_regs));
+ save_item(NAME(m_cfg_indx));
+ save_item(NAME(m_cfg_state));
+}
+
+void p82c606_device::device_reset()
+{
+}
+
+
+void p82c606_device::chipspak_w(offs_t offset, u8 data)
+{
+ LOG("chipspak_w: %04x %02x\n", offset, data);
+
+ address_space &io_space = m_maincpu->space(AS_IO);
+
+ // configuration sequence
+ if (m_cfg_state == 0 && offset == 0x2fa)
+ {
+ m_cfg_key = data;
+ m_cfg_state++;
+ }
+ else if (m_cfg_state == 1 && offset == 0x3fa && data == (u8)(~m_cfg_key))
+ {
+ m_cfg_state++;
+ }
+ else if (m_cfg_state == 2 && offset == 0x3fa && data == 0x36) // part number (ASCII 6)
+ {
+ m_cfg_state++;
+ }
+ else if (m_cfg_state == 3 && offset == 0x3fa)
+ {
+ m_cfg_cri = data << 2;
+ m_cfg_state++;
+ }
+ else if (m_cfg_state == 4 && offset == 0x2fa && data == (u8)(~m_cfg_cri >> 2))
+ {
+ m_cfg_state++;
+ m_cfg_regs[0x0f] = m_cfg_cri >> 2; // Config Addr
+
+ LOG("CFG -- mode on -- CRI %04x\n", m_cfg_cri);
+
+ // install the CRI and CAP ports
+ io_space.install_readwrite_handler(m_cfg_cri, m_cfg_cri + 1, emu::rw_delegate(*this, FUNC(p82c606_device::cfg_r)), emu::rw_delegate(*this, FUNC(p82c606_device::cfg_w)));
+ }
+ else
+ {
+ m_cfg_state = 0;
+ }
+}
+
+
+u8 p82c606_device::cfg_r(offs_t offset, u8 mem_mask)
+{
+ u8 data = 0x00;
+
+ switch (offset & 1)
+ {
+ case 0: // CRI
+ data = m_cfg_indx;
+ break;
+
+ case 1: // CAP
+ data = m_cfg_regs[m_cfg_indx];
+ LOG("CR[%02x] => %02x\n", m_cfg_indx, data);
+ }
+
+ return data;
+}
+
+void p82c606_device::cfg_w(offs_t offset, u8 data, u8 mem_mask)
+{
+ address_space &io_space = m_maincpu->space(AS_IO);
+
+ switch (offset & 1)
+ {
+ case 0: // CRI
+ m_cfg_indx = data & 0x0f;
+ break;
+
+ case 1: // CAP
+ if (m_cfg_indx != 0x0f)
+ m_cfg_regs[m_cfg_indx] = data;
+
+ switch (m_cfg_indx)
+ {
+ case 0x00: // Enable
+ LOG("CR[%02x] <= %02x\n", m_cfg_indx, data);
+ LOG("GP %s\n", BIT(data, GP) ? "enabled" : "disabled");
+ LOG("S1 %s\n", BIT(data, S1) ? "enabled" : "disabled");
+ LOG("S2 %s\n", BIT(data, S2) ? "enabled" : "disabled");
+ LOG("PP %s\n", BIT(data, PP) ? "enabled" : "disabled");
+ LOG("RC %s\n", BIT(data, RC) ? "enabled" : "disabled");
+ break;
+
+ case 0x01: // Configuration
+ LOG("CR[%02x] <= %02x\n", m_cfg_indx, data);
+ break;
+
+ case 0x02: // Ext Baud Rate Select
+ LOG("CR[%02x] <= %02x\n", m_cfg_indx, data);
+ break;
+
+ case 0x03: // RTC Port Base Address
+ LOG("CR[%02x] <= %02x RC address %04x\n", m_cfg_indx, data, data << 2);
+ break;
+
+ case 0x04: // UART1 Port Base Address
+ LOG("CR[%02x] <= %02x S1 address %04x\n", m_cfg_indx, data, (data & 0xfe) << 2);
+ break;
+
+ case 0x05: // UART2 Port Base Address
+ LOG("CR[%02x] <= %02x S2 address %04x\n", m_cfg_indx, data, (data & 0xfe) << 2);
+ break;
+
+ case 0x06: // Parallel Port Base Address
+ LOG("CR[%02x] <= %02x PP address %04x\n", m_cfg_indx, data, data << 2);
+ break;
+
+ case 0x07: // Game Port Base Address
+ LOG("CR[%02x] <= %02x GP address %04x\n", m_cfg_indx, data, data << 2);
+ break;
+
+ case 0x08: // Interrupt Select
+ LOG("CR[%02x] <= %02x\n", m_cfg_indx, data);
+ break;
+
+ case 0x0f: // Config Termination
+ m_cfg_state = 0;
+ LOG("CFG -- mode off --\n");
+
+ // install enabled devices
+ if (BIT(m_cfg_regs[0], GP))
+ {
+ //offs_t addr = m_cfg_regs[7] << 2;
+ //io_space.install_readwrite_handler(addr, addr + 1, emu::rw_delegate(*m_serial[0], FUNC(ins8250_device::ins8250_r)), emu::rw_delegate(*m_serial[0], FUNC(ins8250_device::ins8250_w)));
+ }
+ if (BIT(m_cfg_regs[0], S1))
+ {
+ offs_t addr = (m_cfg_regs[4] & 0xfe) << 2;
+ io_space.install_readwrite_handler(addr, addr + 7, emu::rw_delegate(*m_serial[0], FUNC(ins8250_device::ins8250_r)), emu::rw_delegate(*m_serial[0], FUNC(ins8250_device::ins8250_w)));
+ }
+ if (BIT(m_cfg_regs[0], S2))
+ {
+ offs_t addr = (m_cfg_regs[5] & 0xfe) << 2;
+ io_space.install_readwrite_handler(addr, addr + 7, emu::rw_delegate(*m_serial[1], FUNC(ins8250_device::ins8250_r)), emu::rw_delegate(*m_serial[1], FUNC(ins8250_device::ins8250_w)));
+ }
+ if (BIT(m_cfg_regs[0], PP))
+ {
+ offs_t addr = m_cfg_regs[6] << 2;
+ io_space.install_readwrite_handler(addr, addr + 3, emu::rw_delegate(*m_lpt, FUNC(pc_lpt_device::read)), emu::rw_delegate(*m_lpt, FUNC(pc_lpt_device::write)));
+ }
+ if (BIT(m_cfg_regs[0], RC))
+ {
+ offs_t addr = m_cfg_regs[3] << 2;
+ io_space.install_readwrite_handler(addr, addr + 1, emu::rw_delegate(*this, FUNC(p82c606_device::rtc_r)), emu::rw_delegate(*this, FUNC(p82c606_device::rtc_w)));
+ }
+ break;
+ }
+ }
+}
+
+
+u8 p82c606_device::rtc_r(offs_t offset)
+{
+ u8 data = 0x00;
+
+ if (offset & 1)
+ {
+ if (m_cmos_addr & 0x40)
+ data = m_cmos_ram[m_cmos_addr & 0x3f];
+ else
+ data = m_rtc->read_direct(m_cmos_addr & 0x3f);
+ }
+
+ return data;
+}
+
+void p82c606_device::rtc_w(offs_t offset, u8 data)
+{
+ if (offset & 1)
+ {
+ if (m_cmos_addr & 0x40)
+ m_cmos_ram[m_cmos_addr & 0x3f] = data;
+ else
+ m_rtc->write_direct(m_cmos_addr & 0x3f, data);
+ }
+ else
+ {
+ m_cmos_addr = data & 0x7f;
+ }
+}
+
+
+template <unsigned N>
+void p82c606_device::int_select(int state)
+{
+ switch (N)
+ {
+ case S1:
+ if (BIT(m_cfg_regs[8], 6, 2) == 2) m_irq3_callback(state);
+ if (BIT(m_cfg_regs[8], 4, 2) == 2) m_irq4_callback(state);
+ if (BIT(m_cfg_regs[8], 2, 2) == 2) m_irq5_callback(state);
+ break;
+
+ case S2:
+ if (BIT(m_cfg_regs[8], 6, 2) == 3) m_irq3_callback(state);
+ if (BIT(m_cfg_regs[8], 4, 2) == 3) m_irq4_callback(state);
+ if (BIT(m_cfg_regs[8], 0, 2) == 2) m_irq7_callback(state);
+ break;
+
+ case PP:
+ if (BIT(m_cfg_regs[8], 2, 2) == 3) m_irq5_callback(state);
+ if (BIT(m_cfg_regs[8], 0, 2) == 3) m_irq7_callback(state);
+ break;
+
+ case RC:
+ if (BIT(m_cfg_regs[8], 6, 2) == 1) m_irq3_callback(state);
+ if (BIT(m_cfg_regs[8], 4, 2) == 1) m_irq4_callback(state);
+ if (BIT(m_cfg_regs[8], 2, 2) == 1) m_irq5_callback(state);
+ if (BIT(m_cfg_regs[8], 0, 2) == 1) m_irq7_callback(state);
+ break;
+ }
+}
diff --git a/src/devices/machine/82c606.h b/src/devices/machine/82c606.h
new file mode 100644
index 00000000000..f2ec6a64781
--- /dev/null
+++ b/src/devices/machine/82c606.h
@@ -0,0 +1,105 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/**********************************************************************
+
+ Chips 82C606 CHIPSpak Multifunction Controller
+
+**********************************************************************/
+
+#ifndef MAME_MACHINE_82C606_H
+#define MAME_MACHINE_82C606_H
+
+#pragma once
+
+#include "machine/ins8250.h"
+#include "machine/mc146818.h"
+#include "machine/nvram.h"
+#include "machine/pc_lpt.h"
+
+
+class p82c606_device : public device_t
+{
+public:
+ // construction/destruction
+ p82c606_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+
+ template <typename T> void set_cpu_tag(T &&tag) { m_maincpu.set_tag(std::forward<T>(tag)); }
+
+ u8 cfg_r(offs_t offset, u8 mem_mask = ~0);
+ void cfg_w(offs_t offset, u8 data, u8 mem_mask = ~0);
+
+ auto irq3() { return m_irq3_callback.bind(); }
+ auto irq4() { return m_irq4_callback.bind(); }
+ auto irq5() { return m_irq5_callback.bind(); }
+ auto irq7() { return m_irq7_callback.bind(); }
+ auto txd1() { return m_txd1_callback.bind(); }
+ auto dtr1() { return m_dtr1_callback.bind(); }
+ auto rts1() { return m_rts1_callback.bind(); }
+ auto txd2() { return m_txd2_callback.bind(); }
+ auto dtr2() { return m_dtr2_callback.bind(); }
+ auto rts2() { return m_rts2_callback.bind(); }
+
+ // chip pins for uarts
+ void write_rxd1(int state) { m_serial[0]->rx_w(state); }
+ void write_dcd1(int state) { m_serial[0]->dcd_w(state); }
+ void write_dsr1(int state) { m_serial[0]->dsr_w(state); }
+ void write_ri1(int state) { m_serial[0]->ri_w(state); }
+ void write_cts1(int state) { m_serial[0]->cts_w(state); }
+ void write_rxd2(int state) { m_serial[1]->rx_w(state); }
+ void write_dcd2(int state) { m_serial[1]->dcd_w(state); }
+ void write_dsr2(int state) { m_serial[1]->dsr_w(state); }
+ void write_ri2(int state) { m_serial[1]->ri_w(state); }
+ void write_cts2(int state) { m_serial[1]->cts_w(state); }
+
+protected:
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_add_mconfig(machine_config &config) override ATTR_COLD;
+
+private:
+ void chipspak_w(offs_t offset, u8 data);
+
+ u8 rtc_r(offs_t offset);
+ void rtc_w(offs_t offset, u8 data);
+
+ template <unsigned N> void int_select(int state);
+
+ required_device<cpu_device> m_maincpu;
+ required_device<mc146818_device> m_rtc;
+ memory_share_creator<u8> m_cmos_ram;
+ required_device<nvram_device> m_nvram;
+ required_device<pc_lpt_device> m_lpt;
+ required_device_array<ns16450_device, 2> m_serial;
+
+ devcb_write_line m_irq3_callback; // UART2 (COM2)
+ devcb_write_line m_irq4_callback; // UART1 (COM1)
+ devcb_write_line m_irq5_callback; // Parallel port 2
+ devcb_write_line m_irq7_callback; // Parallel port 1
+
+ devcb_write_line m_txd1_callback;
+ devcb_write_line m_dtr1_callback;
+ devcb_write_line m_rts1_callback;
+ devcb_write_line m_txd2_callback;
+ devcb_write_line m_dtr2_callback;
+ devcb_write_line m_rts2_callback;
+
+ static constexpr int GP = 0; // Game Port
+ static constexpr int S1 = 1; // UART1
+ static constexpr int S2 = 2; // UART2
+ static constexpr int PP = 3; // Parallel Port
+ static constexpr int RC = 4; // RTC
+
+ u8 m_cfg_state = 0;
+ u8 m_cfg_key = 0x00;
+ u8 m_cfg_regs[16] = { 0 };
+ u8 m_cfg_indx = 0x00;
+ u16 m_cfg_cri = 0x00;
+
+ u8 m_cmos_addr = 0x00;
+};
+
+
+DECLARE_DEVICE_TYPE(P82C606, p82c606_device)
+
+#endif // MAME_MACHINE_82C606_H
diff --git a/src/devices/machine/psion_asic7.cpp b/src/devices/machine/psion_asic7.cpp
new file mode 100644
index 00000000000..09eaf82156e
--- /dev/null
+++ b/src/devices/machine/psion_asic7.cpp
@@ -0,0 +1,175 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/******************************************************************************
+
+ Psion ASIC7
+
+******************************************************************************/
+
+#include "emu.h"
+#include "psion_asic7.h"
+
+
+#define VERBOSE 0
+//#define LOG_OUTPUT_FUNC osd_printf_info
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(PSION_ASIC7, psion_asic7_device, "psion_asic7", "Psion ASIC7")
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+psion_asic7_device::psion_asic7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, PSION_ASIC7, tag, owner, clock)
+ , m_as2rd_callback(*this, 0)
+ , m_as2wr_callback(*this)
+ , m_pgsel_callback(*this)
+ , m_lcdcom_callback(*this)
+ , m_caps_callback(*this)
+ , m_numl_callback(*this)
+ , m_scrl_callback(*this)
+ , m_batt_callback(*this)
+ , m_stby_callback(*this)
+{
+}
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void psion_asic7_device::device_start()
+{
+ save_item(NAME(m_a7_control));
+ save_item(NAME(m_a7_key_command));
+ save_item(NAME(m_a7_access_key));
+}
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void psion_asic7_device::device_reset()
+{
+ m_a7_control = 0x08; // STBY
+ m_a7_key_command = 0x00;
+ m_a7_access_key = 0x00;
+
+ m_pgsel_callback(0);
+}
+
+
+//**************************************************************************
+// READ/WRITE HANDLERS
+//**************************************************************************
+
+uint8_t psion_asic7_device::io_r(offs_t offset, uint8_t mem_mask)
+{
+ uint8_t data = 0x00;
+
+ if (m_a7_access_key == 0x5aa5)
+ {
+ switch (offset & 8)
+ {
+ case 0x00:
+ data = m_as2rd_callback(offset);
+ break;
+
+ case 0x08:
+ switch (offset)
+ {
+ case 0x08: // System Control
+ // b0 RamEnable
+ // b1 PageSel
+ // b2 MaximEnable
+ // b3 StandEnable
+ // b4 CapsLockLcd
+ // b5 NumLockLcd
+ // b6 ScrlLockLcd
+ // b7 BatLowLcd
+ data = m_a7_control;
+ LOG("%s io_r: A7Control => %02x\n", machine().describe_context(), data);
+ break;
+
+ case 0x09: // Keyboard Command Busy Flag
+ // b0 KeyBusy
+ data = 0;
+ LOG("%s io_r: A7KeyStatus => %02x\n", machine().describe_context(), data);
+ break;
+ }
+ }
+ }
+ return data;
+}
+
+void psion_asic7_device::io_w(offs_t offset, uint8_t data, uint8_t mem_mask)
+{
+ if (m_a7_access_key == 0x5aa5 || (offset & 0x0e) == 0x0a)
+ {
+ switch (offset & 0x08)
+ {
+ case 0x00:
+ m_as2wr_callback(offset, data);
+ break;
+
+ case 0x08:
+ switch (offset)
+ {
+ case 0x08: // System Control
+ // b0 RamEnable
+ // b1 PageSel
+ // b2 MaximEnable
+ // b3 StandEnable
+ // b4 CapsLockLcd
+ // b5 NumLockLcd
+ // b6 ScrlLockLcd
+ // b7 BatLowLcd
+ LOG("%s io_w: A7Control <= %02x\n", machine().describe_context(), data);
+ m_pgsel_callback(BIT(data, 1));
+ m_lcdcom_callback(BIT(data, 2));
+ if (BIT(data, 3) != BIT(m_a7_control, 3))
+ m_stby_callback(BIT(data, 3));
+ if (BIT(data, 4) != BIT(m_a7_control, 4))
+ m_caps_callback(BIT(data, 4));
+ if (BIT(data, 5) != BIT(m_a7_control, 5))
+ m_numl_callback(BIT(data, 5));
+ if (BIT(data, 6) != BIT(m_a7_control, 6))
+ m_scrl_callback(BIT(data, 6));
+ if (BIT(data, 7) != BIT(m_a7_control, 7))
+ m_batt_callback(BIT(data, 7));
+ m_a7_control = data;
+ break;
+
+ case 0x09: // Keyboard Command
+ LOG("%s io_w: A7KeyCommand <= %02x\n", machine().describe_context(), data);
+ m_a7_key_command = data;
+ break;
+
+ case 0x0a: // Access Key 0
+ case 0x0b: // Access Key 1
+ LOG("%s io_w: A7KeyAccess%d <= %02x\n", machine().describe_context(), (offset & 1) + 1, data);
+ switch (offset & 1)
+ {
+ case 0:
+ m_a7_access_key = (m_a7_access_key & 0xff00) | (data << 0);
+ break;
+ case 1:
+ m_a7_access_key = (m_a7_access_key & 0x00ff) | (data << 8);
+ break;
+ }
+ break;
+ }
+ }
+ }
+}
+
+void psion_asic7_device::update_ramen()
+{
+ if (m_intr_state || m_nmi_state)
+ m_a7_control |= 0x01;
+ else
+ m_a7_control &= ~0x01;
+}
diff --git a/src/devices/machine/psion_asic7.h b/src/devices/machine/psion_asic7.h
new file mode 100644
index 00000000000..84efa3a47f5
--- /dev/null
+++ b/src/devices/machine/psion_asic7.h
@@ -0,0 +1,72 @@
+// license:BSD-3-Clause
+// copyright-holders:Nigel Barnes
+/******************************************************************************
+
+ Psion ASIC7
+
+******************************************************************************/
+
+#ifndef MAME_MACHINE_PSION_ASIC7_H
+#define MAME_MACHINE_PSION_ASIC7_H
+
+#pragma once
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// ======================> psion_asic7_device
+
+class psion_asic7_device : public device_t
+{
+public:
+ // construction/destruction
+ psion_asic7_device(const machine_config &mconfig, const char* tag, device_t* owner, uint32_t clock);
+
+ auto as2rd() { return m_as2rd_callback.bind(); }
+ auto as2wr() { return m_as2wr_callback.bind(); }
+ auto pgsel() { return m_pgsel_callback.bind(); }
+ auto lcdcom() { return m_lcdcom_callback.bind(); }
+ auto caps() { return m_caps_callback.bind(); }
+ auto numl() { return m_numl_callback.bind(); }
+ auto scrl() { return m_scrl_callback.bind(); }
+ auto batt() { return m_batt_callback.bind(); }
+ auto stby() { return m_stby_callback.bind(); }
+
+ uint8_t io_r(offs_t offset, uint8_t mem_mask);
+ void io_w(offs_t offset, uint8_t data, uint8_t mem_mask);
+
+ void intr_w(int state) { m_intr_state = state; update_ramen(); };
+ void nmi_w(int state) { m_nmi_state = state; update_ramen(); };
+
+protected:
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+private:
+ void update_ramen();
+
+ devcb_read8 m_as2rd_callback;
+ devcb_write8 m_as2wr_callback;
+ devcb_write_line m_pgsel_callback;
+ devcb_write_line m_lcdcom_callback;
+ devcb_write_line m_caps_callback;
+ devcb_write_line m_numl_callback;
+ devcb_write_line m_scrl_callback;
+ devcb_write_line m_batt_callback;
+ devcb_write_line m_stby_callback;
+
+ uint8_t m_a7_control;
+ uint8_t m_a7_key_command;
+ uint16_t m_a7_access_key;
+
+ int m_intr_state;
+ int m_nmi_state;
+};
+
+
+// device type definition
+DECLARE_DEVICE_TYPE(PSION_ASIC7, psion_asic7_device)
+
+#endif // MAME_MACHINE_PSION_ASIC7_H