03a3459e Andy McCall 15 days ago
1
2
3
4
5
#include " via.h"
6
#include " i2c.h"
7
#include " memory.h"
8
#include " serial.h"
9
#include < stdio.h>
10
#include < stdlib.h>
11
#include < time.h>
12
#include < string.h>
13
14
#include " glue.h"
15
#include " joystick.h"
16
17
typedef struct {
18
unsigned timer_count[ 2 ] ;
19
unsigned pb6_pulse_counts;
20
uint8_t registers[ 15 ] ;
21
bool timer1_m1;
22
bool timer_running[ 2 ] ;
23
bool pb7_output;
24
} via_t ;
25
26
static via_t via[ 2 ] ;
27
28
29
30
31
static void
32
via_init ( via_t * via )
33
{
34
35
for ( int i = 0 ; i < 4 ; i+ + ) via-> registers[ i] = 0 ;
36
for ( int i = 11 ; i < 15 ; i+ + ) via-> registers[ i] = 0 ;
37
via-> timer_running[ 0 ] = false ;
38
via-> timer_running[ 1 ] = false ;
39
via-> timer1_m1 = false ;
40
via-> pb7_output = true ;
41
}
42
43
static void
44
via_clear_pra_irqs ( via_t * via )
45
{
46
via-> registers[ 13 ] &= ~ 0x02 ;
47
if ( ( via-> registers[ 12 ] & 0b00001010) != 0b00000010) {
48
via-> registers[ 13 ] &= ~ 0x01 ;
49
}
50
}
51
52
static void
53
via_clear_prb_irqs ( via_t * via )
54
{
55
via-> registers[ 13 ] &= ~ 0x10 ;
56
if ( ( via-> registers[ 12 ] & 0b10100000) != 0b00100000) {
57
via-> registers[ 13 ] &= ~ 0x08 ;
58
}
59
}
60
61
static uint8_t
62
via_read ( via_t * via , uint8_t reg , bool debug )
63
{
64
uint8_t ifr;
65
bool irq;
66
switch ( reg) {
67
case 0 :
68
if ( ! debug) via_clear_prb_irqs ( via ) ;
69
return via-> registers[ 0 ] ;
70
case 1 :
71
case 15 :
72
if ( ! debug) via_clear_pra_irqs ( via ) ;
73
return via-> registers[ 1 ] ;
74
case 4 :
75
if ( ! debug) via-> registers[ 13 ] &= ~ 0x40 ;
76
return ( uint8_t ) ( via-> timer_count[ 0 ] & 0xff ) ;
77
case 5 :
78
return ( uint8_t ) ( via-> timer_count[ 0 ] >> 8 ) ;
79
case 8 :
80
if ( ! debug) via-> registers[ 13 ] &= ~ 0x20 ;
81
return ( uint8_t ) ( via-> timer_count[ 1 ] & 0xff ) ;
82
case 9 :
83
return ( uint8_t ) ( via-> timer_count[ 1 ] >> 8 ) ;
84
case 10 :
85
if ( ! debug) via-> registers[ 13 ] &= ~ 0x04 ;
86
return via-> registers[ 10 ] ;
87
case 13 :
88
ifr = via-> registers[ 13 ] ;
89
irq = ( ifr & via-> registers[ 14 ] ) != 0 ;
90
return ( ( uint8_t ) irq << 7 ) | ifr;
91
case 14 :
92
return via-> registers[ 14 ] | 0x80 ;
93
default :
94
return via-> registers[ reg] ;
95
}
96
}
97
98
static void
99
via_write ( via_t * via , uint8_t reg , uint8_t value )
100
{
101
switch ( reg) {
102
case 0 :
103
via_clear_prb_irqs ( via ) ;
104
via-> registers[ 0 ] = value;
105
break ;
106
case 1 :
107
case 15 :
108
via_clear_pra_irqs ( via ) ;
109
via-> registers[ 1 ] = value;
110
break ;
111
case 4 :
112
via-> registers[ 6 ] = value;
113
break ;
114
case 5 :
115
case 7 :
116
via-> registers[ 13 ] &= ~ 0x40 ;
117
via-> registers[ 7 ] = value;
118
if ( reg == 5 ) {
119
via-> timer_count[ 0 ] = ( ( unsigned ) value << 8 ) | via-> registers[ 6 ] ;
120
via-> timer_running[ 0 ] = true ;
121
via-> pb7_output = false ;
122
}
123
break ;
124
case 9 :
125
via-> registers[ 13 ] &= ~ 0x20 ;
126
via-> timer_count[ 1 ] = ( ( unsigned ) value << 8 ) | via-> registers[ 8 ] ;
127
via-> timer_running[ 1 ] = true ;
128
break ;
129
case 10 :
130
via-> registers[ 13 ] &= ~ 0x04 ;
131
via-> registers[ 10 ] = value;
132
break ;
133
case 13 :
134
via-> registers[ 13 ] &= ~ ( value & 0x7f ) ;
135
break ;
136
case 14 :
137
if ( value & 0x80 ) {
138
via-> registers[ 14 ] |= value & 0x7f ;
139
} else {
140
via-> registers[ 14 ] &= ~ value & 0x7f ;
141
}
142
break ;
143
default :
144
via-> registers[ reg] = value;
145
}
146
}
147
148
static void
149
via_step ( via_t * via , unsigned clocks )
150
{
151
152
153
uint8_t acr = via-> registers[ 11 ] ;
154
uint8_t ifr = via-> registers[ 13 ] ;
155
156
unsigned cnt;
157
uint32_t tclk, tclk_s, reload;
158
159
cnt = via-> timer_count[ 0 ] ;
160
tclk = clocks;
161
while ( tclk > 0 ) {
162
if ( via-> timer1_m1) {
163
reload = ( ( ( uint32_t ) via-> registers[ 7 ] << 8 ) | via-> registers[ 6 ] ) ;
164
tclk_s = reload + 1 ;
165
if ( tclk < tclk_s) tclk_s = tclk;
166
cnt = reload - tclk_s + 1 ;
167
via-> timer1_m1 = false ;
168
} else if ( cnt < tclk) {
169
if ( via-> timer_running[ 0 ] ) {
170
ifr |= 0x40 ;
171
via-> pb7_output ^= true ;
172
if ( ! ( acr & 0x40 ) ) via-> timer_running[ 0 ] = false ;
173
}
174
if ( tclk - cnt == 1 ) {
175
176
cnt = 0xffff ;
177
via-> timer1_m1 = true ;
178
tclk_s = 1 ;
179
} else {
180
reload = ( ( ( uint32_t ) via-> registers[ 7 ] << 8 ) | via-> registers[ 6 ] ) ;
181
tclk_s = cnt + reload + 2 ;
182
if ( tclk < tclk_s) tclk_s = tclk;
183
cnt += reload - tclk_s + 2 ;
184
}
185
} else {
186
cnt -= tclk;
187
break ;
188
}
189
tclk -= tclk_s;
190
}
191
via-> timer_count[ 0 ] = ( unsigned ) cnt;
192
193
cnt = via-> timer_count[ 1 ] ;
194
tclk = ( acr & 0x20 ) ? via-> pb6_pulse_counts : clocks;
195
via-> pb6_pulse_counts = 0 ;
196
if ( cnt < tclk) {
197
if ( via-> timer_running[ 1 ] ) {
198
ifr |= 0x20 ;
199
via-> timer_running[ 1 ] = false ;
200
}
201
via-> timer_count[ 1 ] = 0x10000 + cnt - tclk;
202
} else {
203
via-> timer_count[ 1 ] -= tclk;
204
}
205
206
207
208
via-> registers[ 13 ] = ifr;
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
void
236
via1_init ( )
237
{
238
via_init ( & via[ 0 ] ) ;
239
i2c_port. clk_in = 1 ;
240
serial_port. in . atn = 0 ;
241
serial_port. in . clk = 0 ;
242
serial_port. in . data = 0 ;
243
serial_port. out . clk = 1 ;
244
serial_port. out . data = 1 ;
245
}
246
247
uint8_t
248
via1_read ( uint8_t reg , bool debug )
249
{
250
251
252
253
254
switch ( reg) {
255
case 0 :
256
if ( ! debug) via_clear_prb_irqs ( & via[ 0 ] ) ;
257
if ( via[ 0 ] . registers [ 11 ] & 2 ) {
258
259
return 0 ;
260
} else {
261
return
262
( ~ via[ 0 ] . registers [ 2 ] & (
263
( serial_port_read_clk ( ) << 6 ) |
264
( serial_port_read_data ( ) << 7 )
265
) ) |
266
( via[ 0 ] . registers [ 2 ] & (
267
( serial_port. in . atn << 3 ) |
268
( ( ! serial_port. in . clk ) << 4 ) |
269
( ( ! serial_port. in . data ) << 5 )
270
) ) ;
271
}
272
273
case 1 :
274
case 15 :
275
i2c_step ( ) ;
276
if ( ! debug) via_clear_pra_irqs ( & via[ 0 ] ) ;
277
if ( via[ 0 ] . registers [ 11 ] & 1 ) {
278
279
return 0 ;
280
} else {
281
return ( ~ via[ 0 ] . registers [ 3 ] & i2c_port. data_out ) |
282
( via[ 0 ] . registers [ 3 ] & i2c_port. data_in ) |
283
( ~ via[ 0 ] . registers [ 3 ] & I2C_CLK_MASK ) |
284
( via[ 0 ] . registers [ 3 ] & i2c_port. clk_in ) |
285
Joystick_data;
286
}
287
288
default :
289
return via_read ( & via[ 0 ] , reg, debug) ;
290
}
291
}
292
293
void
294
via1_write ( uint8_t reg , uint8_t value )
295
{
296
via_write ( & via[ 0 ] , reg, value) ;
297
if ( reg == 0 || reg == 2 ) {
298
299
const uint8_t pb = via[ 0 ] . registers [ 0 ] | ~ via[ 0 ] . registers [ 2 ] ;
300
serial_port. in . atn = ( pb & SERIAL_ATNIN_MASK) != 0 ;
301
serial_port. in . clk = ( pb & SERIAL_CLOCKIN_MASK) == 0 ;
302
serial_port. in . data = ( pb & SERIAL_DATAIN_MASK) == 0 ;
303
304
} else if ( reg == 1 || reg == 3 ) {
305
i2c_step ( ) ;
306
307
const uint8_t pa = via[ 0 ] . registers [ 1 ] | ~ via[ 0 ] . registers [ 3 ] ;
308
i2c_port. data_in = pa & I2C_DATA_MASK;
309
i2c_port. clk_in = ( pa & I2C_CLK_MASK) >> 1 ;
310
joystick_set_latch ( via[ 0 ] . registers [ 1 ] & JOY_LATCH_MASK ) ;
311
joystick_set_clock ( via[ 0 ] . registers [ 1 ] & JOY_CLK_MASK ) ;
312
}
313
}
314
315
void
316
via1_step ( unsigned clocks )
317
{
318
via_step ( & via[ 0 ] , clocks) ;
319
}
320
321
bool
322
via1_irq ( )
323
{
324
return ( via[ 0 ] . registers [ 13 ] & via[ 0 ] . registers [ 14 ] ) != 0 ;
325
}
326
327
328
329
330
331
332
333
334
void
335
via2_init ( )
336
{
337
via_init ( & via[ 1 ] ) ;
338
}
339
340
uint8_t
341
via2_read ( uint8_t reg , bool debug )
342
{
343
return via_read ( & via[ 1 ] , reg, debug) ;
344
}
345
346
void
347
via2_write ( uint8_t reg , uint8_t value )
348
{
349
via_write ( & via[ 1 ] , reg, value) ;
350
}
351
352
void
353
via2_step ( unsigned clocks )
354
{
355
via_step ( & via[ 1 ] , clocks) ;
356
}
357
358
bool
359
via2_irq ( )
360
{
361
return ( via[ 1 ] . registers [ 13 ] & via[ 1 ] . registers [ 14 ] ) != 0 ;
362
}