summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/scc2698b.h
blob: f693c6df50ae235638bc308dad9b5b6987bebf0f (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
// license:GPL-2.0+
// copyright-holders:Brandon Munger, Stephen Stair
#ifndef MAME_MACHINE_SCC2698B_H
#define MAME_MACHINE_SCC2698B_H

#include "diserial.h"

// _port should be a letter port index from "a" .. "h"



class scc2698b_device;

class scc2698b_channel : public device_t, public device_serial_interface
{
	friend class scc2698b_device;
public:
	scc2698b_channel(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	DECLARE_WRITE_LINE_MEMBER(mpi0_w);
	DECLARE_WRITE_LINE_MEMBER(mpi1_w);

	virtual void rcv_complete() override;    // Rx completed receiving byte
	virtual void tra_complete() override;    // Tx completed sending byte
	virtual void tra_callback() override;    // Tx send bit

	void write_TXH(int txh);
	int read_RXH();

	void reset_all();
	void reset_tx();
	void reset_rx();

	void set_tx_enable(bool enable);
	void set_rx_enable(bool enable);

	void update_serial_configuration();

	void set_tx_bittime(const attotime &bittime);
	void set_rx_bittime(const attotime &bittime);

	void set_mpp_output(bool output);


	int read_SR();

protected:
	static constexpr unsigned SCC2698B_RX_FIFO_SIZE = 3;

	virtual void device_start() override;
	virtual void device_reset() override;

//  devcb_write_line write_tx, write_mpp1, write_mpp2, write_mpo;

	int moderegister_ptr;

	int tx_transmitting;
	int tx_fifo;
	int tx_bytecount;
	u8 rx_fifo[SCC2698B_RX_FIFO_SIZE];
	int rx_bytecount;

	u8 MR1, MR2, SR, CR, CSR;

	bool tx_enable;
	bool rx_enable;

	void recompute_pin_output(bool force = false);
	int mpp1_value, mpp2_value;
	bool mpp_is_output;

	int channel_port;
	scc2698b_device* parent;
};

class scc2698b_device : public device_t
{
public:
	scc2698b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);

	virtual void map(address_map &map);

	DECLARE_READ8_MEMBER(read);
	DECLARE_WRITE8_MEMBER(write);

	void write_reg(int offset, uint8_t data);
	uint8_t read_reg(int offset);

	auto intr_A() { return write_intr_A.bind(); }
	auto intr_B() { return write_intr_B.bind(); }
	auto intr_C() { return write_intr_C.bind(); }
	auto intr_D() { return write_intr_D.bind(); }

	required_device_array<scc2698b_channel, 8> m_channel;

	DECLARE_WRITE_LINE_MEMBER(port_a_rx_w);
	DECLARE_WRITE_LINE_MEMBER(port_b_rx_w);
	DECLARE_WRITE_LINE_MEMBER(port_c_rx_w);
	DECLARE_WRITE_LINE_MEMBER(port_d_rx_w);
	DECLARE_WRITE_LINE_MEMBER(port_e_rx_w);
	DECLARE_WRITE_LINE_MEMBER(port_f_rx_w);
	DECLARE_WRITE_LINE_MEMBER(port_g_rx_w);
	DECLARE_WRITE_LINE_MEMBER(port_h_rx_w);


	void write_line_tx(int port, int value);
	void write_line_mpp1(int port, int value);
	void write_line_mpp2(int port, int value);
	void write_line_mpo(int port, int value);

	// assume contiguous letters - not EBCDIC-friendly
	template <char Port> auto tx_callback() { return write_tx[Port - 'a'].bind(); }
	template <char Port> auto mpp1_callback() { return write_mpp1[Port - 'a'].bind(); }
	template <char Port> auto mpp2_callback() { return write_mpp2[Port - 'a'].bind(); }
	template <char Port> auto mpo_callback() { return write_mpo[Port - 'a'].bind(); }

protected:
	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;
	virtual void device_add_mconfig(machine_config &config) override;

	devcb_write_line write_intr_A, write_intr_B, write_intr_C, write_intr_D;
	devcb_write_line::array<8> write_tx;
	devcb_write_line::array<8> write_mpp1;
	devcb_write_line::array<8> write_mpp2;
	devcb_write_line::array<8> write_mpo;

	scc2698b_channel* get_channel(int port);

	void reset_port(int port);
	void reset_port_tx(int port);
	void reset_port_rx(int port);

	void write_MR(int port, int value);
	void write_CSR(int port, int value);
	void write_CR(int port, int value);
	void write_THR(int port, int value);

	int read_MR(int port);
	int read_SR(int port);
	int read_RHR(int port);

	void update_block_baudrate(int block);
	void update_port_baudrate(int port);
	attotime generate_baudrate(int block, int tx, int table_index);


private:
	struct Block {
		u8 ACR;
	};

	Block m_blocks[4];

};

DECLARE_DEVICE_TYPE(SCC2698B, scc2698b_device)
DECLARE_DEVICE_TYPE(SCC2698B_CHANNEL, scc2698b_channel)

#endif // MAME_MACHINE_SCC2698B_H