1 // license:GPL-2.0+
2 // copyright-holders:Dirk Best
3 /***************************************************************************
4 
5     ACT Apricot Keyboard (HLE)
6 
7     TODO:
8     - MicroScreen emulation
9     - LEDs
10 
11     Keyboard to System:
12     - 01-60: Key make codes
13     - 70-7f: Mouse codes
14     - 80: RAM test failed
15     - 81-e0: Key break codes
16     - e9: ROM test failed
17     - ea: X-on (keyboard ready to receive)
18     - eb: X-off (keyboard buffer full)
19     - ec: Reset request
20     - ed: Time prefix
21     - ee: Date prefix
22     - ef: Mouse header
23     - f0-f9: BCD data
24     - fa: Invalid clock data
25     - fb: Acknowledge firmware version/reset
26 
27     System to keyboard:
28     - 01-7f: Character codes for MicroScreen
29     - 80-cf: Cursor address
30     - d0: Clear screen
31     - d1: Cursor left
32     - d2: Cursor right
33     - d3: Cursor on
34     - d4: Cursor off
35     - d5: Display on
36     - d6: Display off
37     - e0: Query
38     - e1: Time and date request
39     - e2: Display time/data on MicroScreen
40     - e3: Set LED prefix
41     - e4: Set time and date
42     - e5: Mouse enable
43     - e6: Mouse disable
44     - e7: Execute processor diagnostics
45     - e8: Keyboard reset
46     - f0-f9: BCD data
47     - fa: Invalid clock data
48 
49 ***************************************************************************/
50 
51 #include "emu.h"
52 #include "hle.h"
53 #include "machine/keyboard.ipp"
54 
55 
56 //**************************************************************************
57 //  DEVICE DEFINITIONS
58 //**************************************************************************
59 
60 DEFINE_DEVICE_TYPE(APRICOT_KEYBOARD_HLE, apricot_keyboard_hle_device, "apricotkb_hle", "Apricot Keyboard (HLE)")
61 
62 
63 //-------------------------------------------------
64 //  input_ports - device-specific input ports
65 //-------------------------------------------------
66 
INPUT_PORTS_START(keyboard)67 static INPUT_PORTS_START( keyboard )
68 	PORT_START("row_0")
69 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_UNUSED)
70 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F7)         PORT_CHAR(UCHAR_MAMEKEY(F7))      PORT_NAME("Help")
71 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F8)         PORT_CHAR(UCHAR_MAMEKEY(F8))      PORT_NAME("Undo")
72 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F9)         PORT_CHAR(UCHAR_MAMEKEY(F9))      PORT_NAME("Repeat")
73 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F10)        PORT_CHAR(UCHAR_MAMEKEY(F10))     PORT_NAME("Calc")
74 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_PRTSCR)     PORT_CHAR(UCHAR_MAMEKEY(PRTSCR))  PORT_NAME("Print")
75 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_CANCEL)     PORT_CHAR(UCHAR_MAMEKEY(CANCEL))  PORT_NAME("Intr")
76 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F11)        PORT_CHAR(UCHAR_MAMEKEY(F11))     PORT_NAME("Menu")
77 
78 	PORT_START("row_1")
79 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F12)        PORT_CHAR(UCHAR_MAMEKEY(F12))     PORT_NAME("Finish")
80 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F1)         PORT_CHAR(UCHAR_MAMEKEY(F1))      PORT_NAME("Function 1")
81 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F2)         PORT_CHAR(UCHAR_MAMEKEY(F2))      PORT_NAME("Function 2")
82 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F3)         PORT_CHAR(UCHAR_MAMEKEY(F3))      PORT_NAME("Function 3")
83 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F4)         PORT_CHAR(UCHAR_MAMEKEY(F4))      PORT_NAME("Function 4")
84 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F5)         PORT_CHAR(UCHAR_MAMEKEY(F5))      PORT_NAME("Function 5")
85 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F6)         PORT_CHAR(UCHAR_MAMEKEY(F6))      PORT_NAME("Function 6")
86 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_BACKSLASH)  PORT_CHAR('\\') PORT_CHAR('^')
87 
88 	PORT_START("row_2")
89 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_1)          PORT_CHAR('1')  PORT_CHAR('!')
90 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_2)          PORT_CHAR('2')  PORT_CHAR('@')
91 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_3)          PORT_CHAR('3')  PORT_CHAR('#')
92 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_4)          PORT_CHAR('4')  PORT_CHAR(0xa3) // pound
93 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_5)          PORT_CHAR('5')  PORT_CHAR('%')
94 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_6)          PORT_CHAR('6')  PORT_CHAR('$')
95 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_7)          PORT_CHAR('7')  PORT_CHAR('&')
96 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_8)          PORT_CHAR('8')  PORT_CHAR('*')
97 
98 	PORT_START("row_3")
99 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_9)          PORT_CHAR('9')  PORT_CHAR('(')
100 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_0)          PORT_CHAR('0')  PORT_CHAR(')')
101 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_MINUS)      PORT_CHAR('-')  PORT_CHAR('_')
102 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_EQUALS)     PORT_CHAR('=')  PORT_CHAR('+')
103 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_UNUSED)    PORT_CODE(KEYCODE_BACKSPACE)  PORT_CHAR(8)
104 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  // actually a dedicated % key
105 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_ASTERISK)   PORT_CHAR(UCHAR_MAMEKEY(ASTERISK))
106 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_SLASH_PAD)  PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD))
107 
108 	PORT_START("row_4")
109 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_MINUS_PAD)  PORT_CHAR(UCHAR_MAMEKEY(MINUS_PAD))
110 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_PLUS_PAD)   PORT_CHAR(UCHAR_MAMEKEY(PLUS_PAD))
111 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_TAB)        PORT_CHAR(9)
112 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_Q)          PORT_CHAR('q')  PORT_CHAR('Q')
113 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_W)          PORT_CHAR('w')  PORT_CHAR('W')
114 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_E)          PORT_CHAR('e')  PORT_CHAR('E')
115 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_R)          PORT_CHAR('r')  PORT_CHAR('R')
116 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_T)          PORT_CHAR('t')  PORT_CHAR('T')
117 
118 	PORT_START("row_5")
119 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_Y)          PORT_CHAR('y')  PORT_CHAR('Y')
120 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_U)          PORT_CHAR('u')  PORT_CHAR('U')
121 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_I)          PORT_CHAR('i')  PORT_CHAR('I')
122 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_O)          PORT_CHAR('o')  PORT_CHAR('O')
123 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_P)          PORT_CHAR('p')  PORT_CHAR('P')
124 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_OPENBRACE)  PORT_CHAR('[')  PORT_CHAR('{')
125 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']')  PORT_CHAR('}')
126 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_HOME)       PORT_CHAR(UCHAR_MAMEKEY(HOME))
127 
128 	PORT_START("row_6")
129 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_END)        PORT_CHAR(UCHAR_MAMEKEY(END))      PORT_NAME("Clear")
130 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_7_PAD)      PORT_CHAR(UCHAR_MAMEKEY(7_PAD))
131 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_8_PAD)      PORT_CHAR(UCHAR_MAMEKEY(8_PAD))
132 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_9_PAD)      PORT_CHAR(UCHAR_MAMEKEY(9_PAD))
133 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_CAPSLOCK)   PORT_CHAR(UCHAR_MAMEKEY(CAPSLOCK))
134 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_A)          PORT_CHAR('a')   PORT_CHAR('A')
135 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_S)          PORT_CHAR('s')   PORT_CHAR('S')
136 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_D)          PORT_CHAR('d')   PORT_CHAR('D')
137 
138 	PORT_START("row_7")
139 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_F)          PORT_CHAR('f')   PORT_CHAR('F')
140 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_G)          PORT_CHAR('g')   PORT_CHAR('G')
141 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_H)          PORT_CHAR('h')   PORT_CHAR('H')
142 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_J)          PORT_CHAR('j')   PORT_CHAR('J')
143 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_K)          PORT_CHAR('k')   PORT_CHAR('K')
144 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_L)          PORT_CHAR('l')   PORT_CHAR('L')
145 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_COLON)      PORT_CHAR(';')   PORT_CHAR(':')
146 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_QUOTE)      PORT_CHAR('\'')  PORT_CHAR('"')
147 
148 	PORT_START("row_8")
149 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_ENTER)      PORT_CHAR(13)
150 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_INSERT)     PORT_CHAR(UCHAR_MAMEKEY(INSERT))
151 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_DEL)        PORT_CHAR(UCHAR_MAMEKEY(DEL))
152 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_4_PAD)      PORT_CHAR(UCHAR_MAMEKEY(4_PAD))
153 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_5_PAD)      PORT_CHAR(UCHAR_MAMEKEY(5_PAD))
154 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_6_PAD)      PORT_CHAR(UCHAR_MAMEKEY(6_PAD))
155 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_LSHIFT)     PORT_CHAR(UCHAR_SHIFT_1)
156 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_Z)          PORT_CHAR('z')  PORT_CHAR('Z')
157 
158 	PORT_START("row_9")
159 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_X)          PORT_CHAR('x')  PORT_CHAR('X')
160 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_C)          PORT_CHAR('c')  PORT_CHAR('C')
161 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_V)          PORT_CHAR('v')  PORT_CHAR('V')
162 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_B)          PORT_CHAR('b')  PORT_CHAR('B')
163 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_N)          PORT_CHAR('n')  PORT_CHAR('N')
164 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_M)          PORT_CHAR('m')  PORT_CHAR('M')
165 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_COMMA)      PORT_CHAR(',')  PORT_CHAR('<')
166 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_STOP)       PORT_CHAR('.')  PORT_CHAR('>')
167 
168 	PORT_START("row_a")
169 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_SLASH)      PORT_CHAR('/')  PORT_CHAR('?')
170 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_RSHIFT)     PORT_CHAR(UCHAR_SHIFT_1)
171 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_UP)         PORT_CHAR(UCHAR_MAMEKEY(UP))
172 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_SCRLOCK)    PORT_CHAR(UCHAR_MAMEKEY(SCRLOCK))
173 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_1_PAD)      PORT_CHAR(UCHAR_MAMEKEY(1_PAD))
174 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_2_PAD)      PORT_CHAR(UCHAR_MAMEKEY(2_PAD))
175 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_3_PAD)      PORT_CHAR(UCHAR_MAMEKEY(3_PAD))
176 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_ESC)        PORT_CHAR(UCHAR_MAMEKEY(ESC))
177 
178 	PORT_START("row_b")
179 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_LCONTROL)   PORT_CHAR(UCHAR_SHIFT_2)
180 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_SPACE)      PORT_CHAR(' ')
181 	PORT_BIT(0x04, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_RCONTROL)   PORT_CHAR(UCHAR_MAMEKEY(PAUSE))    PORT_NAME("Stop")
182 	PORT_BIT(0x08, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_LEFT)       PORT_CHAR(UCHAR_MAMEKEY(LEFT))
183 	PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_DOWN)       PORT_CHAR(UCHAR_MAMEKEY(DOWN))
184 	PORT_BIT(0x20, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_RIGHT)      PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
185 	PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_0_PAD)      PORT_CHAR(UCHAR_MAMEKEY(0_PAD))
186 	PORT_BIT(0x80, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_DEL_PAD)    PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD))
187 
188 	PORT_START("row_c")
189 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_KEYBOARD)  PORT_CODE(KEYCODE_ENTER_PAD)  PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD))
190 
191 	PORT_START("mouse_b")
192 	PORT_BIT(0x01, IP_ACTIVE_HIGH, IPT_BUTTON2) PORT_NAME("Mouse Right Button")
193 	PORT_BIT(0x02, IP_ACTIVE_HIGH, IPT_BUTTON1) PORT_NAME("Mouse Left Button")
194 	PORT_BIT(0x0c, IP_ACTIVE_HIGH, IPT_UNUSED)
195 
196 	PORT_START("mouse_x")
197 	PORT_BIT(0xff, 0x00, IPT_MOUSE_X) PORT_SENSITIVITY(75) PORT_KEYDELTA(5)
198 
199 	PORT_START("mouse_y")
200 	PORT_BIT(0xff, 0x00, IPT_MOUSE_Y) PORT_SENSITIVITY(50) PORT_KEYDELTA(5)
201 INPUT_PORTS_END
202 
203 ioport_constructor apricot_keyboard_hle_device::device_input_ports() const
204 {
205 	return INPUT_PORTS_NAME( keyboard );
206 }
207 
device_add_mconfig(machine_config & config)208 void apricot_keyboard_hle_device::device_add_mconfig(machine_config &config)
209 {
210 	MSM5832(config, m_rtc, 32.768_kHz_XTAL);
211 
212 	TIMER(config, "timer").configure_periodic(FUNC(apricot_keyboard_hle_device::mouse_callback), attotime::from_hz(60));
213 }
214 
215 
216 //**************************************************************************
217 //  LIVE DEVICE
218 //**************************************************************************
219 
220 //-------------------------------------------------
221 //  apricot_keyboard_hle_device - constructor
222 //-------------------------------------------------
223 
apricot_keyboard_hle_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)224 apricot_keyboard_hle_device::apricot_keyboard_hle_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
225 	device_t(mconfig, APRICOT_KEYBOARD_HLE, tag, owner, clock),
226 	device_apricot_keyboard_interface(mconfig, *this),
227 	device_buffered_serial_interface(mconfig, *this),
228 	device_matrix_keyboard_interface(mconfig, *this, "row_0", "row_1", "row_2", "row_3", "row_4", "row_5", "row_6", "row_7", "row_8", "row_9", "row_a", "row_b", "row_c"),
229 	m_rtc(*this, "rtc"),
230 	m_mouse_b(*this, "mouse_b"),
231 	m_mouse_x(*this, "mouse_x"),
232 	m_mouse_y(*this, "mouse_y"),
233 	m_rtc_index(0),
234 	m_mouse_enabled(false),
235 	m_mouse_last_b(0), m_mouse_last_x(0), m_mouse_last_y(0)
236 {
237 }
238 
239 //-------------------------------------------------
240 //  device_start - device-specific startup
241 //-------------------------------------------------
242 
device_start()243 void apricot_keyboard_hle_device::device_start()
244 {
245 	// register for save states
246 	save_item(NAME(m_rtc_index));
247 	save_item(NAME(m_mouse_enabled));
248 	save_item(NAME(m_mouse_last_b));
249 	save_item(NAME(m_mouse_last_x));
250 	save_item(NAME(m_mouse_last_y));
251 }
252 
253 //-------------------------------------------------
254 //  device_reset - device-specific reset
255 //-------------------------------------------------
256 
device_reset()257 void apricot_keyboard_hle_device::device_reset()
258 {
259 	clear_fifo();
260 
261 	receive_register_reset();
262 	transmit_register_reset();
263 
264 	set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
265 	set_rcv_rate(7800);
266 	set_tra_rate(7800);
267 
268 	reset_key_state();
269 	start_processing(attotime::from_hz(7800));
270 }
271 
272 //-------------------------------------------------
273 //  tra_callback - send bit to host
274 //-------------------------------------------------
275 
tra_callback()276 void apricot_keyboard_hle_device::tra_callback()
277 {
278 	m_host->in_w(transmit_register_get_data_bit());
279 }
280 
281 //-------------------------------------------------
282 //  received_byte - handle received byte
283 //-------------------------------------------------
284 
received_byte(uint8_t byte)285 void apricot_keyboard_hle_device::received_byte(uint8_t byte)
286 {
287 	if ((byte & 0xf0) == 0xf0)
288 	{
289 		// rtc data
290 		if (m_rtc_index >= 0)
291 		{
292 			m_rtc->address_w(m_rtc_index--);
293 			m_rtc->data_w(byte);
294 			m_rtc->write_w(1);
295 			m_rtc->write_w(0);
296 		}
297 	}
298 	else
299 	{
300 		switch (byte)
301 		{
302 		case CMD_REQ_TIME_AND_DATE:
303 			logerror("System requests current time\n");
304 
305 			// remove pending keys just in case
306 			clear_fifo();
307 
308 			// send time prefix
309 			transmit_byte(0xed);
310 
311 			// make rtc chip ready
312 			m_rtc->cs_w(1);
313 			m_rtc->read_w(1);
314 
315 			// send bcd encoded date and time to system
316 			for (int i = 12; i >= 0; i--)
317 			{
318 				m_rtc->address_w(i);
319 				transmit_byte(0xf0 | m_rtc->data_r());
320 			}
321 
322 			break;
323 
324 		case CMD_SET_TIME_AND_DATE:
325 			logerror("System requests to set time\n");
326 
327 			// we start with the year
328 			m_rtc_index = 12;
329 
330 			// make rtc chip ready
331 			m_rtc->cs_w(1);
332 
333 			break;
334 
335 		case CMD_ENABLE_MOUSE:
336 			logerror("System enables mouse\n");
337 			m_mouse_enabled = true;
338 			break;
339 
340 		case CMD_DISABLE_MOUSE:
341 			logerror("System disables mouse\n");
342 			m_mouse_enabled = false;
343 			break;
344 
345 		case CMD_KEYBOARD_RESET:
346 			logerror("System requests keyboard reset\n");
347 			transmit_byte(ACK_DIAGNOSTICS);
348 			break;
349 
350 		default:
351 			logerror("Unhandled command: %02x\n", byte);
352 		}
353 	}
354 }
355 
356 //-------------------------------------------------
357 //  key_make - handle a key being pressed
358 //-------------------------------------------------
359 
key_make(uint8_t row,uint8_t column)360 void apricot_keyboard_hle_device::key_make(uint8_t row, uint8_t column)
361 {
362 	// send the make code
363 	transmit_byte((row << 3) | column);
364 }
365 
366 //-------------------------------------------------
367 //  key_break - handle a key being released
368 //-------------------------------------------------
369 
key_break(uint8_t row,uint8_t column)370 void apricot_keyboard_hle_device::key_break(uint8_t row, uint8_t column)
371 {
372 	// send the break code
373 	transmit_byte(0x80 | (row << 3) | column);
374 }
375 
376 //-------------------------------------------------
377 //  out_w - receive bit from host
378 //-------------------------------------------------
379 
out_w(int state)380 void apricot_keyboard_hle_device::out_w(int state)
381 {
382 	device_buffered_serial_interface::rx_w(state);
383 }
384 
385 //-------------------------------------------------
386 //  mouse_callback - check for new mouse events
387 //-------------------------------------------------
388 
TIMER_DEVICE_CALLBACK_MEMBER(apricot_keyboard_hle_device::mouse_callback)389 TIMER_DEVICE_CALLBACK_MEMBER( apricot_keyboard_hle_device::mouse_callback )
390 {
391 	if (m_mouse_enabled)
392 	{
393 		// get mouse state
394 		uint8_t buttons = m_mouse_b->read();
395 		uint8_t x = m_mouse_x->read();
396 		uint8_t y = m_mouse_y->read();
397 
398 		// anything changed since last time?
399 		if (buttons != m_mouse_last_b || x != m_mouse_last_x || y != m_mouse_last_y)
400 		{
401 			// mouse header
402 			transmit_byte(0xef);
403 
404 			// button state
405 			transmit_byte(0x70 | buttons);
406 
407 			int8_t dx = x - m_mouse_last_x;
408 			int8_t dy = y - m_mouse_last_y;
409 
410 			// y direction change
411 			transmit_byte(0x70 | ((dy >> 4) & 0x0f));
412 			transmit_byte(0x70 | ((dy >> 0) & 0x0f));
413 
414 			// x direction change
415 			transmit_byte(0x70 | ((dx >> 4) & 0x0f));
416 			transmit_byte(0x70 | ((dx >> 0) & 0x0f));
417 
418 			// save mouse state for next run
419 			m_mouse_last_b = buttons;
420 			m_mouse_last_x = x;
421 			m_mouse_last_y = y;
422 		}
423 	}
424 }
425