CIA (Complex Interface Adapter) Registers¶
The Amiga carries two MOS 8520 Complex Interface Adapter (CIA) chips — CIAA and CIAB — that handle I/O glue logic:
- CIAA ($BFE001) — primary I/O: gameports, floppy status, LED, memory overlay
- CIAB ($BFD000) — disk stepper control, serial port, parallel (printer) port, TOD clock
CIAA is accessed on odd byte addresses (low byte of the 16-bit chip bus); CIAB on even byte addresses (high byte). Each CIA exposes 16 byte-wide registers covering I/O ports, timers, time-of-day clock, serial port, and interrupt control.
Register map¶
Offsets are relative to the CIA base. CIAA is at $BFE001 (use odd offsets: $0001, $0101, etc.); CIAB is at $BFD000 (use even offsets: $0000, $0100, etc.).
| Offset | Name | Access | Description |
|---|---|---|---|
$00xx |
ciapra |
RW | Peripheral port A (CIAA: gameports, floppy status, LED, overlay / CIAB: serial, printer) |
$01xx |
ciaprb |
RW | Peripheral port B (CIAA: parallel port / CIAB: disk stepper control) |
$02xx |
ciaddra |
RW | Data direction register for port A (1 = output, 0 = input) |
$03xx |
ciaddrb |
RW | Data direction register for port B |
$04xx |
ciatalo |
RW | Timer A low byte |
$05xx |
ciatahi |
RW | Timer A high byte |
$06xx |
ciatblo |
RW | Timer B low byte |
$07xx |
ciatbhi |
RW | Timer B high byte |
$08xx |
ciatodlow |
RW | Time-of-day clock low byte (1/10 sec) |
$09xx |
ciatodmid |
RW | Time-of-day clock middle byte (seconds) |
$0Axx |
ciatodhi |
RW | Time-of-day clock high byte (minutes + hours) |
$0Cxx |
ciasdr |
RW | Serial data register |
$0Dxx |
ciaicr |
RW | Interrupt control register |
$0Exx |
ciacra |
RW | Control register A (timer A mode + serial) |
$0Fxx |
ciacrb |
RW | Control register B (timer B mode + alarm) |
Absolute addresses¶
CIAA ($BFE001 base, odd offsets)¶
| Address | Name |
|---|---|
$BFE001 |
ciapra |
$BFE101 |
ciaprb |
$BFE201 |
ciaddra |
$BFE301 |
ciaddrb |
$BFE401 |
ciatalo |
$BFE501 |
ciatahi |
$BFE601 |
ciatblo |
$BFE701 |
ciatbhi |
$BFE801 |
ciatodlow |
$BFE901 |
ciatodmid |
$BFEA01 |
ciatodhi |
$BFEC01 |
ciasdr |
$BFED01 |
ciaicr |
$BFEE01 |
ciacra |
$BFEF01 |
ciacrb |
CIAB ($BFD000 base, even offsets)¶
| Address | Name |
|---|---|
$BFD000 |
ciapra |
$BFD100 |
ciaprb |
$BFD200 |
ciaddra |
$BFD300 |
ciaddrb |
$BFD400 |
ciatalo |
$BFD500 |
ciatahi |
$BFD600 |
ciatblo |
$BFD700 |
ciatbhi |
$BFD800 |
ciatodlow |
$BFD900 |
ciatodmid |
$BFDA00 |
ciatodhi |
$BFDC00 |
ciasdr |
$BFDD00 |
ciaicr |
$BFDE00 |
ciacra |
$BFDF00 |
ciacrb |
Interrupt control register (ciaicr)¶
| Bit | Bit name | Flag | Meaning |
|---|---|---|---|
| 0 | CIAICRB_TA |
CIAICRF_TA |
Timer A underflow interrupt |
| 1 | CIAICRB_TB |
CIAICRF_TB |
Timer B underflow interrupt |
| 2 | CIAICRB_ALRM |
CIAICRF_ALRM |
TOD alarm interrupt |
| 3 | CIAICRB_SP |
CIAICRF_SP |
Serial port byte received / transmit buffer empty |
| 4 | CIAICRB_FLG |
CIAICRF_FLG |
FLAG pin (PA2) negative edge |
| 7 | CIAICRB_IR / CIAICRB_SETCLR |
CIAICRF_IR / CIAICRF_SETCLR |
Interrupt request / set-vs-clear selector |
Bit 7 has dual meaning: when read, bit 7 is the actual interrupt request (1 = any enabled interrupt is pending). When written, bit 7 selects set-vs-clear mode: write 1 to set bits, 0 to clear bits (lower 4 bits).
The masked interrupt from each CIA is fed into bit 6 of the custom-chip INTREQ register (INTF_INT6 for CIAA, INTF_INT7 for CIAB).
Control register A (ciacra)¶
Drives Timer A and the serial port.
| Bit | Bit name | Flag | Meaning |
|---|---|---|---|
| 0 | CIACRAB_START |
CIACRAF_START |
Start/stop Timer A |
| 1 | CIACRAB_PBON |
CIACRAF_PBON |
Timer A PBON output mode |
| 2 | CIACRAB_OUTMODE |
CIACRAF_OUTMODE |
Timer A output mode (toggle / pulse) |
| 3 | CIACRAB_RUNMODE |
CIACRAF_RUNMODE |
Timer A run mode (continuous / one-shot) |
| 4 | CIACRAB_LOAD |
CIACRAF_LOAD |
Force-load Timer A from latch |
| 5 | CIACRAB_INMODE |
CIACRAF_INMODE |
Timer A input mode (0 = count Phi2, 1 = count CNT pulses) |
| 6 | CIACRAB_SPMODE |
CIACRAF_SPMODE |
Serial port mode (0 = output, 1 = input) |
| 7 | CIACRAB_TODIN |
CIACRAF_TODIN |
50/60 Hz TOD input select (0 = 60 Hz NTSC, 1 = 50 Hz PAL) |
Control register B (ciacrb)¶
Drives Timer B and the alarm register.
| Bit | Bit name | Flag | Meaning |
|---|---|---|---|
| 0 | CIACRBB_START |
CIACRBF_START |
Start/stop Timer B |
| 1 | CIACRBB_PBON |
CIACRBF_PBON |
Timer B PBON output mode |
| 2 | CIACRBB_OUTMODE |
CIACRBF_OUTMODE |
Timer B output mode (toggle / pulse) |
| 3 | CIACRBB_RUNMODE |
CIACRBF_RUNMODE |
Timer B run mode |
| 4 | CIACRBB_LOAD |
CIACRBF_LOAD |
Force-load Timer B from latch |
| 5 | CIACRBB_INMODE0 |
CIACRBF_INMODE0 |
Timer B input mode (low bit) |
| 6 | CIACRBB_INMODE1 |
CIACRBF_INMODE1 |
Timer B input mode (high bit) |
| 7 | CIACRBB_ALARM |
CIACRBF_ALARM |
0 = write TOD registers, 1 = write ALARM registers |
Timer B input mode (2-bit selector)¶
| INMODE1 | INMODE0 | Mode | Flag |
|---|---|---|---|
| 0 | 0 | Count Phi2 clock | CIACRBF_IN_PHI2 |
| 0 | 1 | Count CNT pulses | CIACRBF_IN_CNT |
| 1 | 0 | Count Timer A underflows | CIACRBF_IN_TA |
| 1 | 1 | Count CNT pulses + Timer A underflows | CIACRBF_IN_CNT_TA |
CIAA port A pins ($BFE001)¶
Peripherals tied to each bit of ciapra on CIAA:
| Bit | Bit name | Flag | Peripheral |
|---|---|---|---|
| 0 | CIA_OVERLAY |
CIAF_OVERLAY |
Memory overlay (1 = overlay RAM, 0 = Kickstart ROM) |
| 1 | CIA_LED |
CIAF_LED |
Power LED (0 = bright, 1 = dim) |
| 2 | CIA_DSKCHANGE |
CIAF_DSKCHANGE |
Disk change* (active low) |
| 3 | CIA_DSKPROT |
CIAF_DSKPROT |
Disk write-protect* (active low) |
| 4 | CIA_DSKTRACK0 |
CIAF_DSKTRACK0 |
Disk on track 00* (active low) |
| 5 | CIA_DSKRDY |
CIAF_DSKRDY |
Disk ready* (active low) |
| 6 | CIA_GAMEPORT0 |
CIAF_GAMEPORT0 |
Gameport 0 fire button (active low) |
| 7 | CIA_GAMEPORT1 |
CIAF_GAMEPORT1 |
Gameport 1 fire button (active low) |
(* = active-low signal — the input reads 0 when the condition is true.)
CIAB port A pins ($BFD000)¶
Serial port and parallel (printer) port handshaking:
| Bit | Bit name | Flag | Peripheral |
|---|---|---|---|
| 0 | CIA_PRTRBUSY |
CIAF_PRTRBUSY |
Printer busy |
| 1 | CIA_PRTRPOUT |
CIAF_PRTRPOUT |
Printer paper out |
| 2 | CIA_PRTRSEL |
CIAF_PRTRSEL |
Printer SELECT |
| 3 | CIA_COMDSR |
CIAF_COMDSR |
Serial Data Set Ready |
| 4 | CIA_COMCTS |
CIAF_COMCTS |
Serial Clear to Send |
| 5 | CIA_COMCD |
CIAF_COMCD |
Serial Carrier Detect |
| 6 | CIA_COMRTS |
CIAF_COMRTS |
Serial Request to Send* (output) |
| 7 | CIA_COMDTR |
CIAF_COMDTR |
Serial Data Terminal Ready* (output) |
CIAB port B pins ($BFD100)¶
Floppy disk stepper control:
| Bit | Bit name | Flag | Peripheral |
|---|---|---|---|
| 0 | CIA_DSKSTEP |
CIAF_DSKSTEP |
Disk step pulse* |
| 1 | CIA_DSKDIREC |
CIAF_DSKDIREC |
Disk seek direction (1 = inward) |
| 2 | CIA_DSKSIDE |
CIAF_DSKSIDE |
Disk side select* |
| 3 | CIA_DSKSEL0 |
CIAF_DSKSEL0 |
Disk select unit 0* |
| 4 | CIA_DSKSEL1 |
CIAF_DSKSEL1 |
Disk select unit 1* |
| 5 | CIA_DSKSEL2 |
CIAF_DSKSEL2 |
Disk select unit 2* |
| 6 | CIA_DSKSEL3 |
CIAF_DSKSEL3 |
Disk select unit 3* |
| 7 | CIA_DSKMOTOR |
CIAF_DSKMOTOR |
Disk motor* (active low) |
CIAA port B pins ($BFE101)¶
Parallel (printer) bidirectional data port — bits not individually named in hardware headers; used directly for Centronics handshake and 8-bit data.
Time-of-day clock (ciatod)¶
The TOD clock is a BCD 24-hour clock incremented every 1/10 second (or by external 50/60 Hz line frequency when CIACRAB_TODIN selects PAL/NTSC mode).
| Register | Range | BCD format |
|---|---|---|
ciatodlow |
0–9 | 1/10 seconds (bit 7 = 0) |
ciatodmid |
0–59 | seconds |
ciatodhi |
0–23 + AM/PM bit | hours + AM/PM flag (bit 7) |
When the TOD equals the ALARM registers, the CIA raises CIAICRF_ALRM (turning it into an interrupt if enabled).
Cross-references¶
../register-reference.md— master register index../../library-reference/timer-library.md,../../library-reference/input-library.md,../../library-reference/gameport-library.md,../../library-reference/serial-library.md,../../library-reference/parallel-library.md,../../library-reference/printer-library.md— device drivers that drive the CIA timers and ports