summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/apollo_kbd.h
blob: 096a1be771021f07214568f4bbd8795c9b00fb07 (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// license:BSD-3-Clause
// copyright-holders:Hans Ostermeyer
/*
 * apollo_kbd.h
 *
 *  Created on: Dec 27, 2010
 *      Author: Hans Ostermeyer
 *
 */

#ifndef MAME_MACHINE_APOLLO_KBD_H
#define MAME_MACHINE_APOLLO_KBD_H

#pragma once

#include "sound/beep.h"

// BSD-derived systems get very sad when you party with system reserved names.
#ifdef getchar
#undef getchar
#endif

#ifdef putchar
#undef putchar
#endif

//**************************************************************************
//  DEVICE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_APOLLO_KBD_TX_CALLBACK(_cb) \
	devcb = &downcast<apollo_kbd_device &>(*device).set_tx_cb(DEVCB_##_cb);

#define MCFG_APOLLO_KBD_GERMAN_CALLBACK(_cb) \
	devcb = &downcast<apollo_kbd_device &>(*device).set_german_cb(DEVCB_##_cb);


//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// ======================> apollo_kbd_device

class apollo_kbd_device : public device_t, public device_serial_interface
{
public:
	// construction/destruction
	apollo_kbd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	template <class Object> devcb_base &set_tx_cb(Object &&cb) { return m_tx_w.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_german_cb(Object &&cb) { return m_german_r.set_callback(std::forward<Object>(cb)); }

private:
	// device-level overrides
	virtual ioport_constructor device_input_ports() const override;
	virtual void device_resolve_objects() override;
	virtual void device_start() override;
	virtual void device_reset() override;

	// serial overrides
	virtual void rcv_complete() override;    // Rx completed receiving byte
	virtual void tra_complete() override;    // Tx completed sending byte
	virtual void tra_callback() override;    // Tx send bit
	void input_callback(uint8_t state);

	TIMER_CALLBACK_MEMBER( kbd_scan_timer );

	std::string cpu_context() const;
	template <typename Format, typename... Params>
	void logerror(Format &&fmt, Params &&... args) const;

	void kgetchar(uint8_t data);

	bool keyboard_is_german();

	void set_mode(uint16_t mode);
	void putdata(const uint8_t *data, int data_length);
	void putstring(const char *data);

	int push_scancode( uint8_t code, uint8_t repeat);
	void scan_keyboard();

	// the keyboard beeper
	class beeper
	{
	public:
		beeper();
		void start(apollo_kbd_device *device);
		void reset();
		void off();
		void on();
	private:
		int keyboard_has_beeper();
		TIMER_CALLBACK_MEMBER(beeper_callback);

		apollo_kbd_device *m_device; // pointer back to our device
		beep_device *m_beeper; // the keyboard beeper device
		emu_timer * m_timer; // timer to clock data in
	};

	// the keyboard mouse
	class mouse
	{
	public:
		mouse();
		void start(apollo_kbd_device *device);
		void reset();
		void read_mouse();
	private:
		apollo_kbd_device *m_device; // pointer back to our device

		int m_last_b;  // previous mouse button values
		int m_last_x;  // previous mouse x-axis value
		int m_last_y;  // previous mouse y-axis value
		int m_tx_pending;  // mouse data packet is pending
	};

	static const int XMIT_RING_SIZE = 64;

	required_ioport_array<4> m_io_keyboard;
	required_ioport_array<3> m_io_mouse;

	devcb_write_line m_tx_w;
	devcb_read_line m_german_r;

	uint8_t m_xmitring[XMIT_RING_SIZE];
	int m_xmit_read, m_xmit_write;
	bool m_tx_busy;

	void xmit_char(uint8_t data);

	beeper  m_beeper;
	mouse   m_mouse;

	apollo_kbd_device *m_device; // pointer to myself (nasty: used for cpu_context)

	/* Receiver */
	uint32_t m_rx_message;
	uint16_t m_loopback_mode;

	emu_timer* m_timer;
	uint16_t m_mode;
	uint16_t m_delay;         // key press delay after initial press
	uint16_t m_repeat;        // key press repeat rate
	uint16_t m_last_pressed;  // last key pressed, for repeat key handling
	uint16_t m_numlock_state; // current num lock state
	int m_keytime[0x80];    // time until next key press (1 ms)
	uint8_t m_keyon[0x80];    // is 1 if key is pressed

	struct code_entry { uint16_t down, up, unshifted, shifted, control, caps_lock, up_trans, auto_repeat; };
	static code_entry const s_code_table[];
};

// device type definition
DECLARE_DEVICE_TYPE(APOLLO_KBD, apollo_kbd_device)

#endif // MAME_MACHINE_APOLLO_KBD_H