summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/z80sti.h
blob: 794c5623a2e8c436db7209801168fb762a13cf62 (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
// license:BSD-3-Clause
// copyright-holders:Curt Coder
/**********************************************************************

    Mostek MK3801 Serial Timer Interrupt Controller (Z80-STI) emulation

**********************************************************************
                            _____   _____
                   TAO   1 |*    \_/     | 40  Vcc
                   TBO   2 |             | 39  RC
                   TCO   3 |             | 38  SI
                   TDO   4 |             | 37  SO
                   TCK   5 |             | 36  TC
                   _M1   6 |             | 35  A0
                  _RES   7 |             | 34  A1
                    I0   8 |             | 33  A2
                    I1   9 |             | 32  A3
                    I2  10 |   MK3801    | 31  _WR
                    I3  11 |   Z80-STI   | 30  _CE
                    I4  12 |             | 29  _RD
                    I5  13 |             | 28  D7
                    I6  14 |             | 27  D6
                    I7  15 |             | 26  D5
                   IEI  16 |             | 25  D4
                  _INT  17 |             | 24  D3
                   IEO  18 |             | 23  D2
                 _IORQ  19 |             | 22  D1
                   Vss  20 |_____________| 21  D0

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

#ifndef MAME_MACHINE_Z80STI_H
#define MAME_MACHINE_Z80STI_H

#pragma once

#include "machine/z80daisy.h"
#include "diserial.h"


//**************************************************************************
//  DEVICE CONFIGURATION MACROS
//**************************************************************************

#define MCFG_Z80STI_RXCLOCK(_clock) \
	downcast<z80sti_device &>(*device).set_rx_clock(_clock);

#define MCFG_Z80STI_TXCLOCK(_clock) \
	downcast<z80sti_device &>(*device).set_tx_clock(_clock);

#define MCFG_Z80STI_OUT_INT_CB(_devcb) \
	devcb = &downcast<z80sti_device &>(*device).set_out_int_callback(DEVCB_##_devcb);

#define MCFG_Z80STI_IN_GPIO_CB(_devcb) \
	devcb = &downcast<z80sti_device &>(*device).set_in_gpio_callback(DEVCB_##_devcb);

#define MCFG_Z80STI_OUT_GPIO_CB(_devcb) \
	devcb = &downcast<z80sti_device &>(*device).set_out_gpio_callback(DEVCB_##_devcb);

#define MCFG_Z80STI_OUT_SO_CB(_devcb) \
	devcb = &downcast<z80sti_device &>(*device).set_out_so_callback(DEVCB_##_devcb);

#define MCFG_Z80STI_OUT_TAO_CB(_devcb) \
	devcb = &downcast<z80sti_device &>(*device).set_out_tao_callback(DEVCB_##_devcb);

#define MCFG_Z80STI_OUT_TBO_CB(_devcb) \
	devcb = &downcast<z80sti_device &>(*device).set_out_tbo_callback(DEVCB_##_devcb);

#define MCFG_Z80STI_OUT_TCO_CB(_devcb) \
	devcb = &downcast<z80sti_device &>(*device).set_out_tco_callback(DEVCB_##_devcb);

#define MCFG_Z80STI_OUT_TDO_CB(_devcb) \
	devcb = &downcast<z80sti_device &>(*device).set_out_tdo_callback(DEVCB_##_devcb);

//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// ======================> z80sti_device

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

	template <class Object> devcb_base &set_out_int_callback(Object &&cb) { return m_out_int_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_in_gpio_callback(Object &&cb) { return m_in_gpio_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_gpio_callback(Object &&cb) { return m_out_gpio_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_so_callback(Object &&cb) { return m_out_so_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_tao_callback(Object &&cb) { return m_out_tao_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_tbo_callback(Object &&cb) { return m_out_tbo_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_tco_callback(Object &&cb) { return m_out_tco_cb.set_callback(std::forward<Object>(cb)); }
	template <class Object> devcb_base &set_out_tdo_callback(Object &&cb) { return m_out_tdo_cb.set_callback(std::forward<Object>(cb)); }

	void set_rx_clock(int clock) { m_rx_clock = clock; }
	void set_tx_clock(int clock) { m_tx_clock = clock; }

	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );

	DECLARE_WRITE_LINE_MEMBER( i0_w );
	DECLARE_WRITE_LINE_MEMBER( i1_w );
	DECLARE_WRITE_LINE_MEMBER( i2_w );
	DECLARE_WRITE_LINE_MEMBER( i3_w );
	DECLARE_WRITE_LINE_MEMBER( i4_w );
	DECLARE_WRITE_LINE_MEMBER( i5_w );
	DECLARE_WRITE_LINE_MEMBER( i6_w );
	DECLARE_WRITE_LINE_MEMBER( i7_w );

	DECLARE_WRITE_LINE_MEMBER( tc_w );
	DECLARE_WRITE_LINE_MEMBER( rc_w );

private:
	enum
	{
		TIMER_A = 0,
		TIMER_B,
		TIMER_C,
		TIMER_D
	};

	enum
	{
		REGISTER_IR = 0,
		REGISTER_GPIP,
		REGISTER_IPRB,
		REGISTER_IPRA,
		REGISTER_ISRB,
		REGISTER_ISRA,
		REGISTER_IMRB,
		REGISTER_IMRA,
		REGISTER_PVR,
		REGISTER_TABC,
		REGISTER_TBDR,
		REGISTER_TADR,
		REGISTER_UCR,
		REGISTER_RSR,
		REGISTER_TSR,
		REGISTER_UDR
	};

	enum
	{
		REGISTER_IR_SCR = 0,
		REGISTER_IR_TDDR,
		REGISTER_IR_TCDR,
		REGISTER_IR_AER,
		REGISTER_IR_IERB,
		REGISTER_IR_IERA,
		REGISTER_IR_DDR,
		REGISTER_IR_TCDC
	};

	enum
	{
		IR_P0 = 0,
		IR_P1,
		IR_P2,
		IR_P3,
		IR_TD,
		IR_TC,
		IR_P4,
		IR_P5,
		IR_TB,
		IR_XE,
		IR_XB,
		IR_RE,
		IR_RB,
		IR_TA,
		IR_P6,
		IR_P7
	};

	static const int INT_LEVEL_GPIP[];
	static const int INT_LEVEL_TIMER[];
	static const uint8_t INT_VECTOR[];
	static const int PRESCALER[];

	// 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;

	// device_serial_interface overrides
	virtual void tra_callback() override;
	virtual void tra_complete() override;
	virtual void rcv_complete() override;

	// device_z80daisy_interface overrides
	virtual int z80daisy_irq_state() override;
	virtual int z80daisy_irq_ack() override;
	virtual void z80daisy_irq_reti() override;

	// internal helpers
	void check_interrupts();
	void take_interrupt(int level);
	void timer_count(int index);
	void gpip_input(int bit, int state);

	// device callbacks
	devcb_write_line        m_out_int_cb;   // this gets called on each change of the _INT pin (pin 17)
	devcb_read8             m_in_gpio_cb;   // this is called on each read of the GPIO pins
	devcb_write8            m_out_gpio_cb;  // this is called on each write of the GPIO pins
	devcb_write_line        m_out_so_cb;    // this gets called for each change of the SO pin (pin 37)
	devcb_write_line        m_out_tao_cb;   // this gets called for each change of the TAO pin (pin 1)
	devcb_write_line        m_out_tbo_cb;   // this gets called for each change of the TBO pin (pin 2)
	devcb_write_line        m_out_tco_cb;   // this gets called for each change of the TCO pin (pin 3)
	devcb_write_line        m_out_tdo_cb;   // this gets called for each change of the TDO pin (pin 4)

	int m_rx_clock;                     // serial receive clock
	int m_tx_clock;                     // serial transmit clock

	// I/O state
	uint8_t m_gpip;                       // general purpose I/O register
	uint8_t m_aer;                        // active edge register
	uint8_t m_ddr;                        // data direction register

	// interrupt state
	uint16_t m_ier;                       // interrupt enable register
	uint16_t m_ipr;                       // interrupt pending register
	uint16_t m_isr;                       // interrupt in-service register
	uint16_t m_imr;                       // interrupt mask register
	uint8_t m_pvr;                        // interrupt vector register
	int m_int_state[16];                // interrupt state

	// timer state
	uint8_t m_tabc;                       // timer A/B control register
	uint8_t m_tcdc;                       // timer C/D control register
	uint8_t m_tdr[4];                     // timer data registers
	uint8_t m_tmc[4];                     // timer main counters
	int m_to[4];                        // timer out latch

	// serial state
	uint8_t m_scr;                        // synchronous character register
	uint8_t m_ucr;                        // USART control register
	uint8_t m_tsr;                        // transmitter status register
	uint8_t m_rsr;                        // receiver status register
	uint8_t m_udr;                        // USART data register

	// timers
	emu_timer *m_timer[4];              // counter timers
};


// device type definition
DECLARE_DEVICE_TYPE(Z80STI, z80sti_device)

#endif // MAME_MACHINE_Z80STI_H