summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/pce_ctrl/mouse.cpp
blob: 5f0fd47625f69b9479c4a146b044a0eb5164d3cb (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
129
130
131
132
133
134
135
136
137
// license:BSD-3-Clause
// copyright-holders:Vas Crabb
/***********************************************************************

    NEC PC Engine/TurboGrafx-16 Mouse emulation

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

#include "emu.h"
#include "mouse.h"

#include <algorithm>
#include <iterator>

//#define VERBOSE 1
//#define LOG_OUTPUT_FUNC osd_printf_info
#include "logmacro.h"


namespace {

INPUT_PORTS_START( pce_mouse )
	PORT_START("BUTTONS")
	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("%p Button I (right)")
	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("%p Button II (left)")
	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_SELECT  )
	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START   ) PORT_NAME("%p Run")

	PORT_START("X")
	PORT_BIT( 0xff, 0x00, IPT_MOUSE_X ) PORT_SENSITIVITY(20) PORT_KEYDELTA(1) PORT_REVERSE

	PORT_START("Y")
	PORT_BIT( 0xff, 0x00, IPT_MOUSE_Y ) PORT_SENSITIVITY(20) PORT_KEYDELTA(1) PORT_REVERSE
INPUT_PORTS_END


class pce_mouse_device : public device_t, public device_pce_control_port_interface
{
public:
	pce_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);

	virtual u8 peripheral_r() override;
	virtual void sel_w(int state) override { m_sel_in = state ? 1 : 0; }
	virtual void clr_w(int state) override;

protected:
	virtual ioport_constructor device_input_ports() const override { return INPUT_PORTS_NAME(pce_mouse); }
	virtual void device_start() override ATTR_COLD;

private:
	required_ioport m_buttons;
	required_ioport_array<2> m_axes;

	attotime m_squeak;
	u16 m_data;
	u8 m_base[2];
	u8 m_sel_in;
	u8 m_clr_in;
};


pce_mouse_device::pce_mouse_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) :
	device_t(mconfig, PCE_MOUSE, tag, owner, clock),
	device_pce_control_port_interface(mconfig, *this),
	m_buttons(*this, "BUTTONS"),
	m_axes(*this, "%c", 'X'),
	m_squeak(),
	m_data(0),
	m_sel_in(1),
	m_clr_in(1)
{
}


u8 pce_mouse_device::peripheral_r()
{
	if (m_clr_in)
		return 0x0f;
	else if (!m_sel_in)
		return m_buttons->read();
	else
		return BIT(m_data, 12, 4);
}


void pce_mouse_device::clr_w(int state)
{
	u8 const clr = state ? 1 : 0;
	if (clr != m_clr_in)
	{
		m_clr_in = clr;
		if (clr)
		{
			attotime const now = machine().time();
			if ((now - m_squeak) > attotime::from_usec(550))
			{
				LOG("%s: CLR rising, latch count\n", machine().describe_context());
				m_squeak = now;
				for (unsigned i = 0; m_axes.size() > i; ++i)
				{
					uint8_t const count = m_axes[i]->read();
					m_data <<= 8;
					m_data |= (count - m_base[i]) & 0x00ff;
					m_base[i] = count;
				}
			}
			else
			{
				LOG("%s: CLR rising, shift count\n", machine().describe_context());
				m_data <<= 4;
			}
		}
		else
		{
			LOG("%s: CLR falling\n", machine().describe_context());
		}
	}
}


void pce_mouse_device::device_start()
{
	m_squeak = machine().time();
	m_data = 0;
	std::fill(std::begin(m_base), std::end(m_base), 0);

	save_item(NAME(m_squeak));
	save_item(NAME(m_data));
	save_item(NAME(m_base));
	save_item(NAME(m_sel_in));
	save_item(NAME(m_clr_in));
}

} // anonymous namespace


DEFINE_DEVICE_TYPE_PRIVATE(PCE_MOUSE, device_pce_control_port_interface, pce_mouse_device, "pce_mouse", "NEC PC Engine Mouse")