-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathVia.cpp
167 lines (164 loc) · 3.37 KB
/
Via.cpp
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
#include "Via.h"
#ifdef _DEBUG
#include <cstdio>
#endif
void Via::write(unsigned int r, unsigned char value)
{
switch (r & 0xF) {
case 0:
prb = value;
break;
case 1:
case 0xF: // same as #1, no handshake
ifr &= ~IRQM_CA1;
pra = value;
break;
case 2:
ddrb = value;
break;
case 3:
ddra = value;
break;
case 4:
case 6:
t1l = (t1l & 0xFF00) | value;
break;
case 5:
// write T1 high order counter, read from low order latch
t1l = (t1l & 0xFF) | (value << 8);
//t1c = t1l;
// trigger a reload
t1r = 1;
// Clear T1 IRQ
ifr &= ~IRQM_T1;
checkIrqCallback(callBackParam, ifr & ier);
t1t = 0;
// PB7 square wave output
// if PB7 is programmed as a T1 output it will go low on the phi2 following the write operation
if (acr & 0xC0) {
pb7 = 0;
pb7trigger = false;
}
break;
case 7:
// write T1 high order latch
t1l = (t1l & 0xFF) | (value << 8);
// despite what official docs state, it does clear the interrupt flag
ifr &= ~IRQM_T1;
checkIrqCallback(callBackParam, ifr & ier);
break;
case 8:
// write T2 low order latch
t2l = (t2l & 0xFF00) | value;
break;
case 9:
// write T2 high order counter, low order latch xfered to low count
t2c = (t2l & 0xFF) | (value << 8);
// trigger reload
t2r = 1;
// Clear T2 IRQ
ifr &= ~IRQM_T2;
checkIrqCallback(callBackParam, ifr & ier);
t2t = 0;
break;
case 0xA:
sr = value;
break;
case 0xB:
/* ACR bits:
7 = PB7 output enable
6 = free-run enable
5 = timer 2 control (0=timed interrupt,1=countdown with pulses)
2,3,4 = shift register control
1 = PB latching enabled
0 = PA latching enabled
*/
acr = value;
break;
case 0xC:
pcr = value;
break;
case 0xD:
ifr &= ~(value | 0x80);
checkIrqCallback(callBackParam, ifr & ier & 0x7F);
break;
case 0xE:
if (value & 0x80)
ier |= value & 0x7F;
else
ier &= ~value;
break;
default:
break;
}
}
unsigned char Via::read(unsigned int r)
{
switch (r & 0xF) {
case 0:
if ((pcr & 0xA0) != 0x20)
ifr &= ~IRQM_CB2;
// Clear CB1 IRQ flag
ifr &= ~IRQM_CB1;
checkIrqCallback(callBackParam, ifr & ier);
return prb | ~ddrb; // & ~(acr & 0x80)) | (pb7 & 0x80 && ddrb);
default:
case 1:
case 0xF:
if ((pcr & 0x0A) != 0x02)
ifr &= ~IRQM_CA2;
// Clear CA1 IRQ flag
ifr &= ~IRQM_CA1;
checkIrqCallback(callBackParam, ifr & ier);
return pra | ~ddra;
case 2:
return ddrb;
case 3:
return ddra;
case 4:
// Clear T1 IRQ flag
ifr &= ~IRQM_T1;
checkIrqCallback(callBackParam, ifr & ier);
return t1c & 0xFF;
case 5:
return t1c >> 8;
case 6:
return t1l & 0xFF;
case 7:
return t1l >> 8;
case 8:
// Clear T2 IRQ flag
ifr &= ~IRQM_T2;
checkIrqCallback(callBackParam, ifr & ier);
return t2c & 0xFF;
case 9:
return t2c >> 8;
case 0xA:
// Shift register IRQ is cleared on read
ifr &= ~IRQM_SR;
checkIrqCallback(callBackParam, ifr & ier);
return sr;
case 0xB:
return acr;
case 0xC:
return pcr;
case 0xD:
// bit #7 will be read as 1 if any IRQ is active
return ifr | ((ifr & ier & 0x7F) ? 0x80 : 0);
case 0xE:
// reading bit #7 gives 1 always
return ier | 0x80;
}
}
void Via::reset()
{
// clears all 6522 internal registers to logic 0
// (except T1 and T2 latches and counters and the shift register)
pra = ddra = prb = ddrb = 0;
ifr = ier = 0;
acr = pcr = 0;
sr = 0; t1c = t2c = t1l = t2l = 0xFFFF;
t1t = t2t = 0;
pb7 = 0x80;
pb7trigger = false;
}