summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine
diff options
context:
space:
mode:
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
commit02197ab4caaccbbd7705c0cfccf3127a9e05b45e (patch)
treeefddb37f89e74527bb86a0b022a93d220a4d0715 /src/devices/machine
parent0aa81fc184b225547091a10f4accb8f3ae7064da (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.cpp221
-rw-r--r--src/devices/machine/busmouse.h74
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