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__ */
|