Both CIA chips use the same register layout. CIA #1 = $DC00, CIA #2 = $DD00.
| Offset | CIA#1 Addr | CIA#2 Addr | Name | Description |
|---|---|---|---|---|
| +0 | $DC00 | $DD00 | PRA | Port A data register |
| +1 | $DC01 | $DD01 | PRB | Port B data register |
| +2 | $DC02 | $DD02 | DDRA | Port A direction (1=output) |
| +3 | $DC03 | $DD03 | DDRB | Port B direction (1=output) |
| +4 | $DC04 | $DD04 | TIMALO | Timer A low byte (latch/counter) |
| +5 | $DC05 | $DD05 | TIMAHI | Timer A high byte |
| +6 | $DC06 | $DD06 | TIMBLO | Timer B low byte |
| +7 | $DC07 | $DD07 | TIMBHI | Timer B high byte |
| +8 | $DC08 | $DD08 | TODTEN | TOD tenths of seconds (BCD) |
| +9 | $DC09 | $DD09 | TODSEC | TOD seconds (BCD) |
| +A | $DC0A | $DD0A | TODMIN | TOD minutes (BCD) |
| +B | $DC0B | $DD0B | TODHR | TOD hours + AM/PM (bit 7) |
| +C | $DC0C | $DD0C | SDR | Serial data register |
| +D | $DC0D | $DD0D | ICR | Interrupt control register |
| +E | $DC0E | $DD0E | CRA | Control register A |
| +F | $DC0F | $DD0F | CRB | Control register B |
The keyboard is a 8×8 matrix. To read a key:
| Bit set in $DC00 column | Keys in that column |
|---|---|
| $FE (col 0) | DEL, RETURN, ←→, F7, F1, F3, F5, ↑↓ |
| $FD (col 1) | 3, W, A, 4, Z, S, E, Left Shift |
| $FB (col 2) | 5, R, D, 6, C, F, T, X |
| $F7 (col 3) | 7, Y, G, 8, B, H, U, V |
| $EF (col 4) | 9, I, J, 0, M, K, O, N |
| $DF (col 5) | +, P, L, -, ., :, @, , |
| $BF (col 6) | £, *, ;, Home, Right Shift, =, ↑, / |
| $7F (col 7) | 1, ←, CTRL, 2, Space, C=, Q, Stop |
Bit 0: Up (0=pressed)
Bit 1: Down (0=pressed)
Bit 2: Left (0=pressed)
Bit 3: Right (0=pressed)
Bit 4: Fire (0=pressed)
J = PEEK(56321) ' Read joystick 1 ($DC01)
IF (J AND 16) = 0 THEN PRINT "FIRE!"
IF (J AND 1) = 0 THEN PRINT "UP!"
Bit 7: Serial bus data line (input)
Bit 6: Serial bus clock line (input)
Bit 5: Serial bus data line (output)
Bit 4: Serial bus attention ACK (output)
Bit 3: Serial bus clock (output)
Bit 2: RS-232 data output (User Port)
Bit 1: VIC-II bank select bit 1 \ Together: 00=bank3, 01=bank2
Bit 0: VIC-II bank select bit 0 / 10=bank1, 11=bank0(default)
' Switch VIC-II to Bank 1 ($4000-$7FFF)
POKE 56576, (PEEK(56576) AND 252) OR 2
' Bank 0 (default): POKE 56576, (PEEK(56576) AND 252) OR 3
Bit 7: TODIN — TOD clock: 1=60Hz, 0=50Hz
Bit 6: SPMODE — Serial port: 1=output, 0=input
Bit 5: INMODE — Timer A input: 1=CNT pulses, 0=system clock
Bit 4: LOAD — Force load timer (write 1 to reload latch into counter)
Bit 3: RUNMODE — 0=continuous, 1=one-shot
Bit 2: OUTMODE — Timer A output to PB6: 1=pulse, 0=toggle
Bit 1: PBON — Port B output enable (1=Timer A appears on PB6)
Bit 0: START — 1=start timer, 0=stop timer
Bit 7: ALARM — 1=write TOD alarm, 0=write TOD clock
Bit 6: INMODE (high bit) — with bit 5: timer B source
Bit 5: INMODE (low bit) — 00=φ2 clock, 01=CNT, 10=Timer A, 11=TimA/CNT
Bit 4: LOAD — Force load
Bit 3: RUNMODE — 0=continuous, 1=one-shot
Bit 2: OUTMODE — Timer B output to PB7
Bit 1: PBON — Port B output enable
Bit 0: START — 1=start, 0=stop
Reading: Returns interrupt flags (1=occurred), clears all flags on read Writing: Sets/clears interrupt enables
Bit 7: (read) IRQ occurred (any source) / (write) 1=enable, 0=disable bits 0-4
Bit 4: FLG — FLAG pin interrupt
Bit 3: SP — Serial port interrupt
Bit 2: ALRM — TOD alarm interrupt
Bit 1: TB — Timer B interrupt
Bit 0: TA — Timer A interrupt
Timer counts down from latch value to 0, then triggers interrupt and reloads.
Timer Period = (latch value + 1) / clock_frequency
NTSC: clock = 1,022,727 Hz
PAL: clock = 985,248 Hz
For 1/60 second at NTSC:
latch = 1,022,727 / 60 - 1 = 17,044 = $4294
For 1/50 second at PAL:
latch = 985,248 / 50 - 1 = 19,704 = $4CB8
; Set CIA #1 Timer A for ~1/60 second, continuous IRQ
LDA #$94 ; $4294 low byte
STA $DC04
LDA #$42 ; high byte
STA $DC05
LDA #$81 ; enable Timer A IRQ
STA $DC0D
LDA #$11 ; start timer, continuous, system clock
STA $DC0E
Powered by TurnKey Linux.