summaryrefslogtreecommitdiffstats
path: root/src/devices/machine/6850acia.h
blob: 1dc975911d897582886c1efa443df12260ba3b87 (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
// license:BSD-3-Clause
// copyright-holders:smf
/*********************************************************************

    6850acia.h

    6850 ACIA code

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

#ifndef MAME_MACHINE_6850ACIA_H
#define MAME_MACHINE_6850ACIA_H

#pragma once


#define MCFG_ACIA6850_TXD_HANDLER(_devcb) \
	devcb = &downcast<acia6850_device &>(*device).set_txd_handler(DEVCB_##_devcb);

#define MCFG_ACIA6850_RTS_HANDLER(_devcb) \
	devcb = &downcast<acia6850_device &>(*device).set_rts_handler(DEVCB_##_devcb);

#define MCFG_ACIA6850_IRQ_HANDLER(_devcb) \
	devcb = &downcast<acia6850_device &>(*device).set_irq_handler(DEVCB_##_devcb);

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

	// static configuration helpers
	template <class Object> devcb_base &set_txd_handler(Object &&cb) { return m_txd_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_rts_handler(Object &&cb) { return m_rts_handler.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_irq_handler(Object &&cb) { return m_irq_handler.set_callback(std::forward<Object>(cb)); }

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

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

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

	// device-level overrides
	virtual void device_start() override;
	virtual void device_reset() override;

	virtual void update_irq();
	int calculate_txirq();
	int calculate_rxirq();

private:
	void output_txd(int txd);
	void output_rts(int txd);
	void output_irq(int irq);

	TIMER_CALLBACK_MEMBER(delayed_output_irq);

	enum
	{
		SR_RDRF = 0x01,
		SR_TDRE = 0x02,
		SR_DCD = 0x04,
		SR_CTS = 0x08,
		SR_FE = 0x10,
		SR_OVRN = 0x20,
		SR_PE = 0x40,
		SR_IRQ = 0x80
	};

	enum serial_state
	{
		STATE_START,
		STATE_DATA,
		STATE_STOP
	};

	enum parity_type
	{
		PARITY_NONE,
		PARITY_ODD,
		PARITY_EVEN
	};

	enum dcd_irq_state
	{
		DCD_IRQ_NONE = 0,
		DCD_IRQ_READ_DATA,
		DCD_IRQ_READ_STATUS
	};

	devcb_write_line m_txd_handler;
	devcb_write_line m_rts_handler;
	devcb_write_line m_irq_handler;

	uint8_t m_status;
	uint8_t m_tdr;
	uint8_t m_rdr;

	bool m_first_master_reset;
	int m_dcd_irq_pending;
	bool m_overrun_pending;

	int m_divide;
	int m_bits;
	int m_stopbits;
	int m_parity;
	int m_brk;

	int m_rts;
	int m_dcd;
	int m_irq;

	int m_txc;
	int m_txd;
	int m_tx_state;
	int m_tx_bits;
	int m_tx_shift;
	int m_tx_parity;
	int m_tx_counter;
	int m_tx_irq_enable;

	int m_rxc;
	int m_rxd;
	int m_rx_state;
	int m_rx_bits;
	int m_rx_shift;
	int m_rx_parity;
	int m_rx_counter;
	int m_rx_irq_enable;

	static const int counter_divide_select[4];
	static const int word_select[8][3];
	static const int transmitter_control[4][3];
};

// device type definition
DECLARE_DEVICE_TYPE(ACIA6850, acia6850_device)

#endif // MAME_MACHINE_6850ACIA_H