summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/bus/rs232/keyboard.c
blob: 3437344a7de7fd7980702eee3946b65b49c656fb (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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/***************************************************************************
Generic ASCII Serial Keyboard

Use MCFG_SERIAL_KEYBOARD_ADD to attach this as a serial device to a terminal
or computer.


Example of usage in a driver.

In MACHINE_CONFIG
	MCFG_SERIAL_KEYBOARD_ADD(KEYBOARD_TAG, keyboard_intf, 0)
or
	MCFG_SERIAL_KEYBOARD_ADD(KEYBOARD_TAG, keyboard_intf, initial_baud_rate)


In the code:

WRITE8_MEMBER( xxx_state::kbd_put )
{
    (code to capture the key as it is pressed)
}

static ASCII_KEYBOARD_INTERFACE( keyboard_intf )
{
    DEVCB_DRIVER_MEMBER(xxx_state, kbd_put)
};

If a baud_rate is specified, it will be the initial baud rate, with
8 bits, no parity, 1 stop bit. However you can override this with the
config switches. (Note that the config switch will specify 9600 initially,
even though it isn't).

If a baud_rate is not specified, the rate will be solely determined
by the config switches. (Default 9600 baud)


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

#include "keyboard.h"

/***************************************************************************
    IMPLEMENTATION
***************************************************************************/

static INPUT_PORTS_START(serial_keyboard)
	PORT_INCLUDE(generic_keyboard)
	PORT_START("TERM_FRAME")
	PORT_CONFNAME(0x0f, 0x06, "Baud") PORT_CHANGED_MEMBER(DEVICE_SELF, serial_keyboard_device, update_frame, 0)
	PORT_CONFSETTING( 0x0d, "110")
	PORT_CONFSETTING( 0x00, "150")
	PORT_CONFSETTING( 0x01, "300")
	PORT_CONFSETTING( 0x02, "600")
	PORT_CONFSETTING( 0x03, "1200")
	PORT_CONFSETTING( 0x04, "2400")
	PORT_CONFSETTING( 0x05, "4800")
	PORT_CONFSETTING( 0x06, "9600")
	PORT_CONFSETTING( 0x07, "14400")
	PORT_CONFSETTING( 0x08, "19200")
	PORT_CONFSETTING( 0x09, "28800")
	PORT_CONFSETTING( 0x0a, "38400")
	PORT_CONFSETTING( 0x0b, "57600")
	PORT_CONFSETTING( 0x0c, "115200")
	PORT_CONFNAME(0x30, 0x00, "Format") PORT_CHANGED_MEMBER(DEVICE_SELF, serial_keyboard_device, update_frame, 0)
	PORT_CONFSETTING( 0x00, "8N1")
	PORT_CONFSETTING( 0x10, "7E1")
	PORT_CONFSETTING( 0x20, "8N2")
	PORT_CONFSETTING( 0x30, "8E1")
INPUT_PORTS_END

ioport_constructor serial_keyboard_device::device_input_ports() const
{
	return INPUT_PORTS_NAME(serial_keyboard);
}

serial_keyboard_device::serial_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
	: generic_keyboard_device(mconfig, SERIAL_KEYBOARD, "Serial Keyboard", tag, owner, clock, "serial_keyboard", __FILE__),
	device_serial_interface(mconfig, *this),
	device_rs232_port_interface(mconfig, *this),
	m_io_term_frame(*this, "TERM_FRAME")
{
}

serial_keyboard_device::serial_keyboard_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
	: generic_keyboard_device(mconfig, type, name, tag, owner, clock, shortname, source),
	device_serial_interface(mconfig, *this),
	device_rs232_port_interface(mconfig, *this),
	m_io_term_frame(*this, "TERM_FRAME")
{
}

void serial_keyboard_device::device_config_complete()
{
	const serial_keyboard_interface *intf = reinterpret_cast<const serial_keyboard_interface *>(static_config());
	if(intf != NULL)
	{
		*static_cast<serial_keyboard_interface *>(this) = *intf;
	}
	else
	{
		memset(&m_out_tx_cb, 0, sizeof(m_out_tx_cb));
	}
}

static int rates[] = {150, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 110};

void serial_keyboard_device::device_start()
{
	m_baud = clock();
	m_out_tx_func.resolve(m_out_tx_cb, *this);
	m_timer = timer_alloc();

	if (m_baud)
	{
		set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
		set_tra_rate(m_baud);
	}
}

INPUT_CHANGED_MEMBER(serial_keyboard_device::update_frame)
{
	m_baud = 0;
	reset();
}

void serial_keyboard_device::device_reset()
{
	generic_keyboard_device::device_reset();
	m_rbit = 1;
	if (m_port)
		output_rxd(m_rbit);
	else
		m_out_tx_func(m_rbit);

	if (m_baud == 0)
	{
		UINT8 val = m_io_term_frame->read();
		set_tra_rate(rates[val & 0x0f]);

		switch(val & 0x30)
		{
		case 0x10:
			set_data_frame(1, 7, PARITY_EVEN, STOP_BITS_1);
			break;
		case 0x00:
		default:
			set_data_frame(1, 8, PARITY_NONE, STOP_BITS_1);
			break;
		case 0x20:
			set_data_frame(1, 8, PARITY_NONE, STOP_BITS_2);
			break;
		case 0x30:
			set_data_frame(1, 8, PARITY_EVEN, STOP_BITS_1);
			break;
		}
	}
}

void serial_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	if (id)
		device_serial_interface::device_timer(timer, id, param, ptr);
	else
		generic_keyboard_device::device_timer(timer, id, param, ptr);
}

void serial_keyboard_device::send_key(UINT8 code)
{
	if(is_transmit_register_empty())
	{
		transmit_register_setup(code);
		return;
	}
	m_key_valid = true;
	m_curr_key = code;
}

void serial_keyboard_device::tra_callback()
{
	m_rbit = transmit_register_get_data_bit();
	if(m_port)
		output_rxd(m_rbit);
	else
		m_out_tx_func(m_rbit);
}

void serial_keyboard_device::tra_complete()
{
	if(m_key_valid)
	{
		transmit_register_setup(m_curr_key);
		m_key_valid = false;
	}
}

READ_LINE_MEMBER(serial_keyboard_device::tx_r)
{
	return m_rbit;
}

const device_type SERIAL_KEYBOARD = &device_creator<serial_keyboard_device>;