diff options
author | Sergey Svishchev <shattered@users.noreply.github.com> | 2018-06-11 13:57:53 +0300 |
---|---|---|
committer | Vas Crabb <cuavas@users.noreply.github.com> | 2018-06-11 20:57:53 +1000 |
commit | 02197ab4caaccbbd7705c0cfccf3127a9e05b45e (patch) | |
tree | efddb37f89e74527bb86a0b022a93d220a4d0715 /src/devices/machine | |
parent | 0aa81fc184b225547091a10f4accb8f3ae7064da (diff) |
ec1841: mouse emulation (Logitech bus mouse protocol) (#3623)
* ec1841: mouse emulation (Logitech bus mouse protocol)
* follow-up to PR#3623
Diffstat (limited to 'src/devices/machine')
-rw-r--r-- | src/devices/machine/busmouse.cpp | 221 | ||||
-rw-r--r-- | src/devices/machine/busmouse.h | 74 |
2 files changed, 295 insertions, 0 deletions
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 <class Object> static devcb_base &set_extint_wr_callback(device_t &device, Object &&cb) { return downcast<bus_mouse_device &>(device).m_write_extint.set_callback(std::forward<Object>(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 |