Skip to content
Hardware

CIA: The C64's Swiss Army Chip

Two chips for I/O, timing, and everything else

The MOS 6526 Complex Interface Adapter handled keyboard scanning, joystick input, serial communication, and timing—the unsung heroes of the Commodore 64.

commodore-64ioprocessorsmos-technologycommodoretimers1981–present

The Commodore 64 contains two CIA chips: CIA1 ($DC00-$DC0F) handles the keyboard and joysticks, while CIA2 ($DD00-$DD0F) manages serial bus communication, VIC-II bank selection, and the user port. Together they provide the glue logic that connects the C64 to the outside world.

Fast facts

  • Model: MOS 6526, or 8521 (HMOS-II shrink in late C64C boards). Commodore’s ordering table defines the A suffix as a speed grade — no suffix is the 1 MHz part, A the 2 MHz one — not as a revision.
  • Chips per C64: two, at $DC00 and $DD00.
  • Features: 16 programmable I/O lines across two ports, two linkable 16-bit interval timers, a 24-hour time-of-day clock with alarm, and an 8-bit serial shift register.
  • Interrupts: can generate IRQ (CIA1) or NMI (CIA2).

CIA1 ($DC00-$DC0F) - User input

Register Address Purpose
Port A $DC00 Keyboard column / joystick 2
Port B $DC01 Keyboard row / joystick 1
DDRA $DC02 Data direction for Port A
DDRB $DC03 Data direction for Port B
Timer A $DC04-$DC05 16-bit countdown timer
Timer B $DC06-$DC07 16-bit countdown timer
TOD $DC08-$DC0B Time of day clock
Serial $DC0C Serial shift register
ICR $DC0D Interrupt control register
CRA $DC0E Control register A
CRB $DC0F Control register B

CIA2 ($DD00-$DD0F) - System control

Function Register Bits
VIC bank $DD00 bits 0-1 (inverted)
RS-232 TX $DD00 bit 2
Serial bus out $DD00 bits 3-5 (ATN, CLK, DATA)
Serial bus in $DD00 bits 6-7 (CLK, DATA)
User port $DD01 8 lines
NMI source $DD0D flags and mask

$DD0D is CIA2’s Interrupt Control Register. Reading returns the active flags and clears them; writing updates the mask using the set/clear protocol. Five events can trigger an NMI through CIA2: Timer A underflow (bit 0), Timer B underflow (bit 1), TOD alarm match (bit 2), serial shift register byte completion (bit 3), and the /FLAG input pulse (bit 4) — typically wired to the user port.

Keyboard scanning

The keyboard matrix uses CIA1’s ports:

  1. Write to $DC00 to select a column (pull one bit low).
  2. Read $DC01 to see which rows have keys pressed.
  3. Scan all 8 columns to read the full keyboard.
$DC00 bits: column select (directly affects keyboard matrix lines)
$DC01 bits: row read (directly affected by pressed keys)

Joystick reading

Joysticks share lines with the keyboard:

Direction CIA1 Port Bit
Joy 1 Up $DC01 0
Joy 1 Down $DC01 1
Joy 1 Left $DC01 2
Joy 1 Right $DC01 3
Joy 1 Fire $DC01 4
Joy 2 Up $DC00 0
Joy 2 Down $DC00 1
Joy 2 Left $DC00 2
Joy 2 Right $DC00 3
Joy 2 Fire $DC00 4

Important: bits are active low (0 = pressed, 1 = released).

Timer operations

Each CIA has two 16-bit timers useful for:

  • Music playback: trigger IRQs at precise intervals.
  • Timing loops: measure elapsed time.
  • Raster sync: supplement VIC-II raster interrupts.
  • Serial timing: generate baud rates for communication. In output mode Timer A is the baud rate generator, shifting at half its underflow rate.

A timer can also drive a pin directly. A control bit routes Timer A’s output to PB6 and Timer B’s to PB7, either toggling or emitting a single one-cycle pulse on each underflow. This overrides DDRB and forces that line to an output, whatever the direction register says.

Basic timer setup

  1. Set timer low byte ($DC04) and high byte ($DC05).
  2. Configure control register ($DC0E) for one-shot or continuous.
  3. Enable timer interrupt in ICR ($DC0D).
  4. Timer counts down from loaded value to zero.

Time of day clock

The TOD clock is the one part of the CIA that does not run off the system clock. Commodore’s data sheet requires “an external 60Hz or 50Hz (programmable) TTL level input on the TOD pin for accurate time-keeping” — the C64 feeds it mains frequency. It counts in BCD across four registers (tenths, seconds, minutes, hours) with the AM/PM flag in the top bit of the hours register, so a single bit test tells you which half of the day it is.

The alarm shares those same four addresses; CRB bit 7 selects whether a write sets the clock or the alarm. A match raises one of the CIA’s five interrupt sources.

Because it is tied to the mains rather than to a crystal, a C64’s TOD keeps time only as well as the supply frequency does — and stops keeping it at all on a machine running from an inverter or a bench supply at the wrong frequency.

Handshaking

Ports A and B are not just pin banks. /PC goes low for one cycle after any read or write of Port B, signalling “data ready” or “data accepted”, and /FLAG is a negative-edge-sensitive input designed to receive another CIA’s /PC. On the C64, /FLAG on CIA2 is wired to the user port, which is why it appears in the NMI list above.

VIC-II bank selection

CIA2’s Port A bits 0-1 select which 16KB bank the VIC-II sees:

$DD00 bits 0-1 Bank Address range
11 0 $0000-$3FFF
10 1 $4000-$7FFF
01 2 $8000-$BFFF
00 3 $C000-$FFFF

Note: bits are inverted—lower values select higher addresses.

See also

Not yet fact-checked. This entry was drafted by an AI and nobody has verified it. The dates, figures and technical details may be wrong. Use it to find your bearings, then confirm anything that matters against a primary source.