From a32b70c03472c0bddbc280ebd69fe9e75593c0e2 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sun, 18 Dec 2022 22:21:33 +1100 Subject: More Micom Soft controller wrangling: * bus/msx/ctrl: Added XE-1AP pad with defaults for personal computers. * bus/pce_ctrl: Added XHE-3 PC joystick adapter. --- scripts/src/bus.lua | 44 ++--- scripts/src/machine.lua | 12 ++ src/devices/bus/msx/ctrl/ctrl.cpp | 2 + src/devices/bus/msx/ctrl/xe1ap.cpp | 101 ++++++++++++ src/devices/bus/msx/ctrl/xe1ap.h | 19 +++ src/devices/bus/pce_ctrl/joypad2.cpp | 93 +++++++++-- src/devices/bus/pce_ctrl/joypad2.h | 75 +-------- src/devices/bus/pce_ctrl/pcectrl.cpp | 6 +- src/devices/bus/pce_ctrl/xhe3.cpp | 92 +++++++++++ src/devices/bus/pce_ctrl/xhe3.h | 18 ++ src/devices/bus/sms_ctrl/xe1ap.cpp | 307 ++++++----------------------------- src/devices/machine/micomxe1a.cpp | 278 +++++++++++++++++++++++++++++++ src/devices/machine/micomxe1a.h | 49 ++++++ 13 files changed, 733 insertions(+), 363 deletions(-) create mode 100644 src/devices/bus/msx/ctrl/xe1ap.cpp create mode 100644 src/devices/bus/msx/ctrl/xe1ap.h create mode 100644 src/devices/bus/pce_ctrl/xhe3.cpp create mode 100644 src/devices/bus/pce_ctrl/xhe3.h create mode 100644 src/devices/machine/micomxe1a.cpp create mode 100644 src/devices/machine/micomxe1a.h diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index d25711e9585..e954b19dc20 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1839,6 +1839,8 @@ if (BUSES["MSX_CTRL"]~=null) then MAME_DIR .. "src/devices/bus/msx/ctrl/towns6b.h", MAME_DIR .. "src/devices/bus/msx/ctrl/townspad.cpp", MAME_DIR .. "src/devices/bus/msx/ctrl/townspad.h", + MAME_DIR .. "src/devices/bus/msx/ctrl/xe1ap.cpp", + MAME_DIR .. "src/devices/bus/msx/ctrl/xe1ap.h", } end @@ -4053,6 +4055,28 @@ if (BUSES["PCE"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/bus/pce_ctrl/pcectrl.h,BUSES["PCE_CTRL"] = true +--------------------------------------------------- + +if (BUSES["PCE_CTRL"]~=null) then + files { + MAME_DIR .. "src/devices/bus/pce_ctrl/pcectrl.cpp", + MAME_DIR .. "src/devices/bus/pce_ctrl/pcectrl.h", + MAME_DIR .. "src/devices/bus/pce_ctrl/joypad2.cpp", + MAME_DIR .. "src/devices/bus/pce_ctrl/joypad2.h", + MAME_DIR .. "src/devices/bus/pce_ctrl/joypad6.cpp", + MAME_DIR .. "src/devices/bus/pce_ctrl/joypad6.h", + MAME_DIR .. "src/devices/bus/pce_ctrl/multitap.cpp", + MAME_DIR .. "src/devices/bus/pce_ctrl/multitap.h", + MAME_DIR .. "src/devices/bus/pce_ctrl/pachinko.cpp", + MAME_DIR .. "src/devices/bus/pce_ctrl/pachinko.h", + MAME_DIR .. "src/devices/bus/pce_ctrl/xhe3.cpp", + MAME_DIR .. "src/devices/bus/pce_ctrl/xhe3.h", + } +end + --------------------------------------------------- -- --@src/devices/bus/scv/slot.h,BUSES["SCV"] = true @@ -5078,26 +5102,6 @@ if (BUSES["THOMSON"]~=null) then } end ---------------------------------------------------- --- ---@src/devices/bus/pce_ctrl/pcectrl.h,BUSES["PCE_CTRL"] = true ---------------------------------------------------- - -if (BUSES["PCE_CTRL"]~=null) then - files { - MAME_DIR .. "src/devices/bus/pce_ctrl/pcectrl.cpp", - MAME_DIR .. "src/devices/bus/pce_ctrl/pcectrl.h", - MAME_DIR .. "src/devices/bus/pce_ctrl/joypad2.cpp", - MAME_DIR .. "src/devices/bus/pce_ctrl/joypad2.h", - MAME_DIR .. "src/devices/bus/pce_ctrl/joypad6.cpp", - MAME_DIR .. "src/devices/bus/pce_ctrl/joypad6.h", - MAME_DIR .. "src/devices/bus/pce_ctrl/multitap.cpp", - MAME_DIR .. "src/devices/bus/pce_ctrl/multitap.h", - MAME_DIR .. "src/devices/bus/pce_ctrl/pachinko.cpp", - MAME_DIR .. "src/devices/bus/pce_ctrl/pachinko.h", - } -end - --------------------------------------------------- -- --@src/devices/bus/pc8801/pc8801_31.h,BUSES["PC8801"] = true diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index d4a23022e4c..4439cfd339f 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -5101,3 +5101,15 @@ if (MACHINES["AM9516"]~=null) then MAME_DIR .. "src/devices/machine/am9516.h", } end + +--------------------------------------------------- +-- +--@src/devices/machine/micomxe1a.h,MACHINES["MICOMXE1A"] = true +--------------------------------------------------- + +if (MACHINES["MICOMXE1A"]~=null) then + files { + MAME_DIR .. "src/devices/machine/micomxe1a.cpp", + MAME_DIR .. "src/devices/machine/micomxe1a.h", + } +end diff --git a/src/devices/bus/msx/ctrl/ctrl.cpp b/src/devices/bus/msx/ctrl/ctrl.cpp index e2981e1adc0..68139c0f625 100644 --- a/src/devices/bus/msx/ctrl/ctrl.cpp +++ b/src/devices/bus/msx/ctrl/ctrl.cpp @@ -16,6 +16,7 @@ #include "sgadapt.h" #include "towns6b.h" #include "townspad.h" +#include "xe1ap.h" DEFINE_DEVICE_TYPE(MSX_GENERAL_PURPOSE_PORT, msx_general_purpose_port_device, "msx_general_purpose_port", "MSX General Purpose port") @@ -52,4 +53,5 @@ void msx_general_purpose_port_devices(device_slot_interface &device) device.option_add("sega", MSX_SEGACTRL); device.option_add("towns6b", MSX_TOWNS6B); device.option_add("townspad", MSX_TOWNSPAD); + device.option_add("xe1ap", MSX_XE1AP); } diff --git a/src/devices/bus/msx/ctrl/xe1ap.cpp b/src/devices/bus/msx/ctrl/xe1ap.cpp new file mode 100644 index 00000000000..8badb0cb997 --- /dev/null +++ b/src/devices/bus/msx/ctrl/xe1ap.cpp @@ -0,0 +1,101 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Dempa Micom Soft Analog/Digital Controller XE-1AP emulation + +**********************************************************************/ + +#include "emu.h" +#include "xe1ap.h" + +#include "machine/micomxe1a.h" + + +namespace { + +INPUT_PORTS_START(xe1ap) + PORT_START("BUTTONS") + PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("%p D") // left shoulder lower + PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("%p C") // left shoulder upper + PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p B") // right shoulder lower + PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p A") // right shoulder upper + PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_SELECT) // left face bottom + PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_START) // right face bottom + PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("%p E2") // left face top inner + PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("%p E1") // left face top outer + PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_BUTTON8) PORT_NAME("%p B'") // right face top inner + PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_BUTTON7) PORT_NAME("%p A'") // right face top outer + PORT_BIT(0xfc00, IP_ACTIVE_LOW, IPT_UNUSED) + + PORT_START("CH0") + PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(50) + + PORT_START("CH1") + PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_SENSITIVITY(50) PORT_KEYDELTA(50) + + PORT_START("CH2") + PORT_BIT(0xff, 0x80, IPT_PADDLE_V) PORT_REVERSE PORT_SENSITIVITY(50) PORT_KEYDELTA(50) + + PORT_START("CH3") + PORT_BIT(0xff, 0x00, IPT_UNUSED) + + PORT_START("MODE") + PORT_CONFNAME(0x01, 0x01, "Mode") PORT_WRITE_LINE_DEVICE_MEMBER("xe1", micom_xe_1a_device, mode_w) + PORT_CONFSETTING( 0x00, "Digital") + PORT_CONFSETTING( 0x01, "Analog") + PORT_CONFNAME(0x02, 0x00, "Interface") PORT_WRITE_LINE_DEVICE_MEMBER("xe1", micom_xe_1a_device, interface_w) + PORT_CONFSETTING( 0x00, "Personal Computer") + PORT_CONFSETTING( 0x02, "MD") +INPUT_PORTS_END + + +class xe1ap_device : public device_t, public device_msx_general_purpose_port_interface +{ +public: + xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) ATTR_COLD; + + virtual u8 read() override { return m_xe1->out_r() | 0xc0; } + virtual void pin_8_w(int state) override { m_xe1->req_w(state); } + +protected: + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual ioport_constructor device_input_ports() const override ATTR_COLD { return INPUT_PORTS_NAME(xe1ap); } + virtual void device_start() override ATTR_COLD { } + virtual void device_reset() override ATTR_COLD; + +private: + u8 read_channel(offs_t offset) { return m_axes[offset]->read(); } + + required_device m_xe1; + required_ioport_array<4> m_axes; + required_ioport m_mode; +}; + +xe1ap_device::xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, MSX_XE1AP, tag, owner, clock), + device_msx_general_purpose_port_interface(mconfig, *this), + m_xe1(*this, "xe1"), + m_axes(*this, "CH%u", 0U), + m_mode(*this, "MODE") +{ +} + +void xe1ap_device::device_add_mconfig(machine_config &config) +{ + MICOM_XE_1A(config, m_xe1); + m_xe1->buttons_handler().set_ioport("BUTTONS"); + m_xe1->analog_handler().set(FUNC(xe1ap_device::read_channel)); +} + +void xe1ap_device::device_reset() +{ + auto const mode = m_mode->read(); + m_xe1->mode_w(BIT(mode, 0)); + m_xe1->interface_w(BIT(mode, 1)); +} + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(MSX_XE1AP, device_msx_general_purpose_port_interface, xe1ap_device, "msx_xe1ap", "Dempa Micom Soft Analog Controller (XE-1AP, PC)") diff --git a/src/devices/bus/msx/ctrl/xe1ap.h b/src/devices/bus/msx/ctrl/xe1ap.h new file mode 100644 index 00000000000..515394b71fa --- /dev/null +++ b/src/devices/bus/msx/ctrl/xe1ap.h @@ -0,0 +1,19 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Dempa Micom Soft Analog/Digital Controller XE-1AP emulation + +**********************************************************************/ + +#ifndef MAME_BUS_MSX_CTRL_XE1AP_H +#define MAME_BUS_MSX_CTRL_XE1AP_H + +#pragma once + +#include "ctrl.h" + + +DECLARE_DEVICE_TYPE(MSX_XE1AP, device_msx_general_purpose_port_interface) + +#endif // MAME_BUS_MSX_CTRL_XE1AP_H diff --git a/src/devices/bus/pce_ctrl/joypad2.cpp b/src/devices/bus/pce_ctrl/joypad2.cpp index 2da64ed49ce..7e07f827b56 100644 --- a/src/devices/bus/pce_ctrl/joypad2.cpp +++ b/src/devices/bus/pce_ctrl/joypad2.cpp @@ -33,22 +33,17 @@ #include "emu.h" #include "joypad2.h" +#include "machine/74157.h" -//************************************************************************** -// DEVICE DEFINITIONS -//************************************************************************** - -DEFINE_DEVICE_TYPE(PCE_JOYPAD2, pce_joypad2_device, "pce_joypad2", "NEC PC Engine Pad") -DEFINE_DEVICE_TYPE(PCE_JOYPAD2_TURBO, pce_joypad2_turbo_device, "pce_joypad2_turbo", "NEC PC Engine/TurboGrafx-16 2 Button Joypad") - +namespace { -static INPUT_PORTS_START( pce_joypad2 ) +INPUT_PORTS_START( pce_joypad2 ) // II is left of I on the original pad so we map them in reverse order PORT_START("BUTTONS") PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p Button I") PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p Button II") - PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT ) PORT_NAME("%p Select") + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT ) PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("%p Run") PORT_START("DIRECTION") @@ -59,7 +54,7 @@ static INPUT_PORTS_START( pce_joypad2 ) INPUT_PORTS_END -static INPUT_PORTS_START( pce_joypad2_turbo ) +INPUT_PORTS_START( pce_joypad2_turbo ) PORT_INCLUDE( pce_joypad2 ) PORT_START("TURBO") @@ -74,6 +69,73 @@ static INPUT_PORTS_START( pce_joypad2_turbo ) INPUT_PORTS_END +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> pce_joypad2_device + +class pce_joypad2_device : public device_t, public device_pce_control_port_interface +{ +public: + // construction/destruction + pce_joypad2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // construction/destruction + pce_joypad2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); + + // optional information overrides + virtual ioport_constructor device_input_ports() const override; + + // device-level overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + + // device_pce_control_port_interface overrides + virtual u8 peripheral_r() override; + virtual void sel_w(int state) override; + virtual void clr_w(int state) override; + + // devices + required_device m_muxer; +}; + + +// ======================> pce_joypad2_turbo_device + +class pce_joypad2_turbo_device : public pce_joypad2_device +{ +public: + // construction/destruction + pce_joypad2_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + // optional information overrides + virtual ioport_constructor device_input_ports() const override; + + // device-level overrides + virtual void device_add_mconfig(machine_config &config) override; + virtual void device_start() override; + virtual void device_reset() override; + + // device_pce_control_port_interface overrides + virtual void clr_w(int state) override; + +private: + u8 buttons_r(); + + // IO ports + required_ioport m_buttons_io; + required_ioport m_turbo_io; + + // internal states + u8 m_counter; // Turbo rate counter, connected on 74xx163 QB and QC. + bool m_prev_clr; // previous CLR pin state +}; + + + //------------------------------------------------- // input_ports - device-specific input ports //------------------------------------------------- @@ -242,3 +304,14 @@ u8 pce_joypad2_turbo_device::buttons_r() } return ret; } + +} // anonymous namespace + + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE_PRIVATE(PCE_JOYPAD2, device_pce_control_port_interface, pce_joypad2_device, "pce_joypad2", "NEC PC Engine Pad") +DEFINE_DEVICE_TYPE_PRIVATE(PCE_JOYPAD2_TURBO, device_pce_control_port_interface, pce_joypad2_turbo_device, "pce_joypad2_turbo", "NEC PC Engine/TurboGrafx-16 2 Button Joypad") diff --git a/src/devices/bus/pce_ctrl/joypad2.h b/src/devices/bus/pce_ctrl/joypad2.h index 13fc0cbe7de..2ad0e2727ec 100644 --- a/src/devices/bus/pce_ctrl/joypad2.h +++ b/src/devices/bus/pce_ctrl/joypad2.h @@ -5,87 +5,16 @@ NEC PC Engine/TurboGrafx-16 2 Button Joypad emulation **********************************************************************/ - #ifndef MAME_BUS_PCE_CTRL_JOYPAD2_H #define MAME_BUS_PCE_CTRL_JOYPAD2_H #pragma once - -#include "machine/74157.h" #include "pcectrl.h" - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -// ======================> pce_joypad2_device - -class pce_joypad2_device : public device_t, - public device_pce_control_port_interface -{ -public: - // construction/destruction - pce_joypad2_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - -protected: - // construction/destruction - pce_joypad2_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); - - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - - // device-level overrides - virtual void device_add_mconfig(machine_config &config) override; - virtual void device_start() override; - - // device_pce_control_port_interface overrides - virtual u8 peripheral_r() override; - virtual void sel_w(int state) override; - virtual void clr_w(int state) override; - - // devices - required_device m_muxer; -}; - -// ======================> pce_joypad2_turbo_device - -class pce_joypad2_turbo_device : public pce_joypad2_device -{ -public: - // construction/destruction - pce_joypad2_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); - -protected: - // optional information overrides - virtual ioport_constructor device_input_ports() const override; - - // device-level overrides - virtual void device_add_mconfig(machine_config &config) override; - virtual void device_start() override; - virtual void device_reset() override; - - // device_pce_control_port_interface overrides - virtual void clr_w(int state) override; - -private: - u8 buttons_r(); - - // IO ports - required_ioport m_buttons_io; - required_ioport m_turbo_io; - - // internal states - u8 m_counter; // Turbo rate counter, connected on 74xx163 QB and QC. - bool m_prev_clr; // previous CLR pin state -}; - - // device type definition -DECLARE_DEVICE_TYPE(PCE_JOYPAD2, pce_joypad2_device) -DECLARE_DEVICE_TYPE(PCE_JOYPAD2_TURBO, pce_joypad2_turbo_device) - +DECLARE_DEVICE_TYPE(PCE_JOYPAD2, device_pce_control_port_interface) +DECLARE_DEVICE_TYPE(PCE_JOYPAD2_TURBO, device_pce_control_port_interface) #endif // MAME_BUS_PCE_CTRL_JOYPAD2_H diff --git a/src/devices/bus/pce_ctrl/pcectrl.cpp b/src/devices/bus/pce_ctrl/pcectrl.cpp index 71e2d9db525..6ed8f3c5acd 100644 --- a/src/devices/bus/pce_ctrl/pcectrl.cpp +++ b/src/devices/bus/pce_ctrl/pcectrl.cpp @@ -51,14 +51,16 @@ **********************************************************************/ #include "emu.h" -#include "screen.h" #include "pcectrl.h" +#include "screen.h" + // slot devices #include "joypad2.h" #include "joypad6.h" #include "multitap.h" #include "pachinko.h" +#include "xhe3.h" @@ -176,6 +178,8 @@ void pce_control_port_devices(device_slot_interface &device) device.option_add("multitap", PCE_MULTITAP); device.option_add("pachinko", PCE_PACHINKO); + + device.option_add("pcjoy", PCE_XHE3); // 3 Button Joypad/Joysticks (ex: Avenue Pad 3) // PC Engine Mouse (PI-PD10) // Memory Base 128 (PI-AD19) diff --git a/src/devices/bus/pce_ctrl/xhe3.cpp b/src/devices/bus/pce_ctrl/xhe3.cpp new file mode 100644 index 00000000000..db73882e0fc --- /dev/null +++ b/src/devices/bus/pce_ctrl/xhe3.cpp @@ -0,0 +1,92 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*********************************************************************** + + Micom Soft XHE-3 PC Joystick Adapter for PC Engine emuation + +***********************************************************************/ + +#include "emu.h" +#include "xhe3.h" + +#include "bus/msx/ctrl/ctrl.h" + + +namespace { + +INPUT_PORTS_START( pce_xhe3 ) + PORT_START("BUTTONS") // using IPT_START/IPT_SELECT would steal a player index + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Select") + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_OTHER) PORT_NAME("Run") +INPUT_PORTS_END + + + +class pce_xhe3_device : public device_t, public device_pce_control_port_interface +{ +public: + pce_xhe3_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + virtual u8 peripheral_r() override; + virtual void sel_w(int state) override; + virtual void clr_w(int state) override; + +protected: + virtual void device_add_mconfig(machine_config &config) override; + virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(pce_xhe3); } + virtual void device_start() override; + +private: + required_device m_port; + required_ioport m_buttons; + + u8 m_sel_in; +}; + + +pce_xhe3_device::pce_xhe3_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, PCE_XHE3, tag, owner, clock), + device_pce_control_port_interface(mconfig, *this), + m_port(*this, "joy"), + m_buttons(*this, "BUTTONS"), + m_sel_in(1) +{ +} + + +u8 pce_xhe3_device::peripheral_r() +{ + if (m_sel_in) + return bitswap<4>(m_port->read(), 2, 1, 3, 0); + else + return bitswap<2>(m_port->read(), 5, 4) | (m_buttons->read() << 2); +} + + +void pce_xhe3_device::sel_w(int state) +{ + m_sel_in = state ? 1 : 0; +} + + +void pce_xhe3_device::clr_w(int state) +{ + m_port->pin_8_w(state); +} + + +void pce_xhe3_device::device_add_mconfig(machine_config &config) +{ + MSX_GENERAL_PURPOSE_PORT(config, m_port, msx_general_purpose_port_devices, "xe1ap"); +} + + +void pce_xhe3_device::device_start() +{ + save_item(NAME(m_sel_in)); +} + +} // anonymous namespace + + +DEFINE_DEVICE_TYPE_PRIVATE(PCE_XHE3, device_pce_control_port_interface, pce_xhe3_device, "pce_xhe3", "Micom Soft XHE-3 PC Joystick Adapter for PC Engine") diff --git a/src/devices/bus/pce_ctrl/xhe3.h b/src/devices/bus/pce_ctrl/xhe3.h new file mode 100644 index 00000000000..86323dd08a9 --- /dev/null +++ b/src/devices/bus/pce_ctrl/xhe3.h @@ -0,0 +1,18 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*********************************************************************** + + Micom Soft XHE-3 PC Joystick Adapter for PC Engine emuation + +***********************************************************************/ +#ifndef MAME_BUS_PCE_CTRL_XHE3_H +#define MAME_BUS_PCE_CTRL_XHE3_H + +#pragma once + +#include "pcectrl.h" + + +DECLARE_DEVICE_TYPE(PCE_XHE3, device_pce_control_port_interface) + +#endif // MAME_BUS_PCE_CTRL_XHE3_H diff --git a/src/devices/bus/sms_ctrl/xe1ap.cpp b/src/devices/bus/sms_ctrl/xe1ap.cpp index 88fb3589025..f29d6a53e24 100644 --- a/src/devices/bus/sms_ctrl/xe1ap.cpp +++ b/src/devices/bus/sms_ctrl/xe1ap.cpp @@ -4,129 +4,29 @@ Dempa Micom Soft Analog/Digital Controller XE-1AP emulation - PC pin Name MD pin Name Dir Signal - 1 Up 1 Up In D0 - 2 Down 2 Down In D1 - 3 Left 3 Left In D2 - 4 Right 4 Right In D3 - 6 TRIG1 6 TL In L/H - 7 TRIG2 9 TR In Ack - 8 STROBE 7 TH Out Req - - In analog mode, data is shifted out as eleven nybbles: - - _ ____________________________________________ - Req \_________/ - ____ __ __ __ __ __ __ __ __ - Ack \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ - _____ _____ _____ _____ - L/H XX\____/ \_____/ \_____/ \_____/ \_____/ - ____ _____ _____ _____ _____ _____ _____ _____ _____ - D XXX____X_____X_____X_____X_____X_____X_____X_____X_____X - - The falling edge on Req causes data output to start. The host - can't control the speed, it just polls the L/H and Ack lines to - know when the data is ready to read. - - Step D0 D1 D2 D3 - 1 Select Start B' A' - 2 D C B A - 2 X4 X5 X6 X7 - 3 Y4 Y5 Y6 Y7 - 5 RZ4 RZ5 RZ6 RZ7 - 6 Z4 Z5 Z6 Z7 - 7 X0 X1 X2 X3 - 8 Y0 Y1 Y2 Y3 - 9 RZ0 RZ1 RZ2 RZ3 - 10 Z0 Z1 Z2 Z3 - 11 E2 E1 - - - - In digital mode, Req is a simple multiplexer input: - - Req 0 1 - D0 Up Throttle Up - D1 Down Throttle Down - D2 Left C - D3 Right D - L/H A E1 - Ack B E2 - - Start appears as simultaneous Left/Right - Select appears as simultaneous Up/Down - - This mode is almost compatible with a 6-button Towns Pad (on a - real 6-button Towns Pad, buttons A and B can be read in either - state, they bypass the multiplexer). - - TODO: - * Measure timings. - * Confirm reported value for unused analog channel 4. - * Confirm A', B', E1 and E2 bit mappings in analog mode. - * Confirm buttons mapping in digital mode. - - Is the mapping different in PC vs MD mode? - * Implement trigger A/B rapid fire switches. - * Implement channel shift switch (Y->X, X->Z, Z->X). - * Implement special modes (holding buttons on power-on): - - Double displacement modes: - + X/Y (hold SELECT + A') - + Z (hold SELECT + B') - + X/Y/Z (hold SELECT + A' + B') - - Up/down reverse mode (hold C) - **********************************************************************/ #include "emu.h" #include "xe1ap.h" -//#define VERBOSE 1 -//#define LOG_OUTPUT_FUNC osd_printf_info -#include "logmacro.h" +#include "machine/micomxe1a.h" namespace { -class sms_xe1ap_device : public device_t, public device_sms_control_interface -{ -public: - sms_xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); - - virtual u8 in_r() override; - virtual void out_w(u8 data, u8 mem_mask) override; - - DECLARE_INPUT_CHANGED_MEMBER(mode_changed); - -protected: - virtual ioport_constructor device_input_ports() const override; - virtual void device_start() override; - -private: - TIMER_CALLBACK_MEMBER(step_output); - - required_ioport m_buttons; - required_ioport_array<4> m_axes; - required_ioport m_mode; - - emu_timer *m_output_timer; - - u8 m_req; - u8 m_out; -}; - - - INPUT_PORTS_START( sms_xe1ap ) PORT_START("BUTTONS") - PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_SELECT) // left face bottom - PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_START) // right face bottom - PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("%p B'") // right face top inner - PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("%p A'") // right face top outer - PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("%p D") // left shoulder lower - PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("%p C") // left shoulder upper - PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p B") // right shoulder lower - PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p A") // right shoulder upper - PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_BUTTON8) PORT_NAME("%p E2") // left face top inner - PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_BUTTON7) PORT_NAME("%p E1") // left face top outer - PORT_BIT(0x0c00, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x0001, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_NAME("%p D") // left shoulder lower + PORT_BIT(0x0002, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("%p C") // left shoulder upper + PORT_BIT(0x0004, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("%p B") // right shoulder lower + PORT_BIT(0x0008, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("%p A") // right shoulder upper + PORT_BIT(0x0010, IP_ACTIVE_LOW, IPT_SELECT) // left face bottom + PORT_BIT(0x0020, IP_ACTIVE_LOW, IPT_START) // right face bottom + PORT_BIT(0x0040, IP_ACTIVE_LOW, IPT_BUTTON6) PORT_NAME("%p E2") // left face top inner + PORT_BIT(0x0080, IP_ACTIVE_LOW, IPT_BUTTON5) PORT_NAME("%p E1") // left face top outer + PORT_BIT(0x0100, IP_ACTIVE_LOW, IPT_BUTTON8) PORT_NAME("%p B'") // right face top inner + PORT_BIT(0x0200, IP_ACTIVE_LOW, IPT_BUTTON7) PORT_NAME("%p A'") // right face top outer + PORT_BIT(0xfc00, IP_ACTIVE_LOW, IPT_UNUSED) PORT_START("CH0") PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(50) @@ -138,181 +38,70 @@ INPUT_PORTS_START( sms_xe1ap ) PORT_BIT(0xff, 0x80, IPT_PADDLE_V) PORT_REVERSE PORT_SENSITIVITY(50) PORT_KEYDELTA(50) PORT_START("CH3") - PORT_BIT(0xff, 0x80, IPT_UNUSED) + PORT_BIT(0xff, 0x00, IPT_UNUSED) PORT_START("MODE") - PORT_CONFNAME(0x01, 0x01, "Mode") PORT_CHANGED_MEMBER(DEVICE_SELF, sms_xe1ap_device, mode_changed, 0) + PORT_CONFNAME(0x01, 0x01, "Mode") PORT_WRITE_LINE_DEVICE_MEMBER("xe1", micom_xe_1a_device, mode_w) PORT_CONFSETTING( 0x00, "Digital") PORT_CONFSETTING( 0x01, "Analog") + PORT_CONFNAME(0x02, 0x02, "Interface") PORT_WRITE_LINE_DEVICE_MEMBER("xe1", micom_xe_1a_device, interface_w) + PORT_CONFSETTING( 0x00, "Personal Computer") + PORT_CONFSETTING( 0x02, "MD") INPUT_PORTS_END -sms_xe1ap_device::sms_xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : - device_t(mconfig, SMS_XE1AP, tag, owner, clock), - device_sms_control_interface(mconfig, *this), - m_buttons(*this, "BUTTONS"), - m_axes(*this, "CH%u", 0U), - m_mode(*this, "MODE"), - m_output_timer(nullptr), - m_req(1), - m_out(0x3f) +class sms_xe1ap_device : public device_t, public device_sms_control_interface { -} - +public: + sms_xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) ATTR_COLD; -u8 sms_xe1ap_device::in_r() -{ - if (BIT(m_mode->read(), 0)) - { - LOG( - "%s: analog mode read data = %02X\n", - machine().describe_context(), - m_out); - return m_out; - } - else - { - u16 const buttons = m_buttons->read(); - if (m_req) - { - u8 const x = m_axes[0]->read(); - u8 const y = m_axes[1]->read(); - u8 const result = - ((BIT(buttons, 0) && (0x40 <= y)) ? 0x01 : 0x00) | // Select/Up - ((BIT(buttons, 0) && (0xc0 > y)) ? 0x02 : 0x00) | // Select/Down - ((BIT(buttons, 1) && (0x40 <= x)) ? 0x04 : 0x00) | // Start/Left - ((BIT(buttons, 1) && (0xc0 > x)) ? 0x08 : 0x00) | // Start/Right - (BIT(buttons, 7) << 4) | // A - (BIT(buttons, 6) << 5); // B - LOG( - "%s: digital mode basic read = 0x%02X\n", - machine().describe_context(), - result); - return result; - } - else - { - u8 const z = m_axes[3]->read(); - u8 const result = - ((0xc0 > z) ? 0x01 : 0x00) | // Throttle Up - ((0x40 <= z) ? 0x02 : 0x00) | // Throttle Down - (BIT(buttons, 5) << 2) | // C - (BIT(buttons, 4) << 3) | // D - (BIT(buttons, 9) << 4) | // E1 - (BIT(buttons, 8) << 5); // E2 - LOG( - "%s: digital mode extended read = 0x%02X\n", - machine().describe_context(), - result); - return result; - } - } -} + virtual u8 in_r() override { return m_xe1->out_r(); } + virtual void out_w(u8 data, u8 mem_mask) override { m_xe1->req_w(BIT(data, 6)); } +protected: + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; + virtual ioport_constructor device_input_ports() const override ATTR_COLD { return INPUT_PORTS_NAME(sms_xe1ap); } + virtual void device_start() override ATTR_COLD { } + virtual void device_reset() override ATTR_COLD; -void sms_xe1ap_device::out_w(u8 data, u8 mem_mask) -{ - u8 const req = BIT(data, 6); - if (req != m_req) - { - if (BIT(m_mode->read(), 0)) - { - LOG("%s: /Req = %u\n", machine().describe_context(), req); - if (!req) - m_output_timer->adjust(attotime::from_usec(4), 0); - } - else - { - LOG("%s: /Req = %u ignored in digital mode\n", machine().describe_context(), req); - } - m_req = req; - } -} +private: + u8 read_channel(offs_t offset) { return m_axes[offset]->read(); } + required_device m_xe1; + required_ioport_array<4> m_axes; + required_ioport m_mode; +}; -INPUT_CHANGED_MEMBER(sms_xe1ap_device::mode_changed) -{ - if (newval) - { - LOG("Analog mode selected\n"); - } - else - { - LOG("Digital mode selected\n"); - m_output_timer->enable(false); - m_out = 0x3f; - } -} -ioport_constructor sms_xe1ap_device::device_input_ports() const +sms_xe1ap_device::sms_xe1ap_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : + device_t(mconfig, SMS_XE1AP, tag, owner, clock), + device_sms_control_interface(mconfig, *this), + m_xe1(*this, "xe1"), + m_axes(*this, "CH%u", 0U), + m_mode(*this, "MODE") { - return INPUT_PORTS_NAME(sms_xe1ap); } -void sms_xe1ap_device::device_start() +void sms_xe1ap_device::device_add_mconfig(machine_config &config) { - m_output_timer = timer_alloc(FUNC(sms_xe1ap_device::step_output), this); - - save_item(NAME(m_req)); - save_item(NAME(m_out)); + MICOM_XE_1A(config, m_xe1); + m_xe1->buttons_handler().set_ioport("BUTTONS"); + m_xe1->analog_handler().set(FUNC(sms_xe1ap_device::read_channel)); } -TIMER_CALLBACK_MEMBER(sms_xe1ap_device::step_output) +void sms_xe1ap_device::device_reset() { - if (!BIT(param, 0)) - { - auto const step = param >> 1; - if (12 > step) - { - switch (step) - { - case 0: - case 1: - m_out = BIT(m_buttons->read(), step ? 4 : 0, 4); - break; - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 9: - m_out = BIT(m_axes[((step - 2) & 0x03) ^ 0x01]->read(), (step < 6) ? 4 : 0, 4); - break; - case 10: - m_out = BIT(m_buttons->read(), 8, 4); - break; - default: - m_out = 0x0f; - } - m_out |= BIT(param, 1) ? 0x30 : 0x20; - LOG( - "Set nybble %u data = 0x%X, L/H = %d, /Ack = 1\n", - step, - BIT(m_out, 0, 4), - BIT(m_out, 4)); - m_output_timer->adjust(attotime::from_usec(4), param + 1); - } - else - { - m_out = 0x3f; - } - } - else - { - m_out &= 0x1f; - LOG("Set nybble %u /Ack = 0\n", param >> 1); - m_output_timer->adjust(attotime::from_usec(20), param + 1); - } + auto const mode = m_mode->read(); + m_xe1->mode_w(BIT(mode, 0)); + m_xe1->interface_w(BIT(mode, 1)); } } // anonymous namespace -DEFINE_DEVICE_TYPE_PRIVATE(SMS_XE1AP, device_sms_control_interface, sms_xe1ap_device, "sms_xe1ap", "Dempa Micom Soft Analog Controller (XE-1AP)") +DEFINE_DEVICE_TYPE_PRIVATE(SMS_XE1AP, device_sms_control_interface, sms_xe1ap_device, "sms_xe1ap", "Dempa Micom Soft Analog Controller (XE-1AP, Sega)") diff --git a/src/devices/machine/micomxe1a.cpp b/src/devices/machine/micomxe1a.cpp new file mode 100644 index 00000000000..1b94f9f0418 --- /dev/null +++ b/src/devices/machine/micomxe1a.cpp @@ -0,0 +1,278 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Dempa Micom Soft Analog/Digital Controller emulation + + PC pin Name MD pin Name Dir Signal + 1 Up 1 Up In D0 + 2 Down 2 Down In D1 + 3 Left 3 Left In D2 + 4 Right 4 Right In D3 + 6 TRIG1 6 TL In L/H + 7 TRIG2 9 TR In Ack + 8 STROBE 7 TH Out Req + + In analog mode, data is shifted out as eleven nybbles: + + _ ____________________________________________ + Req \_________/ + ____ __ __ __ __ __ __ __ __ + Ack \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ \__/ + _____ _____ _____ _____ + L/H XX\____/ \_____/ \_____/ \_____/ \_____/ + ____ _____ _____ _____ _____ _____ _____ _____ _____ + D XXX____X_____X_____X_____X_____X_____X_____X_____X_____X + + The falling edge on Req causes data output to start. The host + can't control the speed, it just polls the L/H and Ack lines to + know when the data is ready to read. + + Step D0 D1 D2 D3 + 1 D C B/B' A/A' + 2 Select Start E2 E1 + 3 Y4 Y5 Y6 Y7 + 4 X4 X5 X6 X7 + 5 Z4 Z5 Z6 Z7 + 6 RZ4 RZ5 RZ6 RZ7 + 7 Y0 Y1 Y2 Y3 + 8 X0 X1 X2 X3 + 9 Z0 Z1 Z2 Z3 + 10 RZ0 RZ1 RZ2 RZ3 + 11 B' A' B A + 12 - - - - + + In MD mode, each pair of nybbles is transmitted in reverse + order. + + In digital mode, Req is a simple multiplexer input: + + Req 0 1 + D0 Up Throttle Up + D1 Down Throttle Down + D2 Left C + D3 Right D + L/H A/A' E1 + Ack B/B' E2 + + Start appears as simultaneous Left/Right + Select appears as simultaneous Up/Down + + This mode is almost compatible with a 6-button Towns Pad (on a + real 6-button Towns Pad, buttons A and B can be read in either + state, they bypass the multiplexer). + + TODO: + * Dump MB88513 microcontroller from original controller. + * Measure timings. + * Latch data at beginning of packet. + * Confirm A', B', E1 and E2 bit mappings in analog mode. + * Confirm buttons mapping in digital mode. + - Is the mapping different in PC vs MD mode? + * Implement trigger A/B rapid fire switches. + * Implement channel shift switch (Y->X, X->Z, Z->X). + * Implement special modes (holding buttons on power-on): + - Double displacement modes: + + X/Y (hold SELECT + A') + + Z (hold SELECT + B') + + X/Y/Z (hold SELECT + A' + B') + - Up/down reverse mode (hold C) + * Implement desktop (XE-1AJ/CZ-8NJ2) version: + - Four analog channels + - E1/E2 on a rocker switch (can't press simultaneously) + - Hold mode for A and B triggers + - Variable rapid fire rate for A and B triggers + - Reset button + - Different special modes + - No Mega Drive mode + - Start and Select not reported in digital mode + +**********************************************************************/ + +#include "emu.h" +#include "micomxe1a.h" + +//#define VERBOSE 1 +//#define LOG_OUTPUT_FUNC osd_printf_info +#include "logmacro.h" + + +DEFINE_DEVICE_TYPE(MICOM_XE_1A, micom_xe_1a_device, "micom_xe_1a", "Dempa Micom Soft Analog/Digital Intelligent Controller") + + + +micom_xe_1a_device::micom_xe_1a_device( + machine_config const &mconfig, + char const *tag, + device_t *owner, + u32 clock): + device_t(mconfig, MICOM_XE_1A, tag, owner, clock), + m_buttons_callback(*this), + m_analog_callback(*this), + m_output_timer(nullptr), + m_req(1), + m_mode(1), + m_interface(0), + m_out(0x2e) +{ +} + + +u8 micom_xe_1a_device::out_r() +{ + if (m_mode) + { + LOG("%s: analog mode read data = %02X\n", machine().describe_context(), m_out); + return m_out; + } + else + { + u16 const buttons = m_buttons_callback(); + if (m_req) + { + u8 const z = m_analog_callback(2); + u8 const result = + ((0xc0 > z) ? 0x01 : 0x00) | // Throttle Up + ((0x40 <= z) ? 0x02 : 0x00) | // Throttle Down + (BIT(buttons, 1) << 2) | // C + (BIT(buttons, 0) << 3) | // D + (BIT(buttons, 7) << 4) | // E1 + (BIT(buttons, 6) << 5); // E2 + LOG( + "%s: digital mode extended read = 0x%02X\n", + machine().describe_context(), + result); + return result; + } + else + { + u8 const y = m_analog_callback(0); + u8 const x = m_analog_callback(1); + u8 const result = + ((BIT(buttons, 4) && (0x40 <= y)) ? 0x01 : 0x00) | // Select/Up + ((BIT(buttons, 4) && (0xc0 > y)) ? 0x02 : 0x00) | // Select/Down + ((BIT(buttons, 5) && (0x40 <= x)) ? 0x04 : 0x00) | // Start/Left + ((BIT(buttons, 5) && (0xc0 > x)) ? 0x08 : 0x00) | // Start/Right + ((BIT(buttons, 3) & BIT(buttons, 9)) << 4) | // A/A' + ((BIT(buttons, 2) & BIT(buttons, 8)) << 5); // B/B' + LOG( + "%s: digital mode basic read = 0x%02X\n", + machine().describe_context(), + result); + return result; + } + } +} + + +WRITE_LINE_MEMBER(micom_xe_1a_device::req_w) +{ + u8 const req = state ? 1 : 0; + if (req != m_req) + { + if (m_mode) + { + LOG("%s: /Req = %u\n", machine().describe_context(), req); + if (!req) + { + // acquire data + u16 const buttons = m_buttons_callback(); + u8 analog[4]; + for (unsigned i = 0; std::size(analog) > i; ++i) + analog[i] = m_analog_callback(i); + + // pack data + m_data[0] = BIT(buttons, 0, 8) & ((BIT(buttons, 8, 2) << 2) | 0xf3); + m_data[1] = BIT(analog[0], 4, 4) | (BIT(analog[1], 4, 4) << 4); + m_data[2] = BIT(analog[2], 4, 4) | (BIT(analog[3], 4, 4) << 4); + m_data[3] = BIT(analog[0], 0, 4) | (BIT(analog[1], 0, 4) << 4); + m_data[4] = BIT(analog[2], 0, 4) | (BIT(analog[3], 0, 4) << 4); + m_data[5] = BIT(buttons, 8, 8) & ((BIT(buttons, 6, 2) << 2) | 0xf3); + + // takes a while to respond + m_output_timer->adjust(attotime::from_nsec(46'600), 0); + } + } + else + { + LOG("%s: /Req = %u ignored in digital mode\n", machine().describe_context(), req); + } + m_req = req; + } +} + + +WRITE_LINE_MEMBER(micom_xe_1a_device::mode_w) +{ + u8 const mode = state ? 1 : 0; + if (mode != m_mode) + { + if (mode) + { + LOG("Analog mode selected\n"); + } + else + { + LOG("Digital mode selected\n"); + m_output_timer->enable(false); + m_out = 0x2e; + } + m_mode = mode; + } +} + + +WRITE_LINE_MEMBER(micom_xe_1a_device::interface_w) +{ + m_interface = state ? 1 : 0; +} + + +void micom_xe_1a_device::device_start() +{ + m_buttons_callback.resolve_safe(0xffff); + m_analog_callback.resolve_safe(0x00); + + m_output_timer = timer_alloc(FUNC(micom_xe_1a_device::step_output), this); + + std::fill(std::begin(m_data), std::end(m_data), 0x00); + m_out = 0x2e; + + save_item(NAME(m_req)); + save_item(NAME(m_mode)); + save_item(NAME(m_interface)); + save_item(NAME(m_data)); + save_item(NAME(m_out)); +} + + +TIMER_CALLBACK_MEMBER(micom_xe_1a_device::step_output) +{ + auto const step = param >> 1; + if (!BIT(param, 0)) + { + auto const nybble = step ^ m_interface; + if ((std::size(m_data) * 2) > step) + m_out = BIT(m_data[nybble >> 1], BIT(nybble, 0) ? 4 : 0, 4); + else + m_out = 0xe; + m_out |= BIT(step, 0) ? 0x30 : 0x20; + LOG( + "Set nybble %u data = 0x%X, L/H = %d, /Ack = 1\n", + step, + BIT(m_out, 0, 4), + BIT(m_out, 4)); + if ((std::size(m_data) * 2) > step) + { + m_output_timer->adjust( + attotime::from_nsec(BIT(step, 0) ? 3'800 : 21'800), + param + 1); + } + } + else if ((std::size(m_data) * 2) > step) + { + m_out &= 0x1f; + LOG("Set nybble %u /Ack = 0\n", step); + m_output_timer->adjust(attotime::from_nsec(12'100), param + 1); + } +} diff --git a/src/devices/machine/micomxe1a.h b/src/devices/machine/micomxe1a.h new file mode 100644 index 00000000000..e8b55e7f488 --- /dev/null +++ b/src/devices/machine/micomxe1a.h @@ -0,0 +1,49 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/********************************************************************** + + Dempa Micom Soft Analog/Digital Controller emulation + +**********************************************************************/ +#ifndef MAME_MACHINE_MICOMXE1A_H +#define MAME_MACHINE_MICOMXE1A_H + +#pragma once + + +class micom_xe_1a_device : public device_t +{ +public: + micom_xe_1a_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0) ATTR_COLD; + + auto buttons_handler() { return m_buttons_callback.bind(); } + auto analog_handler() { return m_analog_callback.bind(); } + + u8 out_r(); + + DECLARE_WRITE_LINE_MEMBER(req_w); + DECLARE_WRITE_LINE_MEMBER(mode_w); // 0 = digital, 1 = analog + DECLARE_WRITE_LINE_MEMBER(interface_w); // 0 = PC, 1 = MD + +protected: + virtual void device_start() override ATTR_COLD; + +private: + TIMER_CALLBACK_MEMBER(step_output); + + devcb_read16 m_buttons_callback; + devcb_read8 m_analog_callback; + + emu_timer *m_output_timer; + + u8 m_req; + u8 m_mode; + u8 m_interface; + u8 m_data[6]; + u8 m_out; +}; + + +DECLARE_DEVICE_TYPE(MICOM_XE_1A, micom_xe_1a_device) + +#endif // MAME_MACHINE_MICOMXE1A_H -- cgit v1.2.3