diff options
-rw-r--r-- | scripts/src/bus.lua | 2 | ||||
-rw-r--r-- | src/devices/bus/bbc/userport/pointer.cpp | 277 | ||||
-rw-r--r-- | src/devices/bus/bbc/userport/pointer.h | 104 | ||||
-rw-r--r-- | src/devices/bus/bbc/userport/userport.cpp | 9 |
4 files changed, 388 insertions, 4 deletions
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index f42f0fcb740..474569b1110 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -333,6 +333,8 @@ if (BUSES["BBC_USERPORT"]~=null) then files { MAME_DIR .. "src/devices/bus/bbc/userport/userport.cpp", MAME_DIR .. "src/devices/bus/bbc/userport/userport.h", + MAME_DIR .. "src/devices/bus/bbc/userport/pointer.cpp", + MAME_DIR .. "src/devices/bus/bbc/userport/pointer.h", MAME_DIR .. "src/devices/bus/bbc/userport/cfa3000kbd.cpp", MAME_DIR .. "src/devices/bus/bbc/userport/cfa3000kbd.h", } diff --git a/src/devices/bus/bbc/userport/pointer.cpp b/src/devices/bus/bbc/userport/pointer.cpp new file mode 100644 index 00000000000..a56f1f1378e --- /dev/null +++ b/src/devices/bus/bbc/userport/pointer.cpp @@ -0,0 +1,277 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + AMX Mouse + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/AMX_Mouse.html + + Marconi RB2 Tracker Ball + + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Marconi_MarcusRB2.html + http://chrisacorns.computinghistory.org.uk/8bit_Upgrades/Acorn_Trackerball.html + + The Tracker Ball outputs are fed directly into the user port with the port defined as + an input. The CB1 and CB2 lines are used in conjunction with PB3 and PB4 for + sensing pulses and determining the direction of rotation of the ball. + + The connections are:— + CB1 X1 + CB2 Y2 + PB0 Left switch button + PB1 Middle switch button + PB2 Right switch button + PB3 X2 + PB4 Y1 + + Quadrature implementation derived from SmallyMouse2, + see https://github.com/simoninns/SmallyMouse2 + +**********************************************************************/ + +#include "emu.h" +#include "pointer.h" + +//************************************************************************** +// DEVICE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(BBC_AMXMOUSE, bbc_amxmouse_device, "bbc_amxmouse", "AMX Mouse (BBC Micro)") +DEFINE_DEVICE_TYPE(BBC_M512MOUSE, bbc_m512mouse_device, "bbc_m512mouse", "Acorn Master 512 Mouse") +DEFINE_DEVICE_TYPE(BBC_TRACKER, bbc_tracker_device, "bbc_tracker", "Marconi RB2 Tracker Ball") + + +//------------------------------------------------- +// INPUT_PORTS( amxmouse ) +//------------------------------------------------- + +static INPUT_PORTS_START( amxmouse ) + PORT_START("POINTER_X") + PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET + + PORT_START("POINTER_Y") + PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET + + PORT_START("BUTTONS") + PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Mouse Left Button (Execute)") PORT_CODE(MOUSECODE_BUTTON1) + PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("Mouse Middle Button (Move)") PORT_CODE(MOUSECODE_BUTTON3) + PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Mouse Right Button (Cancel)") PORT_CODE(MOUSECODE_BUTTON2) +INPUT_PORTS_END + + +//------------------------------------------------- +// INPUT_PORTS( m512mouse ) +//------------------------------------------------- + +static INPUT_PORTS_START( m512mouse ) + PORT_START("POINTER_X") + PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET + + PORT_START("POINTER_Y") + PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET + + PORT_START("BUTTONS") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Mouse Left Button") PORT_CODE(MOUSECODE_BUTTON1) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_UNUSED) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Mouse Right Button") PORT_CODE(MOUSECODE_BUTTON2) +INPUT_PORTS_END + +//------------------------------------------------- +// INPUT_PORTS( tracker ) +//------------------------------------------------- + +static INPUT_PORTS_START( tracker ) + PORT_START("POINTER_X") + PORT_BIT(0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET + + PORT_START("POINTER_Y") + PORT_BIT(0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(5) PORT_CHANGED_MEMBER(DEVICE_SELF, bbc_pointer_device, pointer_changed, 0) PORT_RESET + + PORT_START("BUTTONS") + PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_NAME("Left Button") PORT_CODE(MOUSECODE_BUTTON1) + PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_NAME("Middle Button") PORT_CODE(MOUSECODE_BUTTON3) + PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_NAME("Right Button") PORT_CODE(MOUSECODE_BUTTON2) +INPUT_PORTS_END + +//------------------------------------------------- +// input_ports - device-specific input ports +//------------------------------------------------- + +ioport_constructor bbc_amxmouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( amxmouse ); +} + +ioport_constructor bbc_m512mouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( m512mouse ); +} + +ioport_constructor bbc_tracker_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( tracker ); +} + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// bbc_pointer_device - constructor +//------------------------------------------------- + +bbc_pointer_device::bbc_pointer_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, type, tag, owner, clock) + , device_bbc_userport_interface(mconfig, *this) + , m_pointer_x(*this, "POINTER_X") + , m_pointer_y(*this, "POINTER_Y") + , m_buttons(*this, "BUTTONS") +{ +} + +bbc_amxmouse_device::bbc_amxmouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : bbc_pointer_device(mconfig, BBC_AMXMOUSE, tag, owner, clock) +{ +} + +bbc_m512mouse_device::bbc_m512mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : bbc_pointer_device(mconfig, BBC_M512MOUSE, tag, owner, clock) +{ +} + +bbc_tracker_device::bbc_tracker_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : bbc_pointer_device(mconfig, BBC_TRACKER, tag, owner, clock) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void bbc_pointer_device::device_start() +{ + m_pointer_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(bbc_pointer_device::pointer_poll), this)); + m_pointer_timer->adjust(attotime::zero, 0, attotime::from_hz(1400)); +} + + +//------------------------------------------------- +// device_reset - device-specific reset +//------------------------------------------------- + +void bbc_pointer_device::device_reset() +{ + m_xdir = 0; + m_ydir = 0; + m_direction_x = 0; + m_direction_y = 0; + m_distance_x = 0; + m_distance_y = 0; + m_phase_x = 0; + m_phase_y = 0; +} + + +//************************************************************************** +// IMPLEMENTATION +//************************************************************************** + +INPUT_CHANGED_MEMBER(bbc_pointer_device::pointer_changed) +{ + int x = m_pointer_x->read(); + int y = m_pointer_y->read(); + x -= (x & 0x80) ? 0x100 : 0; + y -= (y & 0x80) ? 0x100 : 0; + + // Set the mouse movement direction and record the movement units + m_direction_x = (x > 0) ? 1 : 0; + m_distance_x = abs(x); + + m_direction_y = (y > 0) ? 1 : 0; + m_distance_y = abs(y); +} + +TIMER_CALLBACK_MEMBER(bbc_pointer_device::pointer_poll) +{ + // Process X output + if (m_distance_x) + { + // Set the output pins according to the current phase + switch (m_phase_x) + { + case 0: + m_slot->cb1_w(1); // Set X1 to 1 + break; + case 1: + m_xdir = 1; // Set X2 to 1 + break; + case 2: + m_slot->cb1_w(0); // Set X1 to 0 + break; + case 3: + m_xdir = 0; // Set X2 to 0 + break; + } + + // Change phase + if (m_direction_x == 0) + m_phase_x--; + else + m_phase_x++; + + // Decrement the distance left to move + m_distance_x--; + + // Range check the phase + m_phase_x &= 3; + } + + // Process Y output + if (m_distance_y) + { + // Set the output pins according to the current phase + switch (m_phase_y) + { + case 3: + m_slot->cb2_w(0); // Set Y1 to 0 + break; + case 2: + m_ydir = 0; // Set Y2 to 0 + break; + case 1: + m_slot->cb2_w(1); // Set Y1 to 1 + break; + case 0: + m_ydir = 1; // Set Y2 to 1 + break; + } + + // Change phase + if (m_direction_y == 0) + m_phase_y--; + else + m_phase_y++; + + // Decrement the distance left to move + m_distance_y--; + + // Range check the phase + m_phase_y &= 3; + } +} + +READ8_MEMBER(bbc_amxmouse_device::pb_r) +{ + return (m_buttons->read() & 0xe0) | (m_xdir << 0) | (m_ydir << 2) | 0x1a; +} + +READ8_MEMBER(bbc_m512mouse_device::pb_r) +{ + return (m_buttons->read() & 0x07) | (m_xdir << 3) | (m_ydir << 4) | 0xe0; +} + +READ8_MEMBER(bbc_tracker_device::pb_r) +{ + return (m_buttons->read() & 0x07) | (m_xdir << 3) | (m_ydir << 4) | 0xe0; +} diff --git a/src/devices/bus/bbc/userport/pointer.h b/src/devices/bus/bbc/userport/pointer.h new file mode 100644 index 00000000000..5551a2c82dd --- /dev/null +++ b/src/devices/bus/bbc/userport/pointer.h @@ -0,0 +1,104 @@ +// license:BSD-3-Clause +// copyright-holders:Nigel Barnes +/********************************************************************** + + Mouse emulation + +**********************************************************************/ + + +#ifndef MAME_BUS_BBC_USERPORT_POINTER_H +#define MAME_BUS_BBC_USERPORT_POINTER_H + +#pragma once + +#include "userport.h" + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class bbc_pointer_device : + public device_t, + public device_bbc_userport_interface +{ +public: + DECLARE_INPUT_CHANGED_MEMBER(pointer_changed); + +protected: + // construction/destruction + bbc_pointer_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + required_ioport m_pointer_x; + required_ioport m_pointer_y; + required_ioport m_buttons; + + // quadrature output + int m_xdir, m_ydir; + + // internal quadrature state + int m_direction_x, m_direction_y; + int m_distance_x, m_distance_y; + int m_phase_x, m_phase_y; + + TIMER_CALLBACK_MEMBER(pointer_poll); + emu_timer *m_pointer_timer; +}; + + +// ======================> bbc_amxmouse_device + +class bbc_amxmouse_device : public bbc_pointer_device +{ +public: + // construction/destruction + bbc_amxmouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ8_MEMBER(pb_r) override; + + // optional information overrides + virtual ioport_constructor device_input_ports() const override; +}; + + +// ======================> bbc_m512mouse_device + +class bbc_m512mouse_device : public bbc_pointer_device +{ +public: + // construction/destruction + bbc_m512mouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ8_MEMBER(pb_r) override; + + // optional information overrides + virtual ioport_constructor device_input_ports() const override; +}; + + +// ======================> bbc_tracker_device + +class bbc_tracker_device : public bbc_pointer_device +{ +public: + // construction/destruction + bbc_tracker_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ8_MEMBER(pb_r) override; + + // optional information overrides + virtual ioport_constructor device_input_ports() const override; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(BBC_AMXMOUSE, bbc_amxmouse_device) +DECLARE_DEVICE_TYPE(BBC_M512MOUSE, bbc_m512mouse_device) +DECLARE_DEVICE_TYPE(BBC_TRACKER, bbc_tracker_device) + + +#endif // MAME_BUS_BBC_USERPORT_POINTER_H diff --git a/src/devices/bus/bbc/userport/userport.cpp b/src/devices/bus/bbc/userport/userport.cpp index 6152d893cec..b42edec0877 100644 --- a/src/devices/bus/bbc/userport/userport.cpp +++ b/src/devices/bus/bbc/userport/userport.cpp @@ -115,15 +115,16 @@ WRITE8_MEMBER(bbc_userport_slot_device::pb_w) // slot devices -//#include "mouse.h" +#include "pointer.h" #include "cfa3000kbd.h" void bbc_userport_devices(device_slot_interface &device) { -// device.option_add("amxmouse", BBC_AMXMOUSE); /* AMX Mouse */ -// device.option_add("m512mouse", BBC_M512MOUSE); /* Acorn Mouse (provided with Master 512) */ -// device.option_add("tracker", BBC_TRACKER); /* Marconi RB2 Tracker Ball / Acorn Tracker Ball */ + device.option_add("amxmouse", BBC_AMXMOUSE); /* AMX Mouse */ +// device.option_add("beebsynth", BBC_BEEBSYNTH); /* Beeb Speech Synthesiser (Watford) */ + device.option_add("m512mouse", BBC_M512MOUSE); /* Acorn Mouse (provided with Master 512) */ + device.option_add("tracker", BBC_TRACKER); /* Marconi RB2 Tracker Ball / Acorn Tracker Ball */ // device.option_add("music4000", BBC_MUSIC4000); /* Hybrid Music 4000 Keyboard */ device.option_add("cfa3000kbd", CFA3000_KBD); /* Henson CFA 3000 Keyboard */ } |