summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/6526cia.h
blob: b28952c4a2bc377d8a30c4079bd67dff5703f6cd (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
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
/**********************************************************************

    MOS 6526/8520 Complex Interface Adapter emulation

    Copyright MESS Team.
    Visit http://mamedev.org for licensing and usage restrictions.

**********************************************************************
                            _____   _____
                   Vss   1 |*    \_/     | 40  CNT
                   PA0   2 |             | 39  SP
                   PA1   3 |             | 38  RS0
                   PA2   4 |             | 37  RS1
                   PA3   5 |             | 36  RS2
                   PA4   6 |             | 35  RS3
                   PA5   7 |             | 34  _RES
                   PA6   8 |             | 33  DB0
                   PA7   9 |             | 32  DB1
                   PB0  10 |   MOS6526   | 31  DB2
                   PB1  11 |   MOS8520   | 30  DB3
                   PB2  12 |             | 29  DB4
                   PB3  13 |             | 28  DB5
                   PB4  14 |             | 27  DB6
                   PB5  15 |             | 26  DB7
                   PB6  16 |             | 25  phi2
                   PB7  17 |             | 24  _FLAG
                   _PC  18 |             | 23  _CS
                   TOD  19 |             | 22  R/W
                   Vcc  20 |_____________| 21  _IRQ

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

#pragma once

#ifndef __6526CIA_H__
#define __6526CIA_H__

#include "emu.h"



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

#define MCFG_MOS6526R1_ADD(_tag, _clock, _tod_clock, _config) \
	MCFG_DEVICE_ADD(_tag, MOS6526R1, _clock) \
	MCFG_DEVICE_CONFIG(_config) \
	mos6526_device::static_set_tod_clock(*device, _tod_clock);

#define MCFG_MOS6526R2_ADD(_tag, _clock, _tod_clock, _config) \
	MCFG_DEVICE_ADD(_tag, MOS6526R2, _clock) \
	MCFG_DEVICE_CONFIG(_config) \
	mos6526_device::static_set_tod_clock(*device, _tod_clock);

#define MCFG_MOS8520_ADD(_tag, _clock, _tod_clock, _config) \
	MCFG_DEVICE_ADD(_tag, MOS8520, _clock) \
	MCFG_DEVICE_CONFIG(_config) \
	mos6526_device::static_set_tod_clock(*device, _tod_clock);

#define MCFG_MOS5710_ADD(_tag, _clock, _tod_clock, _config) \
	MCFG_DEVICE_ADD(_tag, MOS5710, _clock) \
	MCFG_DEVICE_CONFIG(_config) \
	mos6526_device::static_set_tod_clock(*device, _tod_clock);


#define MOS6526_INTERFACE(name) \
	const mos6526_interface (name)=

#define MOS8520_INTERFACE(name) \
	const mos6526_interface (name)=

#define MOS5710_INTERFACE(name) \
	const mos6526_interface (name)=



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


// ======================> mos6526_interface

struct mos6526_interface
{
	devcb_write_line	m_out_irq_cb;
	devcb_write_line	m_out_pc_cb;
	devcb_write_line	m_out_cnt_cb;
	devcb_write_line	m_out_sp_cb;

	devcb_read8			m_in_pa_cb;
	devcb_write8		m_out_pa_cb;

	devcb_read8			m_in_pb_cb;
	devcb_write8		m_out_pb_cb;
};



// ======================> mos6526_device

class mos6526_device :  public device_t,
                        public mos6526_interface
{
protected:
    // construction/destruction
    mos6526_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);

public:
	// inline configuration
	static void static_set_tod_clock(device_t &device, int tod_clock);

	DECLARE_READ8_MEMBER( read );
	DECLARE_WRITE8_MEMBER( write );
	
	UINT8 reg_r(UINT8 offset);
	void reg_w(UINT8 offset, UINT8 data);

	/* port access */
	UINT8 pa_r(UINT8 offset) { return (m_port[0].m_latch | ~m_port[0].m_ddr); }
	UINT8 pb_r(UINT8 offset) { return (m_port[1].m_latch | ~m_port[1].m_ddr); }

	/* interrupt request */
	UINT8 irq_r() { return m_irq; }

	/* time of day clock */
	void tod_w(UINT8 state) { if(state) clock_tod(); }

	/* serial counter */
	UINT8 cnt_r() { return m_cnt; }
	void cnt_w(UINT8 state);

	/* serial port */
	UINT8 sp_r() { return m_sp; }
	void sp_w(UINT8 state) { m_sp = state; }

	/* flag */
	void flag_w(UINT8 state);

	/* port mask */
	void set_port_mask_value(int port, int data);

protected:
    // device-level overrides
    virtual void device_config_complete();
    virtual void device_start();
    virtual void device_reset();
    virtual void device_post_load() { }
    virtual void device_clock_changed() { }
	virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);

	static TIMER_CALLBACK( timer_proc );
	static TIMER_CALLBACK( clock_tod_callback );

