summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/i8251.h
blob: cf966ac2693dbdbd2be52713476e12ab35e5faa2 (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
// license:BSD-3-Clause
// copyright-holders:smf
/*********************************************************************

    i8251.h

    Intel 8251 Universal Synchronous/Asynchronous Receiver Transmitter code

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

#ifndef MAME_DEVICES_MACHINE_I8251_H
#define MAME_DEVICES_MACHINE_I8251_H


//**************************************************************************
//  INTERFACE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_I8251_TXD_HANDLER(_devcb) \
	devcb = &i8251_device::set_txd_handler(*device, DEVCB_##_devcb);

#define MCFG_I8251_DTR_HANDLER(_devcb) \
	devcb = &i8251_device::set_dtr_handler(*device, DEVCB_##_devcb);

#define MCFG_I8251_RTS_HANDLER(_devcb) \
	devcb = &i8251_device::set_rts_handler(*device, DEVCB_##_devcb);

#define MCFG_I8251_RXRDY_HANDLER(_devcb) \
	devcb = &i8251_device::set_rxrdy_handler(*device, DEVCB_##_devcb);

#define MCFG_I8251_TXRDY_HANDLER(_devcb) \
	devcb = &i8251_device::set_txrdy_handler(*device, DEVCB_##_devcb);

#define MCFG_I8251_TXEMPTY_HANDLER(_devcb) \
	devcb = &i8251_device::set_txempty_handler(*device, DEVCB_##_devcb);

#define MCFG_I8251_SYNDET_HANDLER(_devcb) \
	devcb = &i8251_device::set_syndet_handler(*device, DEVCB_##_devcb);

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

	// static configuration helpers
	template<class _Object> static devcb_base &set_txd_handler(device_t &device, _Object object) { return downcast<i8251_device &>(device).m_txd_handler.set_callback(object); }
	template<class _Object> static devcb_base &set_dtr_handler(device_t &device, _Object object) { return downcast<i8251_device &>(device).m_dtr_handler.set_callback(object); }
	template<class _Object> static devcb_base &set_rts_handler(device_t &device, _Object object) { return downcast<i8251_device &>(device).m_rts_handler.set_callback(object); }
	template<class _Object> static devcb_base &set_rxrdy_handler(device_t &device, _Object object) { return downcast<i8251_device &>(device).m_rxrdy_handler.set_callback(object); }
	template<class _Object> static devcb_base &set_txrdy_handler(device_t &device, _Object object) { return downcast<i8251_device &>(device).m_txrdy_handler.set_callback(object); }
	template<class _Object> static devcb_base &set_txempty_handler(device_t &device, _Object object) { return downcast<i8251_device &>(device).m_txempty_handler.set_callback(object); }
	template<class _Object> static devcb_base &set_syndet_handler(device_t &device, _Object object) { return downcast<i8251_device &>(device).m_syndet_handler.set_callback(object); }

	DECLARE_READ8_MEMBER(data_r);
	DECLARE_WRITE8_MEMBER(data_w);
	DECLARE_READ8_MEMBER(status_r);
	DECLARE_WRITE8_MEMBER(control_w);

	DECLARE_WRITE_LINE_MEMBER( write_rxd );
	DECLARE_WRITE_LINE_MEMBER( write_cts );
	DECLARE_WRITE_LINE_MEMBER( write_dsr );
	DECLARE_WRITE_LINE_MEMBER( write_txc );
	DECLARE_WRITE_LINE_MEMBER( write_rxc );

	/// TODO: REMOVE THIS
	void receive_character(uint8_t ch);

	/// TODO: this shouldn't be public
	enum
	{
		I8251_STATUS_FRAMING_ERROR = 0x20,
		I8251_STATUS_OVERRUN_ERROR = 0x10,
		I8251_STATUS_PARITY_ERROR = 0x08,
		I8251_STATUS_TX_EMPTY = 0x04,
		I8251_STATUS_RX_READY = 0x02,
		I8251_STATUS_TX_READY = 0x01
	};

protected:
	i8251_device(
			const machine_config &mconfig,
			device_type type,
			const char *name,
			const char *tag,
			device_t *owner,
			uint32_t clock,
			const char *shortname,
			const char *source);

	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;

	void command_w(uint8_t data);
	void mode_w(uint8_t data);

	void update_rx_ready();
	void update_tx_ready();
	void update_tx_empty();
	void transmit_clock();
	void receive_clock();
	bool is_tx_enabled() const;
	void check_for_tx_start();
	void start_tx();


	enum
	{
		I8251_EXPECTING_MODE = 0x01,
		I8251_EXPECTING_SYNC_BYTE = 0x02,
				I8251_DELAYED_TX_EN = 0x04
	};

private:
	devcb_write_line m_txd_handler;
	devcb_write_line m_dtr_handler;
	devcb_write_line m_rts_handler;
	devcb_write_line m_rxrdy_handler;
	devcb_write_line m_txrdy_handler;
	devcb_write_line m_txempty_handler;
	devcb_write_line m_syndet_handler;

	/* flags controlling how i8251_control_w operates */
	uint8_t m_flags;
	/* offset into sync_bytes used during sync byte transfer */
	uint8_t m_sync_byte_offset;
	/* number of sync bytes written so far */
	uint8_t m_sync_byte_count;
	/* the sync bytes written */
	uint8_t m_sync_bytes[2];
	/* status of i8251 */
	uint8_t m_status;
	uint8_t m_command;
	/* mode byte - bit definitions depend on mode - e.g. synchronous, asynchronous */
	uint8_t m_mode_byte;

	int m_cts;
	int m_dsr;
	int m_rxd;
	int m_rxc;
	int m_txc;
	int m_rxc_count;
	int m_txc_count;
	int m_br_factor;

	/* data being received */
	uint8_t m_rx_data;
		/* tx buffer */
	uint8_t m_tx_data;
};

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

	DECLARE_WRITE8_MEMBER(command_w);
	DECLARE_WRITE8_MEMBER(mode_w);
};



// device type definition
extern const device_type I8251;
extern const device_type V53_SCU;

extern template class device_finder<i8251_device, false>;
extern template class device_finder<i8251_device, true>;
extern template class device_finder<v53_scu_device, false>;
extern template class device_finder<v53_scu_device, true>;


#endif // MAME_DEVICES_MACHINE_I8251_H