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.

C64 ioprocessorsmos-technologycommodoretimers 1981–present

Overview

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 (original) or MOS 8521 (later revision).
  • Chips per C64: two, at $DC00 and $DD00.
  • Features: two 8-bit parallel ports, two 16-bit timers, real-time clock, serial shift register.
  • Interrupts: can generate IRQ (CIA1) or NMI (CIA2).

CIA1 ($DC00-$DC0F) - User input

RegisterAddressPurpose
Port A$DC00Keyboard column / joystick 2
Port B$DC01Keyboard row / joystick 1
DDRA$DC02Data direction for Port A
DDRB$DC03Data direction for Port B
Timer A$DC04-$DC0516-bit countdown timer
Timer B$DC06-$DC0716-bit countdown timer
TOD$DC08-$DC0BTime of day clock
Serial$DC0CSerial shift register
ICR$DC0DInterrupt control register
CRA$DC0EControl register A
CRB$DC0FControl register B

CIA2 ($DD00-$DD0F) - System control

FunctionRegisterBits
VIC bank$DD00bits 0-1 (inverted)
Serial bus$DD00bits 3-7
User port$DD018 lines
NMI source$DD0Dflags and mask

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:

DirectionCIA1 PortBit
Joy 1 Up$DC010
Joy 1 Down$DC011
Joy 1 Left$DC012
Joy 1 Right$DC013
Joy 1 Fire$DC014
Joy 2 Up$DC000
Joy 2 Down$DC001
Joy 2 Left$DC002
Joy 2 Right$DC003
Joy 2 Fire$DC004

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.

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.

VIC-II bank selection

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

$DD00 bits 0-1BankAddress range
110$0000-$3FFF
101$4000-$7FFF
012$8000-$BFFF
003$C000-$FFFF

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

See also