summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sh/sh_sci.h
blob: 3c36a346254688d1f727be7d07079c1a4ccfb531 (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
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************

    sh_sci.h

    SH Serial Communications Interface


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

#ifndef MAME_CPU_SH_SH_SCI_H
#define MAME_CPU_SH_SH_SCI_H

#pragma once

class sh7042_device;
class sh_intc_device;

class sh_sci_device : public device_t {
public:
	sh_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
	template<typename T, typename U> sh_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, int id, T &&cpu, U &&intc, int eri, int rxi, int txi, int tei)
		: sh_sci_device(mconfig, tag, owner, 0)
	{
		m_cpu.set_tag(std::forward<T>(cpu));
		m_intc.set_tag(std::forward<U>(intc));
		m_id = id;
		m_eri_int = eri;
		m_rxi_int = rxi;
		m_txi_int = txi;
		m_tei_int = tei;
	}

	void do_set_external_clock_period(const attotime &_period);

	void smr_w(u8 data);
	u8 smr_r();
	void brr_w(u8 data);
	u8 brr_r();
	void scr_w(u8 data);
	u8 scr_r();
	void tdr_w(u8 data);
	u8 tdr_r();
	void ssr_w(u8 data);
	u8 ssr_r();
	u8 rdr_r();
	void scmr_w(u8 data);
	u8 scmr_r();

	void do_rx_w(int state);
	void do_clk_w(int state);

	u64 internal_update(u64 current_time);

protected:
	enum {
		ST_IDLE, ST_START, ST_BIT, ST_PARITY, ST_STOP, ST_LAST_TICK
	};

	static const char *const state_names[];

	enum {
		CLK_TX = 1,
		CLK_RX = 2
	};

	enum {
		INTERNAL_ASYNC,
		INTERNAL_ASYNC_OUT,
		EXTERNAL_ASYNC,
		EXTERNAL_RATE_ASYNC,
		INTERNAL_SYNC_OUT,
		EXTERNAL_SYNC,
		EXTERNAL_RATE_SYNC
	};

	enum {
		SMR_CA   = 0x80,
		SMR_CHR  = 0x40,
		SMR_PE   = 0x20,
		SMR_OE   = 0x10,
		SMR_STOP = 0x08,
		SMR_MP   = 0x04,
		SMR_CKS  = 0x03,

		SCR_TIE  = 0x80,
		SCR_RIE  = 0x40,
		SCR_TE   = 0x20,
		SCR_RE   = 0x10,
		SCR_MPIE = 0x08,
		SCR_TEIE = 0x04,
		SCR_CKE  = 0x03,
		SCR_CKE1 = 0x02,
		SCR_CKE0 = 0x01,

		SSR_TDRE = 0x80,
		SSR_RDRF = 0x40,
		SSR_ORER = 0x20,
		SSR_FER  = 0x10,
		SSR_PER  = 0x08,
		SSR_TEND = 0x04,
		SSR_MPB  = 0x02,
		SSR_MPBT = 0x01
	};

	required_device<sh7042_device> m_cpu;
	required_device<sh_intc_device> m_intc;
	attotime m_external_clock_period;
	double m_external_to_internal_ratio, m_internal_to_external_ratio;

	int m_id, m_eri_int, m_rxi_int, m_txi_int, m_tei_int;

	int m_tx_state, m_rx_state, m_tx_bit, m_rx_bit, m_clock_state, m_tx_parity, m_rx_parity, m_tx_clock_counter, m_rx_clock_counter;
	u32 m_clock_mode;
	bool m_ext_clock_value, m_rx_value;

	u8 m_rdr, m_tdr, m_smr, m_scr, m_ssr, m_brr, m_rsr, m_tsr;
	u64 m_clock_event, m_clock_step, m_divider;

	std::string m_last_clock_message;

	void device_start() override ATTR_COLD;
	void device_reset() override ATTR_COLD;

	TIMER_CALLBACK_MEMBER(sync_tick);

	void clock_start(int mode);
	void clock_stop(int mode);
	void clock_update();

	void tx_start();
	void tx_async_tick();
	void tx_async_step();
	void tx_sync_tick();
	void tx_sync_step();

	void rx_start();
	void rx_done();
	void rx_async_tick();
	void rx_async_step();
	void rx_sync_tick();
	void rx_sync_step();

	bool is_sync_start() const;
	bool has_recv_error() const;
};

DECLARE_DEVICE_TYPE(SH_SCI, sh_sci_device)

#endif // MAME_CPU_SH_SH_SCI_H