private:
	enum
	{
		TIMER_PC,
		TIMER_TOD
	};

    inline attotime cycles_to_time(int c);
	void update_pc();
	void update_interrupts();
	void timer_bump(int timer);
	void timer_underflow(int timer);
	void increment();
	void clock_tod();

	struct cia_timer
	{
	public:
		cia_timer() { }

		UINT16 get_count();
		void update(int which, INT32 new_count);

		UINT32			m_clock;
		UINT16			m_latch;
		UINT16			m_count;
		UINT8			m_mode;
		UINT8			m_irq;
		emu_timer*		m_timer;
		mos6526_device*	m_cia;
	};

	struct cia_port
	{
		UINT8		m_ddr;
		UINT8		m_latch;
		UINT8		m_in;
		UINT8		m_out;
		devcb_resolved_read8	m_read;
		devcb_resolved_write8	m_write;
		UINT8		m_mask_value; /* in READ operation the value can be forced by a extern electric circuit */
	};

	devcb_resolved_write_line m_out_irq_func;
	devcb_resolved_write_line m_out_pc_func;
	devcb_resolved_write_line m_out_cnt_func;
	devcb_resolved_write_line m_out_sp_func;

	cia_port		m_port[2];
	cia_timer		m_timer[2];

	/* Time Of the Day clock (TOD) */
	int				m_tod_clock;
	UINT32			m_tod;
	UINT32			m_tod_latch;
	UINT8			m_tod_latched;
	UINT8			m_tod_running;
	UINT32			m_alarm;

	/* Interrupts */
	UINT8			m_icr;
	UINT8			m_ics;
	UINT8			m_irq;
	int				m_flag;

	/* Serial */
	UINT8			m_loaded;
	UINT8			m_sdr;
	UINT8			m_sp;
	UINT8			m_cnt;
	UINT8			m_shift;
	UINT8			m_serial;

	emu_timer *m_pc_timer;
	emu_timer *m_tod_timer;
};

class mos6526r1_device : public mos6526_device
{
public:
	mos6526r1_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};

class mos6526r2_device : public mos6526_device
{
public:
	mos6526r2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};

class mos8520_device : public mos6526_device
{
public:
	mos8520_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};

class mos5710_device : public mos6526_device
{
public:
	mos5710_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
};


// device type definition
extern const device_type MOS6526R1;
extern const device_type MOS6526R2;
extern const device_type MOS8520;
extern const device_type MOS5710;



/***************************************************************************
    FUNCTION PROTOTYPES
***************************************************************************/

/* register access */
READ8_DEVICE_HANDLER( mos6526_r );
WRITE8_DEVICE_HANDLER( mos6526_w );

/* port access */
READ8_DEVICE_HANDLER( mos6526_pa_r );
READ8_DEVICE_HANDLER( mos6526_pb_r );

/* interrupt request */
READ_LINE_DEVICE_HANDLER( mos6526_irq_r );

/* time of day clock */
WRITE_LINE_DEVICE_HANDLER( mos6526_tod_w );

/* serial counter */
READ_LINE_DEVICE_HANDLER( mos6526_cnt_r );
WRITE_LINE_DEVICE_HANDLER( mos6526_cnt_w );

/* serial port */
READ_LINE_DEVICE_HANDLER( mos6526_sp_r );
WRITE_LINE_DEVICE_HANDLER( mos6526_sp_w );

/* flag */
WRITE_LINE_DEVICE_HANDLER( mos6526_flag_w );

/* port mask */
void cia_set_port_mask_value(device_t *device, int port, int data);

#endif /* __6526CIA_H__ */