ec1841: mouse emulation (Logitech bus mouse protocol) (#3623)

* ec1841: mouse emulation (Logitech bus mouse protocol)

* follow-up to PR#3623
This commit is contained in:
Sergey Svishchev 2018-06-11 13:57:53 +03:00 committed by Vas Crabb
parent 0aa81fc184
commit 02197ab4ca
7 changed files with 360 additions and 8 deletions

View File

@ -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

View File

@ -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")

View File

@ -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<bus_mouse_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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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

View File

@ -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)