From 02197ab4caaccbbd7705c0cfccf3127a9e05b45e Mon Sep 17 00:00:00 2001 From: Sergey Svishchev Date: Mon, 11 Jun 2018 13:57:53 +0300 Subject: ec1841: mouse emulation (Logitech bus mouse protocol) (#3623) * ec1841: mouse emulation (Logitech bus mouse protocol) * follow-up to PR#3623 --- scripts/src/machine.lua | 12 +++ src/devices/bus/isa/fdc.cpp | 30 ++++++ src/devices/bus/isa/fdc.h | 15 +++ src/devices/bus/isa/xsu_cards.cpp | 8 +- src/devices/machine/busmouse.cpp | 221 ++++++++++++++++++++++++++++++++++++++ src/devices/machine/busmouse.h | 74 +++++++++++++ src/mame/drivers/ec184x.cpp | 8 +- 7 files changed, 360 insertions(+), 8 deletions(-) create mode 100644 src/devices/machine/busmouse.cpp create mode 100644 src/devices/machine/busmouse.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 95c2f99c582..0f8dc41aa06 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -744,6 +744,18 @@ if (MACHINES["BANKDEV"]~=null) then } end +--------------------------------------------------- +-- +--@src/devices/machine/busmouse.h,MACHINES["BUSMOUSE"] = true +--------------------------------------------------- + +if (MACHINES["BUSMOUSE"]~=null) then + files { + MAME_DIR .. "src/devices/machine/busmouse.cpp", + MAME_DIR .. "src/devices/machine/busmouse.h", + } +end + --------------------------------------------------- -- --@src/devices/machine/cdp1852.h,MACHINES["CDP1852"] = true diff --git a/src/devices/bus/isa/fdc.cpp b/src/devices/bus/isa/fdc.cpp index cf064c94963..1f9602018cc 100644 --- a/src/devices/bus/isa/fdc.cpp +++ b/src/devices/bus/isa/fdc.cpp @@ -8,6 +8,7 @@ #include "emu.h" #include "fdc.h" +#include "machine/busmouse.h" #include "machine/pc_fdc.h" #include "imagedev/flopdrv.h" #include "formats/pc_dsk.h" @@ -139,8 +140,37 @@ MACHINE_CONFIG_START(isa8_fdc_superio_device::device_add_mconfig) MCFG_FLOPPY_DRIVE_ADD("fdc:1", pc_hd_floppies, "35hd", isa8_fdc_device::floppy_formats) MACHINE_CONFIG_END +isa8_ec1841_0003_device::isa8_ec1841_0003_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : isa8_fdc_device(mconfig, ISA8_EC1841_0003, tag, owner, clock) + , m_bus_mouse(*this, "bus_mouse") +{ +} + +void isa8_ec1841_0003_device::device_start() +{ + isa8_fdc_device::device_start(); + m_isa->install_device(0x023c, 0x023f, *m_bus_mouse, &bus_mouse_device::map); +} + +WRITE_LINE_MEMBER( isa8_ec1841_0003_device::aux_irq_w ) +{ + m_isa->irq4_w(state ? ASSERT_LINE : CLEAR_LINE); +} + +MACHINE_CONFIG_START( isa8_ec1841_0003_device::device_add_mconfig ) + MCFG_PC_FDC_XT_ADD("fdc") + MCFG_PC_FDC_INTRQ_CALLBACK(WRITELINE(*this, isa8_fdc_device, irq_w)) + MCFG_PC_FDC_DRQ_CALLBACK(WRITELINE(*this, isa8_fdc_device, drq_w)) + MCFG_FLOPPY_DRIVE_ADD("fdc:0", pc_dd_floppies, "525dd", isa8_fdc_device::floppy_formats) + MCFG_FLOPPY_DRIVE_ADD("fdc:1", pc_dd_floppies, "525dd", isa8_fdc_device::floppy_formats) + + MCFG_DEVICE_ADD("bus_mouse", BUS_MOUSE, 0) + MCFG_BUS_MOUSE_EXTINT_CALLBACK(WRITELINE(*this, isa8_ec1841_0003_device, aux_irq_w)) +MACHINE_CONFIG_END + DEFINE_DEVICE_TYPE(ISA8_FDC_XT, isa8_fdc_xt_device, "isa8_fdc_xt", "ISA 8bits XT FDC hookup") DEFINE_DEVICE_TYPE(ISA8_FDC_AT, isa8_fdc_at_device, "isa8_fdc_at", "ISA 8bits AT FDC hookup") DEFINE_DEVICE_TYPE(ISA8_FDC_SMC, isa8_fdc_smc_device, "isa8_fdc_smc", "ISA 8bits SMC FDC hookup") DEFINE_DEVICE_TYPE(ISA8_FDC_PS2, isa8_fdc_ps2_device, "isa8_fdc_ps2", "ISA 8bits PS/2 FDC hookup") DEFINE_DEVICE_TYPE(ISA8_FDC_SUPERIO, isa8_fdc_superio_device, "isa8_fdc_superio", "ISA 8bits SUPERIO FDC hookup") +DEFINE_DEVICE_TYPE(ISA8_EC1841_0003, isa8_ec1841_0003_device, "isa8_ec1841_0003", "ISA 8bits EC1841.0003 FDC hookup") diff --git a/src/devices/bus/isa/fdc.h b/src/devices/bus/isa/fdc.h index 026e0d5005d..b1364f2cc51 100644 --- a/src/devices/bus/isa/fdc.h +++ b/src/devices/bus/isa/fdc.h @@ -11,6 +11,7 @@ #pragma once #include "isa.h" +#include "machine/busmouse.h" #include "machine/upd765.h" //************************************************************************** @@ -83,11 +84,25 @@ protected: virtual void device_add_mconfig(machine_config &config) override; }; +class isa8_ec1841_0003_device : public isa8_fdc_device { +public: + isa8_ec1841_0003_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void device_start() override; + virtual void device_add_mconfig(machine_config &config) override; + + DECLARE_WRITE_LINE_MEMBER( aux_irq_w ); + + required_device m_bus_mouse; +}; + // device type definition DECLARE_DEVICE_TYPE(ISA8_FDC_XT, isa8_fdc_xt_device) DECLARE_DEVICE_TYPE(ISA8_FDC_AT, isa8_fdc_at_device) DECLARE_DEVICE_TYPE(ISA8_FDC_SMC, isa8_fdc_smc_device) DECLARE_DEVICE_TYPE(ISA8_FDC_PS2, isa8_fdc_ps2_device) DECLARE_DEVICE_TYPE(ISA8_FDC_SUPERIO, isa8_fdc_superio_device) +DECLARE_DEVICE_TYPE(ISA8_EC1841_0003, isa8_ec1841_0003_device) #endif // MAME_BUS_ISA_FDC_H diff --git a/src/devices/bus/isa/xsu_cards.cpp b/src/devices/bus/isa/xsu_cards.cpp index 1e8856e70ac..708c6b0ea86 100644 --- a/src/devices/bus/isa/xsu_cards.cpp +++ b/src/devices/bus/isa/xsu_cards.cpp @@ -64,17 +64,17 @@ void mc1502_isa8_cards(device_slot_interface &device) void ec184x_isa8_cards(device_slot_interface &device) { device.option_add("ec1840.0002", ISA8_EC1840_0002); // MDA with downloadable font + device.option_add("ec1840.0003", ISA8_FDC_XT); device.option_add("ec1841.0002", ISA8_EC1841_0002); // CGA with downloadable font - device.option_add("ec1841.0003", ISA8_FDC_XT); -/* - device.option_add("ec1841.0010", ISA8_EC1841_0010); // 8089-based HDC device.option_add("ec1841.0003", ISA8_EC1841_0003); // FDC + mouse port + device.option_add("ec1841.0004", ISA8_LPT); +/* device.option_add("ec1841.0004", ISA8_EC1841_0004); // BSC-like serial ports + parallel port + device.option_add("ec1841.0010", ISA8_EC1841_0010); // 8089-based HDC */ device.option_add("mda", ISA8_MDA); device.option_add("hdc", ISA8_HDC_EC1841); device.option_add("pccom", ISA8_COM); - device.option_add("pclpt", ISA8_LPT); device.option_add("xtide", ISA8_XTIDE); } diff --git a/src/devices/machine/busmouse.cpp b/src/devices/machine/busmouse.cpp new file mode 100644 index 00000000000..2b2d3dd8e33 --- /dev/null +++ b/src/devices/machine/busmouse.cpp @@ -0,0 +1,221 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/********************************************************************** + + Logitech bus mouse interface emulation + + References: + - ec1841 technical manual + - https://github.com/OBattler/86Box/blob/master/src/mouse_bus.c + - https://communities.intel.com/docs/DOC-22714 + - http://toastytech.com/guis/msmouse.html + + To do: + - selectable IRQ level + - Microsoft protocol + - ec1841.0003 clone: diag mode + - ec1841.0003 clone: fix detection by m86v32 driver + +**********************************************************************/ + +#include "emu.h" +#include "busmouse.h" + +#include "machine/i8255.h" + + +#define LOG_GENERAL (1U << 0) + +//#define VERBOSE (LOG_GENERAL) +//#define LOG_OUTPUT_FUNC printf +#include "logmacro.h" + + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(BUS_MOUSE, bus_mouse_device, "bus_mouse", "Bus Mouse Interface") + +void bus_mouse_device::map(address_map &map) +{ + map(0x0, 0x3).rw("ppi", FUNC(i8255_device::read), FUNC(i8255_device::write)); +} + + +//------------------------------------------------- +// INPUT_CHANGED_MEMBER( mouse_x_changed ) +//------------------------------------------------- + +INPUT_CHANGED_MEMBER(bus_mouse_device::mouse_x_changed) +{ + m_x += newval - oldval; + LOG("m_x_c: irqdis %d; %d = %d - %d\n", irq_disabled, m_x, newval, oldval); +} + + +//------------------------------------------------- +// INPUT_CHANGED_MEMBER( mouse_y_changed ) +//------------------------------------------------- + +INPUT_CHANGED_MEMBER(bus_mouse_device::mouse_y_changed) +{ + m_y += newval - oldval; + LOG("m_y_c: irqdis %d; %d = %d - %d\n", irq_disabled, m_y, newval, oldval); +} + + +//------------------------------------------------- +// INPUT_PORTS( bus_mouse ) +//------------------------------------------------- + +INPUT_PORTS_START( bus_mouse ) + PORT_START("mouse_x") + PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_CHANGED_MEMBER(DEVICE_SELF, bus_mouse_device, mouse_x_changed, 0) + + PORT_START("mouse_y") + PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(5) PORT_MINMAX(0, 255) PORT_CHANGED_MEMBER(DEVICE_SELF, bus_mouse_device, mouse_y_changed, 0) + + PORT_START("mouse_buttons") + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Left Mouse Button") PORT_CODE(MOUSECODE_BUTTON1) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Right Mouse Button") PORT_CODE(MOUSECODE_BUTTON3) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Middle Mouse Button") PORT_CODE(MOUSECODE_BUTTON2) + PORT_BIT( 0x1f, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("irq_rate") + PORT_DIPNAME(0x0f, 0x02, "IRQ rate") + PORT_DIPSETTING(0x01, "15 hz") + PORT_DIPSETTING(0x02, "30 hz") + PORT_DIPSETTING(0x04, "60 hz") + PORT_DIPSETTING(0x08, "120 hz") + + PORT_START("irq_line") + PORT_DIPNAME(0x0f, 0x02, "IRQ line") + PORT_DIPSETTING(0x02, "IRQ4") +#if 0 + PORT_DIPSETTING(0x08, "IRQ2") + PORT_DIPSETTING(0x04, "IRQ3") + PORT_DIPSETTING(0x01, "IRQ5") +#endif +INPUT_PORTS_END + + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor bus_mouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(bus_mouse); +} + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// bus_mouse_device - constructor +//------------------------------------------------- + +bus_mouse_device::bus_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, BUS_MOUSE, tag, owner, clock) + , m_write_extint(*this) + , m_buttons(*this, "mouse_buttons") +{ +} + + +MACHINE_CONFIG_START(bus_mouse_device::device_add_mconfig) + MCFG_DEVICE_ADD("ppi", I8255, 0) + MCFG_I8255_IN_PORTA_CB(READ8(*this, bus_mouse_device, ppi_a_r)) + MCFG_I8255_OUT_PORTC_CB(WRITE8(*this, bus_mouse_device, ppi_c_w)) + MCFG_I8255_IN_PORTC_CB(READ8(*this, bus_mouse_device, ppi_c_r)) +MACHINE_CONFIG_END + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void bus_mouse_device::device_start() +{ + // resolve callbacks + m_write_extint.resolve_safe(); + + m_irq_timer = timer_alloc(0); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void bus_mouse_device::device_reset() +{ + int hz = 2 * 15 * ioport("irq_rate")->read(); + + m_irq_timer->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz)); + + irq = 0; + irq_disabled = 1; + irq_line = ioport("irq_line")->read(); + + LOG("irq rate: %d Hz\n", hz); +} + +void bus_mouse_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + irq = !irq; + + if (!irq_disabled && irq) + { + m_write_extint(irq); + } +} + +READ8_MEMBER(bus_mouse_device::ppi_a_r) +{ + return m_pa; +} + +READ8_MEMBER(bus_mouse_device::ppi_c_r) +{ + return irq ? irq_line : 0; +} + +WRITE8_MEMBER(bus_mouse_device::ppi_c_w) +{ + irq_disabled = BIT(data, 4); + + switch (data & 0xe0) + { + case 0: + m_write_extint(CLEAR_LINE); + m_pa = 0; + break; + + case 0x80: // LSB X + m_pa = m_x & 0xf; + break; + + case 0xa0: // MSB X + m_pa = (m_x >> 4) & 0xf; + if (m_x < 0) m_pa |= 8; + m_pa |= m_buttons->read() & 0xe0; + m_x = 0; + break; + + case 0xc0: // LSB Y + m_pa = m_y & 0xf; + break; + + case 0xe0: // MSB Y + m_pa = (m_y >> 4) & 0xf; + if (m_y < 0) m_pa |= 8; + m_pa |= m_buttons->read() & 0xe0; + m_y = 0; + break; + } + LOG("c_w: data %02x m_pa %02x\n", data, m_pa); +} diff --git a/src/devices/machine/busmouse.h b/src/devices/machine/busmouse.h new file mode 100644 index 00000000000..8c30fd34d54 --- /dev/null +++ b/src/devices/machine/busmouse.h @@ -0,0 +1,74 @@ +// license:BSD-3-Clause +// copyright-holders:Sergey Svishchev +/********************************************************************** + + Logitech bus mouse interface emulation + +**********************************************************************/ + +#ifndef MAME_MACHINE_BUSMOUSE_H +#define MAME_MACHINE_BUSMOUSE_H + +#pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_BUS_MOUSE_EXTINT_CALLBACK(_write) \ + devcb = &bus_mouse_device::set_extint_wr_callback(*device, DEVCB_##_write); + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// ======================> bus_mouse_device + +class bus_mouse_device : public device_t +{ +public: + // construction/destruction + bus_mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + template static devcb_base &set_extint_wr_callback(device_t &device, Object &&cb) { return downcast(device).m_write_extint.set_callback(std::forward(cb)); } + + DECLARE_INPUT_CHANGED_MEMBER(mouse_x_changed); + DECLARE_INPUT_CHANGED_MEMBER(mouse_y_changed); + + void map(address_map &map); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; + virtual void device_add_mconfig(machine_config &config) override; + + // optional information overrides + virtual ioport_constructor device_input_ports() const override; + + DECLARE_READ8_MEMBER(ppi_a_r); + DECLARE_READ8_MEMBER(ppi_c_r); + DECLARE_WRITE8_MEMBER(ppi_c_w); + +private: + emu_timer *m_irq_timer; + bool irq, irq_disabled; + int irq_line; + + devcb_write_line m_write_extint; + + required_ioport m_buttons; + + uint8_t m_pa; + int8_t m_x, m_y; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(BUS_MOUSE, bus_mouse_device) + + +#endif // MAME_MACHINE_BUSMOUSE_H diff --git a/src/mame/drivers/ec184x.cpp b/src/mame/drivers/ec184x.cpp index 409d2e658c6..a2eed7a6ff7 100644 --- a/src/mame/drivers/ec184x.cpp +++ b/src/mame/drivers/ec184x.cpp @@ -233,7 +233,7 @@ MACHINE_CONFIG_START(ec184x_state::ec1840) // FIXME: determine ISA bus clock MCFG_DEVICE_ADD("isa1", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "ec1840.0002", false) - MCFG_DEVICE_ADD("isa2", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "ec1841.0003", false) // actually ec1840.0003 -- w/o mouse port + MCFG_DEVICE_ADD("isa2", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "ec1840.0003", false) MCFG_DEVICE_ADD("isa3", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, nullptr, false) MCFG_DEVICE_ADD("isa4", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, nullptr, false) MCFG_DEVICE_ADD("isa5", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, nullptr, false) @@ -259,9 +259,9 @@ MACHINE_CONFIG_START(ec184x_state::ec1841) // FIXME: determine ISA bus clock MCFG_DEVICE_ADD("isa1", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "ec1841.0002", false) // cga - MCFG_DEVICE_ADD("isa2", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "ec1841.0003", false) // fdc + mouse port - MCFG_DEVICE_ADD("isa3", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "hdc", false) - MCFG_DEVICE_ADD("isa4", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, nullptr, false) + MCFG_DEVICE_ADD("isa2", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "ec1841.0003", false) // fdc (IRQ6) + mouse port (IRQ2..5) + MCFG_DEVICE_ADD("isa3", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "ec1841.0004", false) // lpt (IRQ7||5) [+ serial (IRQx)] + MCFG_DEVICE_ADD("isa4", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, "hdc", false) MCFG_DEVICE_ADD("isa5", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, nullptr, false) MCFG_DEVICE_ADD("isa6", ISA8_SLOT, 0, "mb:isa", ec184x_isa8_cards, nullptr, false) -- cgit v1.2.3