summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/bus/rs232/rs232.h
blob: 56c8ec7b89605cd5a202c130d79e74ce86cebe1f (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
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
// license:BSD-3-Clause
// copyright-holders:smf,Vas Crabb
#ifndef MAME_BUS_RS232_RS232_H
#define MAME_BUS_RS232_RS232_H

#pragma once


#define MCFG_RS232_RXD_HANDLER(_devcb) \
	devcb = &downcast<rs232_port_device &>(*device).set_rxd_handler(DEVCB_##_devcb);

#define MCFG_RS232_DCD_HANDLER(_devcb) \
	devcb = &downcast<rs232_port_device &>(*device).set_dcd_handler(DEVCB_##_devcb);

#define MCFG_RS232_DSR_HANDLER(_devcb) \
	devcb = &downcast<rs232_port_device &>(*device).set_dsr_handler(DEVCB_##_devcb);

#define MCFG_RS232_RI_HANDLER(_devcb) \
	devcb = &downcast<rs232_port_device &>(*device).set_ri_handler(DEVCB_##_devcb);

#define MCFG_RS232_SI_HANDLER(_devcb) \
	devcb = &downcast<rs232_port_device &>(*device).set_si_handler(DEVCB_##_devcb);

#define MCFG_RS232_CTS_HANDLER(_devcb) \
	devcb = &downcast<rs232_port_device &>(*device).set_cts_handler(DEVCB_##_devcb);

#define MCFG_RS232_RXC_HANDLER(_devcb) \
	devcb = &downcast<rs232_port_device &>(*device).set_rxc_handler(DEVCB_##_devcb);

#define MCFG_RS232_TXC_HANDLER(_devcb) \
	devcb = &downcast<rs232_port_device &>(*device).set_txc_handler(DEVCB_##_devcb);

#define RS232_BAUD_110 (0x00)
#define RS232_BAUD_150 (0x01)
#define RS232_BAUD_300 (0x02)
#define RS232_BAUD_600 (0x03)
#define RS232_BAUD_1200 (0x04)
#define RS232_BAUD_2400 (0x05)
#define RS232_BAUD_4800 (0x06)
#define RS232_BAUD_9600 (0x07)
#define RS232_BAUD_14400 (0x08)
#define RS232_BAUD_19200 (0x09)
#define RS232_BAUD_28800 (0x0a)
#define RS232_BAUD_38400 (0x0b)
#define RS232_BAUD_57600 (0x0c)
#define RS232_BAUD_115200 (0x0d)

#define MCFG_RS232_BAUD(_tag, _default_baud, _description, _class, _write_line) \
	PORT_START(_tag) \
	PORT_CONFNAME(0xff, _default_baud, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
	PORT_CONFSETTING( RS232_BAUD_110, "110") \
	PORT_CONFSETTING( RS232_BAUD_150, "150") \
	PORT_CONFSETTING( RS232_BAUD_300, "300") \
	PORT_CONFSETTING( RS232_BAUD_600, "600") \
	PORT_CONFSETTING( RS232_BAUD_1200, "1200") \
	PORT_CONFSETTING( RS232_BAUD_2400, "2400") \
	PORT_CONFSETTING( RS232_BAUD_4800, "4800") \
	PORT_CONFSETTING( RS232_BAUD_9600, "9600") \
	PORT_CONFSETTING( RS232_BAUD_14400, "14400") \
	PORT_CONFSETTING( RS232_BAUD_19200, "19200") \
	PORT_CONFSETTING( RS232_BAUD_28800, "28800") \
	PORT_CONFSETTING( RS232_BAUD_38400, "38400") \
	PORT_CONFSETTING( RS232_BAUD_57600, "57600") \
	PORT_CONFSETTING( RS232_BAUD_115200, "115200")

#define RS232_STARTBITS_0 (0x00)
#define RS232_STARTBITS_1 (0x01)

#define MCFG_RS232_STARTBITS(_tag, _default_startbits, _description, _class, _write_line) \
	PORT_START(_tag) \
	PORT_CONFNAME(0xff, _default_startbits, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
	PORT_CONFSETTING( RS232_STARTBITS_0, "0") \
	PORT_CONFSETTING( RS232_STARTBITS_1, "1")

#define RS232_DATABITS_5 (0x00)
#define RS232_DATABITS_6 (0x01)
#define RS232_DATABITS_7 (0x02)
#define RS232_DATABITS_8 (0x03)

#define MCFG_RS232_DATABITS(_tag, _default_databits, _description, _class, _write_line) \
	PORT_START(_tag) \
	PORT_CONFNAME(0xff, _default_databits, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
	PORT_CONFSETTING( RS232_DATABITS_5, "5") \
	PORT_CONFSETTING( RS232_DATABITS_6, "6") \
	PORT_CONFSETTING( RS232_DATABITS_7, "7") \
	PORT_CONFSETTING( RS232_DATABITS_8, "8")

#define RS232_PARITY_NONE (0x00)
#define RS232_PARITY_ODD (0x01)
#define RS232_PARITY_EVEN (0x02)
#define RS232_PARITY_MARK (0x03)
#define RS232_PARITY_SPACE (0x04)

#define MCFG_RS232_PARITY(_tag, _default_parity, _description, _class, _write_line) \
	PORT_START(_tag) \
	PORT_CONFNAME(0xff, _default_parity, "Parity") PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
	PORT_CONFSETTING( RS232_PARITY_NONE, "None") \
	PORT_CONFSETTING( RS232_PARITY_ODD, "Odd") \
	PORT_CONFSETTING( RS232_PARITY_EVEN, "Even") \
	PORT_CONFSETTING( RS232_PARITY_MARK, "Mark") \
	PORT_CONFSETTING( RS232_PARITY_SPACE, "Space")

#define RS232_STOPBITS_0 (0x00)
#define RS232_STOPBITS_1 (0x01)
#define RS232_STOPBITS_1_5 (0x02)
#define RS232_STOPBITS_2 (0x03)

#define MCFG_RS232_STOPBITS(_tag, _default_stopbits, _description, _class, _write_line) \
	PORT_START(_tag) \
	PORT_CONFNAME(0xff, 0x01, _description) PORT_WRITE_LINE_DEVICE_MEMBER(DEVICE_SELF, _class, _write_line) \
	PORT_CONFSETTING( RS232_STOPBITS_0, "0") \
	PORT_CONFSETTING( RS232_STOPBITS_1, "1") \
	PORT_CONFSETTING( RS232_STOPBITS_1_5, "1.5") \
	PORT_CONFSETTING( RS232_STOPBITS_2, "2")

class device_rs232_port_interface;

class rs232_port_device : public device_t, public device_slot_interface
{
	friend class device_rs232_port_interface;

public:
	template <typename T>
	rs232_port_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&opts, const char *dflt)
		: rs232_port_device(mconfig, tag, owner, 0)
	{
		option_reset();
		opts(*this);
		set_default_option(dflt);
		set_fixed(false);
	}
	rs232_port_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
	virtual ~rs232_port_device();

	// static configuration helpers
	template <class Object> devcb_base &set_rxd_handler(Object &&cb) { return m_rxd_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_dcd_handler(Object &&cb) { return m_dcd_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_dsr_handler(Object &&cb) { return m_dsr_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_ri_handler(Object &&cb) { return m_ri_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_si_handler(Object &&cb) { return m_si_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_cts_handler(Object &&cb) { return m_cts_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_rxc_handler(Object &&cb) { return m_rxc_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_txc_handler(Object &&cb) { return m_txc_handler.set_callback(std::forward<Object>(cb)); }

	DECLARE_WRITE_LINE_MEMBER( write_txd );
	DECLARE_WRITE_LINE_MEMBER( write_dtr );
	DECLARE_WRITE_LINE_MEMBER( write_rts );
	DECLARE_WRITE_LINE_MEMBER( write_etc );
	DECLARE_WRITE_LINE_MEMBER( write_spds );

	DECLARE_READ_LINE_MEMBER( rxd_r ) { return m_rxd; }
	DECLARE_READ_LINE_MEMBER( dcd_r ) { return m_dcd; }
	DECLARE_READ_LINE_MEMBER( dsr_r ) { return m_dsr; }
	DECLARE_READ_LINE_MEMBER( ri_r )  { return m_ri; }
	DECLARE_READ_LINE_MEMBER( si_r )  { return m_si; }
	DECLARE_READ_LINE_MEMBER( cts_r ) { return m_cts; }
	DECLARE_READ_LINE_MEMBER( rxc_r ) { return m_dce_rxc; }
	DECLARE_READ_LINE_MEMBER( txc_r ) { return m_dce_txc; }

protected:
	rs232_port_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);

	virtual void device_resolve_objects() override;
	virtual void device_start() override;
	virtual void device_config_complete() override;

	int m_rxd;
	int m_dcd;
	int m_dsr;
	int m_ri;
	int m_si;
	int m_cts;
	int m_dce_rxc;
	int m_dce_txc;

	devcb_write_line m_rxd_handler;
	devcb_write_line m_dcd_handler;
	devcb_write_line m_dsr_handler;
	devcb_write_line m_ri_handler;
	devcb_write_line m_si_handler;
	devcb_write_line m_cts_handler;
	devcb_write_line m_rxc_handler;
	devcb_write_line m_txc_handler;

private:
	device_rs232_port_interface *m_dev;
};

class device_rs232_port_interface : public device_slot_card_interface
{
	friend class rs232_port_device;

public:
	virtual ~device_rs232_port_interface();

	virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) { }
	virtual DECLARE_WRITE_LINE_MEMBER( input_dtr ) { }
	virtual DECLARE_WRITE_LINE_MEMBER( input_rts ) { }
	virtual DECLARE_WRITE_LINE_MEMBER( input_etc ) { }
	virtual DECLARE_WRITE_LINE_MEMBER( input_spds ) { }

	DECLARE_WRITE_LINE_MEMBER( output_rxd ) { m_port->m_rxd = state; m_port->m_rxd_handler(state); }
	DECLARE_WRITE_LINE_MEMBER( output_dcd ) { m_port->m_dcd = state; m_port->m_dcd_handler(state); }
	DECLARE_WRITE_LINE_MEMBER( output_dsr ) { m_port->m_dsr = state; m_port->m_dsr_handler(state); }
	DECLARE_WRITE_LINE_MEMBER( output_ri )  { m_port->m_ri = state; m_port->m_ri_handler(state); }
	DECLARE_WRITE_LINE_MEMBER( output_si )  { m_port->m_si = state; m_port->m_si_handler(state); }
	DECLARE_WRITE_LINE_MEMBER( output_cts ) { m_port->m_cts = state; m_port->m_cts_handler(state); }
	DECLARE_WRITE_LINE_MEMBER( output_rxc ) { m_port->m_dce_rxc = state; m_port->m_rxc_handler(state); }
	DECLARE_WRITE_LINE_MEMBER( output_txc ) { m_port->m_dce_txc = state; m_port->m_txc_handler(state); }

protected:
	device_rs232_port_interface(const machine_config &mconfig, device_t &device);

	rs232_port_device *m_port;

	static int convert_baud(uint8_t baud)
	{
		static const int values[] =
		{
			110,
			150,
			300,
			600,
			1200,
			2400,
			4800,
			9600,
			14400,
			19200,
			28800,
			38400,
			57600,
			115200
		};

		return values[baud];
	}

	static int convert_startbits(uint8_t startbits)
	{
		static const int values[] =
		{
			0,
			1
		};

		return values[startbits];
	}

	static int convert_databits(uint8_t databits)
	{
		static const int values[] =
		{
			5,
			6,
			7,
			8
		};

		return values[databits];
	}

	static device_serial_interface::parity_t convert_parity(uint8_t parity)
	{
		static const device_serial_interface::parity_t values[] =
		{
			device_serial_interface::PARITY_NONE,
			device_serial_interface::PARITY_ODD,
			device_serial_interface::PARITY_EVEN,
			device_serial_interface::PARITY_MARK,
			device_serial_interface::PARITY_SPACE
		};

		return values[parity];
	}

	static device_serial_interface::stop_bits_t convert_stopbits(uint8_t stopbits)
	{
		static const device_serial_interface::stop_bits_t values[] =
		{
			device_serial_interface::STOP_BITS_0,
			device_serial_interface::STOP_BITS_1,
			device_serial_interface::STOP_BITS_1_5,
			device_serial_interface::STOP_BITS_2
		};

		return values[stopbits];
	}
};

template <uint32_t FIFO_LENGTH>
class buffered_rs232_device : public device_t, public device_buffered_serial_interface<FIFO_LENGTH>, public device_rs232_port_interface
{
public:
	virtual DECLARE_WRITE_LINE_MEMBER( input_txd ) override
	{
		device_buffered_serial_interface<FIFO_LENGTH>::rx_w(state);
	}

protected:
	buffered_rs232_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
		: device_t(mconfig, type, tag, owner, clock)
		, device_buffered_serial_interface<FIFO_LENGTH>(mconfig, *this)
		, device_rs232_port_interface(mconfig, *this)
	{
	}

	virtual void device_start() override
	{
	}

	virtual void tra_callback() override
	{
		output_rxd(this->transmit_register_get_data_bit());
	}
};

DECLARE_DEVICE_TYPE(RS232_PORT, rs232_port_device)

void default_rs232_devices(device_slot_interface &device);

#endif // MAME_BUS_RS232_RS232_H