summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/quadmouse.cpp
blob: 68d9d94c606cdd7259eb9eb30630fc6bd89224ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/**********************************************************************

    Generic quadrature mouse axis emulation

    Note: Axis only, no buttons, do the buttons in the owning device

**********************************************************************/

#include "emu.h"
#include "quadmouse.h"

DEFINE_DEVICE_TYPE(QUADMOUSE, quadmouse_device, "quadmouse", "Generic quadrature mouse support")

static INPUT_PORTS_START(quadmouse)
	PORT_START("x")
	PORT_BIT(0xf000, IP_ACTIVE_HIGH, IPT_UNUSED)
	PORT_BIT(0x0fff, 0, IPT_MOUSE_X) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(quadmouse_device::x_changed), 0)

	PORT_START("y")
	PORT_BIT(0xf000, IP_ACTIVE_HIGH, IPT_UNUSED)
	PORT_BIT(0x0fff, 0, IPT_MOUSE_Y) PORT_SENSITIVITY(100) PORT_KEYDELTA(0) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(quadmouse_device::y_changed), 0)
INPUT_PORTS_END

quadmouse_device::quadmouse_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, QUADMOUSE, tag, owner, clock),
	m_port_x(*this, "x"),
	m_port_y(*this, "y"),
	m_up_cb(*this),
	m_down_cb(*this),
	m_left_cb(*this),
	m_right_cb(*this)
{
}

void quadmouse_device::device_start()
{
	m_x_timer = timer_alloc(FUNC(quadmouse_device::x_tick), this);
	m_y_timer = timer_alloc(FUNC(quadmouse_device::y_tick), this);

	save_item(NAME(m_up));
	save_item(NAME(m_down));
	save_item(NAME(m_left));
	save_item(NAME(m_right));
	save_item(NAME(m_x_time));
	save_item(NAME(m_y_time));
	save_item(NAME(m_x_delta));
	save_item(NAME(m_y_delta));
}

void quadmouse_device::device_reset()
{
	m_x_time = m_y_time = machine().time();

	m_up = m_down = m_left = m_right = false;
	m_x_delta = m_y_delta = 0;
}

ioport_constructor quadmouse_device::device_input_ports() const
{
	return INPUT_PORTS_NAME(quadmouse);
}

void quadmouse_device::changed(s32 oldval, s32 newval, s32 &delta, attotime &time, emu_timer *timer)
{
	s32 ldelta = (newval - oldval) & 0xfff;
	if(ldelta & 0x800)
		ldelta -= 0x1000;
	attotime ctime = machine().time();
	attotime tdelta = ctime - time;
	delta += ldelta;
	time = ctime;

	if(delta) {
		int steps = delta > 0 ? delta : -delta;
		attotime step = tdelta / (steps+1);
		timer->adjust(step/2, 0, step);
	} else
		timer->adjust(attotime::never);
}

INPUT_CHANGED_MEMBER(quadmouse_device::x_changed)
{
	changed(oldval, newval, m_x_delta, m_x_time, m_x_timer);
}

INPUT_CHANGED_MEMBER(quadmouse_device::y_changed)
{
	changed(oldval, newval, m_y_delta, m_y_time, m_y_timer);
}

void quadmouse_device::step(s32 &delta, bool &mn, bool &pl, devcb_write_line &mn_cb, devcb_write_line &pl_cb)
{
	if(delta > 0) {
		delta --;

		if(mn == pl)
			mn_cb(mn = !mn);
		else
			pl_cb(pl = !pl);

	} else if(delta < 0) {
		delta ++;

		if(mn == pl)
			pl_cb(pl = !pl);
		else
			mn_cb(mn = !mn);
	}
}

TIMER_CALLBACK_MEMBER(quadmouse_device::x_tick)
{
	step(m_x_delta, m_left, m_right, m_left_cb, m_right_cb);

	if(!m_x_delta)
		m_x_timer->adjust(attotime::never);
}

TIMER_CALLBACK_MEMBER(quadmouse_device::y_tick)
{
	step(m_y_delta, m_up, m_down, m_up_cb, m_down_cb);

	if(!m_y_delta)
		m_y_timer->adjust(attotime::never);
}