diff options
Diffstat (limited to 'src/devices/bus/ti99x/mecmouse.cpp')
-rw-r--r-- | src/devices/bus/ti99x/mecmouse.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/devices/bus/ti99x/mecmouse.cpp b/src/devices/bus/ti99x/mecmouse.cpp new file mode 100644 index 00000000000..6afcec642d4 --- /dev/null +++ b/src/devices/bus/ti99x/mecmouse.cpp @@ -0,0 +1,209 @@ +// license:LGPL-2.1+ +// copyright-holders:Michael Zapf +/**************************************************************************** + + TI-99 Mechatronic mouse with adapter + + The Mechatronic mouse is connected to the joystick port and occupies + both joystick select lines and the switch lines. From these five + lines, left/right/down are used for the motion (i.e. 3 motion steps + for positive and four for negative motion and one for rest), + the fire line is used for the secondary mouse button, and the up + line is used for the primary button. + The mouse motion is delivered by the same lines for both directions; + this requires swapping the axes. According to the source code of + the accompanying mouse driver, the readout of the current axis is + done by selecting joystick 1, then joystick 2. The axis swapping is + achieved by selecting stick 1 again. When selecting stick 2, the + second axis is seen on the input lines. + Interrupting this sequence will lead to swapped axes. This is + prevented by resetting the toggle when the mouse is deselected + (neither 1 nor 2 are selected). + + The joystick lines are selected as follows: + TI-99/4: Stick 1: P4=1, P3=0, P2=1 (5) + Stick 2: P4=1, P3=1, P2=0 (6) + + TI-99/4A: Stick 1: P4=1, P3=1, P2=0 (6) + Stick 2: P4=1, P3=1, P2=1 (7) + + TI-99/8: Stick 1: P3=1, P2=1, P1=1, P0=0 (14) + Stick 2: P3=1, P2=1, P1=1, P0=1 (15) + + Geneve: n/a, has own mouse handling via v9938 + + As we can only deliver at max 3 steps positive and 4 steps negative, + we split the delta so that subsequent queries add up to the actual + delta. That is, one delta of +10 yields a 3+3+3+1. + + mecmouse_x holds the current delta to be counted down for x + (y accordingly) + + mecmouse_x_buf is the current step count reported to CRU + + Michael Zapf, 2008-01-22 + + 2010-10-22 Rewriten as device + February 2012: Rewritten as class + +*****************************************************************************/ + +#include "mecmouse.h" + +#define POLL_TIMER 1 + +mecmouse_device::mecmouse_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : joyport_attached_device(mconfig, MECMOUSE, "Mechatronics Mouse", tag, owner, clock, "mecmouse", __FILE__) +{ +} + + +UINT8 mecmouse_device::read_dev() +{ + int answer; + int buttons = ioport("MOUSE0")->read() & 3; + + answer = (m_read_y_axis? m_y_buf : m_x_buf) << 1; + + if ((buttons & 1)==0) + /* action button */ + answer |= 0x01; + if ((buttons & 2)==0) + /* home button */ + answer |= 0x10; + + // answer: |0|0|0|B2|V|V|V|B1| + + return answer; +} + +/* + Used to select lines. data = 0x01 (Joy1), 0x02 (Joy2) +*/ +void mecmouse_device::write_dev(UINT8 data) +{ + if (data == 0x02) { + if (m_last_select == 0x01) { + if (!m_read_y_axis) + { + /* Sample x motion. */ + if (m_x < -4) + m_x_buf = -4; + else if (m_x > 3) + m_x_buf = 3; + else + m_x_buf = m_x; + m_x -= m_x_buf; + m_x_buf = (m_x_buf-1) & 7; + } + else + { + /* Sample y motion. */ + if (m_y < -4) + m_y_buf = -4; + else if (m_y > 3) + m_y_buf = 3; + else + m_y_buf = m_y; + m_y -= m_y_buf; + m_y_buf = (m_y_buf-1) & 7; + } + } + m_last_select = data; + } + else if (data == 0x01) + { + if (m_last_select == 0x02) + { + /* Swap the axes. */ + m_read_y_axis = !m_read_y_axis; + } + m_last_select = data; + } + else + { + // Reset the axis toggle when the mouse is deselected + m_read_y_axis = false; + } +} + +void mecmouse_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + // Poll the movement + int new_mx, new_my; + int delta_x, delta_y; + + new_mx = ioport("MOUSEX")->read(); + new_my = ioport("MOUSEY")->read(); + + // compute x delta + delta_x = new_mx - m_last_mx; + + // check for wrap + if (delta_x > 0x80) + delta_x = -0x100+delta_x; + if (delta_x < -0x80) + delta_x = 0x100+delta_x; + + // Prevent unplausible values at startup. + if (delta_x > 100 || delta_x<-100) delta_x = 0; + + m_last_mx = new_mx; + + // compute y delta + delta_y = new_my - m_last_my; + + // check for wrap + if (delta_y > 0x80) + delta_y = -0x100+delta_y; + if (delta_y < -0x80) + delta_y = 0x100+delta_y; + + if (delta_y > 100 || delta_y<-100) delta_y = 0; + + m_last_my = new_my; + + // update state + m_x += delta_x; + m_y += delta_y; +} + +void mecmouse_device::device_start(void) +{ + m_poll_timer = timer_alloc(POLL_TIMER); + // The poll time cannot depend on the console settings, since the TI-99/4A + // has no clock line on the joystick port. The rate is not mentioned in + // the specs; however, if it is too low, the mouse pointer will do jumps + m_poll_timer->adjust(attotime::from_hz(100), 0, attotime::from_hz(100)); +} + +void mecmouse_device::device_reset(void) +{ + m_poll_timer->enable(true); + m_last_select = 0; + m_read_y_axis = false; + m_x = 0; + m_y = 0; + m_last_mx = 0; + m_last_my = 0; +} + +INPUT_PORTS_START( mecmouse ) + /* 3 ports for mouse */ + PORT_START("MOUSEX") /* Mouse - X AXIS */ + PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) + + PORT_START("MOUSEY") /* Mouse - Y AXIS */ + PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_PLAYER(1) + + PORT_START("MOUSE0") /* Mouse - buttons */ + PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Button 1") PORT_PLAYER(1) + PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Mouse Button 2") PORT_PLAYER(1) +INPUT_PORTS_END + +ioport_constructor mecmouse_device::device_input_ports() const +{ + return INPUT_PORTS_NAME( mecmouse ); +} + +const device_type MECMOUSE = &device_creator<mecmouse_device>; |