$DFF000

Chipset Architecture

The Amiga's power came from its custom chipset — three specialized chips that handled graphics, sound, and DMA independently of the CPU. While the Motorola 68000 ran your code, the custom chips ran the machine.

COMMODORE
AMIGA A500
REV 6A · 1987
68000 CPU
AGNUS 8375
GARY 5719
DENISE 8362
PAULA 8364
CIA-A $BFE001
CIA-B $BFD000
ROM KS 1.3
CHIP
RAM
KEYBOARD
PWR
FDD
JOY 0
JOY 1
SER
PAR
VIDEO
AUD
EXPANSION / TRAPDOOR
Hover a component to inspect

Agnus (later Fat Agnus, then Alice) was the brain of the custom chipset. It controlled DMA — managing memory access for all the other chips so they could read data without bothering the CPU. It contained the Copper (a programmable co-processor that modified hardware registers in sync with the video beam) and the Blitter (a hardware block-transfer engine for fast memory copies, line drawing, and fill operations).

Denise (later Lisa in the AGA chipset) handled all video output: bitplane graphics, hardware sprites, collision detection, and the color palette. The Amiga used a planar graphics model — instead of storing pixels as packed values, each bit of a pixel's color came from a separate bitplane. This made scrolling and certain effects extremely efficient.

Paula handled four independent 8-bit audio channels with hardware volume and period control, disk drive access, serial I/O, and interrupt management. MOD music worked by having Paula's DMA channels continuously read waveform samples from chip RAM while the CPU did other work — the music literally played itself.

CIA 8520 (×2) — Complex Interface Adapters. CIA-A at $BFE001 handled the keyboard, game port fire buttons, the power LED, and the audio low-pass filter. CIA-B at $BFD000 handled the parallel port, serial control lines, and disk drive signals. Each CIA contained two 16-bit timers and a 24-bit time-of-day counter.

$000000

Memory Map

The 68000's 24-bit address bus gave 16 MB of address space. Every piece of hardware had its place. Writing to a memory address could store data, draw graphics, play a sound, or toggle the power LED — depending on where in the map you were writing.

$000000
Chip RAM
up to 2 MB
shared between CPU and custom chips; graphics, audio, disk data live here
$200000
Fast RAM / Zorro II
up to 8 MB
CPU-only, no DMA contention
$A00000
Reserved
$BFD000
CIA-B registers
parallel, disk, serial control
$BFE001
CIA-A registers ★
keyboard, LED, filter, game ports
$C00000
Slow RAM
512 KB (A500 trapdoor)
shares bus but no DMA access
$D00000
Reserved / Expansion
$DFF000
Custom Chip Registers
~256 registers
Agnus, Denise, Paula — bitplanes, sprites, colors, DMA
$E80000
Autoconfig / Zorro II ID
$F80000
Kickstart ROM
256–512 KB
exec.library, intuition, graphics — the entire Amiga OS kernel

At power-on, the overlay bit in CIA-A maps the ROM at address $000000 so the CPU can read its reset vectors. One of the first things Kickstart does is clear that bit, swapping chip RAM into $000000 and moving the ROM back to $F80000. The jump-table architecture of exec.library meant you could call OS functions at fixed negative offsets from the library base — a mechanism I spent many evenings exploring.

$BFE001

CIA-A Registers

The register this site is named after. CIA-A sits at odd addresses starting from $BFE001 (the two CIAs use odd/even address decoding to share the same region without conflicts).

Bit Dir Name $BFE001 — PRA — Port Register A
7 IN /FIR1 Game port 1 fire button (active low)
6 IN /FIR0 Game port 0 fire button (active low)
5 IN /RDY Disk ready (active low)
4 IN /TK0 Disk track zero (active low)
3 IN /WPRO Disk write protect (active low)
2 IN /CHNG Disk change (active low)
1 OUT LED Power LED / audio low-pass filter
0 OUT OVL Overlay — 1: ROM at $000000, 0: RAM

Bit 1 is the star. Setting it low turns on the power LED and engages the audio low-pass filter. On the Amiga 500, it was a hard on/off. On the Amiga 2000 and later, the LED dimmed instead — and the filter smoothly attenuated frequencies above ~3.3 kHz. Games toggled it to simulate effects like driving through a tunnel: the muffled audio came from the hardware filter, not from software processing.

The instruction MOVE.b #$02,$BFE001 sets bit 1 and clears everything else — turning the LED off and disabling the filter. To toggle just the LED without affecting other bits, you'd read the register, XOR bit 1, and write it back: BCHG #1,$BFE001.

Other CIA-A Registers
$BFE101 PRB — Port B: parallel port data (active but directly bits)
$BFE201 DDRA — Data Direction Register A (1 = output, 0 = input)
$BFE301 DDRB — Data Direction Register B
$BFE401 TALO — Timer A low byte
$BFE501 TAHI — Timer A high byte
$BFE601 TBLO — Timer B low byte
$BFE701 TBHI — Timer B high byte
$BFE801 Event counter (TOD) — low byte (1/10 seconds)
$BFE901 Event counter (TOD) — mid byte (seconds)
$BFEA01 Event counter (TOD) — high byte (minutes)
$BFED01 ICR — Interrupt Control Register
$BFEE01 CRA — Control Register A (timer A mode, serial port)
$BFEF01 CRB — Control Register B (timer B mode, TOD alarm)

The keyboard was read through CIA-A's serial port mechanism. Each keypress generated an 8-bit scan code sent serially via the KDAT line, clocked by KCLK. The CIA shifted in the bits and triggered an interrupt when a full byte was received. The Amiga keyboard had its own microcontroller running a handshake protocol — the host had to acknowledge each keycode before the next one could be sent.

$BFD000

CIA-B Registers

CIA-B sits at even addresses starting from $BFD000. Where CIA-A faced the user (keyboard, LED, joystick buttons), CIA-B faced the peripherals — parallel port, floppy drive control, and serial handshaking.

Bit Dir Name $BFD000 — PRA — Port Register A
7 IN /DTR Serial DTR (active low)
6 IN /RTS Serial RTS (active low)
5 IN /CD Serial carrier detect (active low)
4 IN /CTS Serial clear to send (active low)
3 IN /DSR Serial data set ready (active low)
2 OUT /SEL External floppy drive select (active low)
1 OUT /SIDE Disk side select (0 = upper, 1 = lower)
0 OUT /STEP Disk step pulse (active low)

CIA-B's Port B ($BFD100) carried the parallel port's 8 data lines — directly mapped, bit for bit. The data direction register at $BFD300 controlled whether each line was input or output, making the port fully bidirectional.

Other CIA-B Registers
$BFD100 PRB — Port B: parallel port data (8 bidirectional data lines, directly mapped)
$BFD200 DDRA — Data Direction Register A
$BFD300 DDRB — Data Direction Register B
$BFD400 TALO — Timer A low byte
$BFD500 TAHI — Timer A high byte
$BFD600 TBLO — Timer B low byte
$BFD700 TBHI — Timer B high byte
$BFD800 Event counter (TOD) — low byte
$BFD900 Event counter (TOD) — mid byte
$BFDA00 Event counter (TOD) — high byte
$BFDD00 ICR — Interrupt Control Register
$BFDE00 CRA — Control Register A
$BFDF00 CRB — Control Register B

The two CIAs shared the address range $A00000$BFFFFF through an elegant trick: CIA-A responded only to odd addresses (byte-aligned on the 68000's lower data byte), CIA-B only to even ones. Gary, the address decoder, used address line A12 to select between them and directly drove their chip selects. This meant you could never accidentally talk to both at once.

Each CIA's two 16-bit timers could run in one-shot or continuous mode, count system clock pulses or external events, and trigger interrupts on underflow. The 24-bit time-of-day counter was clocked by the mains frequency (50 Hz PAL, 60 Hz NTSC) — giving real wall-clock timing without burning a timer.

$DFF096

DMA System

The Amiga's DMA system was the key to its performance. While the 68000 could only do one thing at a time, the custom chips could independently read and write chip RAM through 25 DMA channels — all orchestrated by Agnus without CPU intervention.

Every scan line was divided into 227.5 color clocks (PAL). Each color clock contained two bus cycles — an even cycle and an odd cycle. Agnus allocated these cycles to different DMA channels in a fixed priority order. The CPU got whatever cycles were left over.

DMA Channels
Disk 3 cycles per scan line — reads/writes floppy data
Audio 4 channels, 1 cycle each when active — fetches waveform samples
Bitplane Up to 6 channels (1 per bitplane) — fetches display data
Sprite 8 channels, 2 cycles each during sprite lines — fetches sprite image data
Copper 1 cycle per instruction word — fetches Copper program instructions
Blitter Up to 4 channels (A, B, C, D) — bulk memory operations

The priority order (highest first) was: disk, audio, sprites, bitplanes, Copper, Blitter, CPU. In practice, the CPU typically had about 40–60% of bus cycles available in a normal low-res display. A 6-bitplane hi-res display consumed so many cycles that the CPU was effectively starved.

Bit R/W Name DMACON $096 (W) / DMACONR $002 (R) — DMA Control
15 W SET/CLR 1 = set listed bits, 0 = clear listed bits
14 R BBUSY Blitter busy (read-only)
13 R BZERO Blitter zero — all output bits were 0 (read-only)
10 RW BLTPRI Blitter priority over CPU (blitter nasty)
9 RW DMAEN Master DMA enable — all DMA off if clear
8 RW BPLEN Bitplane DMA enable
7 RW COPEN Copper DMA enable
6 RW BLTEN Blitter DMA enable
5 RW SPREN Sprite DMA enable
4 RW DSKEN Disk DMA enable
3 RW AUD3EN Audio channel 3 DMA enable
2 RW AUD2EN Audio channel 2 DMA enable
1 RW AUD1EN Audio channel 1 DMA enable
0 RW AUD0EN Audio channel 0 DMA enable

DMACON used the SET/CLR convention found throughout the custom chip registers: writing with bit 15 set turned on the specified bits; writing with bit 15 clear turned them off. This avoided the read-modify-write race conditions that would occur if you had to read the register first. For example, MOVE.w #$8380,$DFF096 enabled master DMA, bitplane DMA, and Copper DMA without affecting anything else.

$DFF09A

Interrupts

The Amiga had 14 interrupt sources mapped across 7 priority levels of the 68000. Paula managed the interrupt request and enable registers, combining all sources into the CPU's IPL lines.

Bit Level Name INTREQ $09C (W) / INTREQR $01E (R) — Interrupt Request
15 SET/CLR 1 = set listed bits, 0 = clear listed bits
14 6 INTEN Master interrupt enable (must be set for any interrupt)
13 6 EXTER CIA-B interrupt (active low from /INT on CIA-B)
12 5 DSKSYN Disk sync word matched (DSKSYNC register)
11 5 RBF Serial port receive buffer full
10 4 AUD3 Audio channel 3 block finished
9 4 AUD2 Audio channel 2 block finished
8 4 AUD1 Audio channel 1 block finished
7 4 AUD0 Audio channel 0 block finished
6 3 BLIT Blitter finished
5 3 VERTB Vertical blank (start of frame)
4 3 COPER Copper (triggered by Copper program)
3 2 PORTS CIA-A interrupt (keyboard, TOD, timers)
2 1 SOFT Software interrupt (set by CPU)
1 1 DSKBLK Disk block finished (DMA transfer complete)
0 1 TBE Serial port transmit buffer empty

INTENA ($09A write, $01C read) had the same layout. Both the request and the enable bit had to be set, plus the master enable (bit 14), for an interrupt to actually reach the CPU. Interrupt handlers had to clear the request bit in INTREQ before returning, or the interrupt would re-trigger immediately.

Level 3 (INT3) was the workhorse — vertical blank ran every frame at 50 Hz (PAL) or 60 Hz (NTSC), making it the standard heartbeat for game logic, music playback, and OS scheduling. The Copper interrupt let programs trigger code at specific screen positions, which was essential for split-screen effects.

$DFF080

Copper

The Copper was a simple but extraordinarily powerful coprocessor built into Agnus. It had only three instructions — MOVE, WAIT, and SKIP — and could only write to custom chip registers. But because it executed in sync with the video beam, it could change hardware state at any point on screen.

Copper Instructions (32 bits each)
MOVE Write a value to a custom chip register. First word: register address (low 9 bits, bit 0 always 0). Second word: data value.
WAIT Halt until the beam reaches a given position. First word: VP[7:0] HP[7:1] 1. Second word: VPM[7:0] HPM[7:1] 0. Mask bits define comparison precision.
SKIP Skip the next instruction if the beam has passed a position. Same format as WAIT but second word bit 0 = 1.

The Copper list was a program stored in chip RAM. On every frame, the Copper restarted from the address in COP1LC ($080/$082). Writing to COPJMP1 ($088) forced an immediate restart. COP2LC/COPJMP2 provided a second entry point — typically used by the vertical blank interrupt to switch lists between frames.

A typical Copper list set up the display: load bitplane pointers, set colors, configure scroll registers. But the real magic was mid-screen changes. By waiting for specific beam positions and then writing new values, the Copper could create effects impossible with static register settings — gradient skies, split-screen resolutions, per-scanline color cycling, and even raster bars that cost zero CPU time.

The WAIT $FFDFFFFE instruction was the conventional end-of-list marker. It waited for beam position V=255 H=223, which in PAL exceeded the visible area. The Copper would stall there until the next vertical blank restarted it.

For Copper to write to registers above $07F (the color and sprite registers), bit 1 of COPCON ($02E) — the "Copper danger" bit — had to be set. This prevented the Copper from accidentally modifying sensitive registers like DMACON or disk pointers.

$DFF100

Playfields

The Amiga used a planar graphics model. Instead of storing each pixel as a packed color value, the image was split across up to 6 bitplanes — each bitplane held one bit of every pixel's color index. This made scrolling and certain blitter operations extremely efficient at the cost of more complex pixel manipulation.

Display Modes (BPLCON0 $100)
Low-res 320×256 (PAL) / 320×200 (NTSC), up to 6 bitplanes = 64 colors (HAM) or 32 colors
High-res 640×256 / 640×200, up to 4 bitplanes = 16 colors (HIRES bit 15 = 1)
HAM Hold-and-Modify — 6 bitplanes, top 2 bits select hold/modify-R/modify-G/modify-B, bottom 4 bits = value. 4096 colors on screen.
EHB Extra Half-Brite — 6 bitplanes, plane 6 selects half-brightness version of the 32-color palette. 64 colors.
Dual PF Dual Playfield — two independent 3-bitplane layers (odd planes = PF1, even planes = PF2). 8+8 colors with transparency.
Interlace Doubles vertical resolution (512 lines PAL) by alternating fields. LACE bit 2 in BPLCON0.

The display window defined the visible area. DIWSTRT ($08E) set the start position and DIWSTOP ($090) set the stop position, both in beam coordinates. Standard PAL values were $2C81 (start) and $2CC1 (stop) for a 320×256 display.

Data fetch timing was separate from the display window. DDFSTRT ($092) and DDFSTOP ($094) controlled when Agnus started and stopped reading bitplane data from RAM. For standard low-res: DDFSTRT = $0038, DDFSTOP = $00D0. For high-res: DDFSTRT = $003C, DDFSTOP = $00D4.

Each bitplane had a pointer pair (BPL1PTH/L at $0E0/$0E2 through BPL6PTH/L at $0EC/$0EE) pointing to its data in chip RAM. After each scan line, a modulo value was added to the pointer — BPL1MOD ($108) for odd bitplanes, BPL2MOD ($10A) for even. Setting the modulo to the display width allowed the bitplanes to wrap naturally; larger values enabled smooth vertical scrolling by skipping lines.

Horizontal scrolling was achieved through BPLCON1 ($102), which held independent 4-bit delay values for playfield 1 and playfield 2. Combined with adjusting the data fetch start and bitplane pointers, this gave pixel-precise smooth scrolling at no CPU cost — the hardware did it all.

Color Palette — COLOR00–COLOR31 ($180–$1BE)
Format 12-bit RGB: ---- RRRR GGGG BBBB. Each component 0–15. Example: $0F00 = bright red, $0FFF = white.
COLOR00 Background color — displayed in border and behind all playfields/sprites
Sprite colors Sprites 0–1 use COLOR17–19, Sprites 2–3 use COLOR21–23, Sprites 4–5 use COLOR25–27, Sprites 6–7 use COLOR29–31
$DFF120

Sprites

The Amiga had 8 hardware sprites, each 16 pixels wide and any height, with 3 colors plus transparency. They were completely independent of the playfield — rendered by Denise on top of (or behind) the bitplane display, with zero CPU overhead once the DMA was set up.

Each sprite had a pointer pair (SPR0PTH/L at $120/$122 through SPR7PTH/L at $13E/$13F) pointing to sprite data in chip RAM. The data format was simple:

Sprite Data Format (in chip RAM)
Word 0 SPRxPOS — vertical start (V7–V0 in high byte), horizontal start (H8–H1 in low byte)
Word 1 SPRxCTL — vertical stop (V7–V0 in high byte), control bits (attach, V8, H0) in low byte
Words 2+3 First image line: DATA word (plane 0) + DATB word (plane 1). 16 pixels, 2 bits per pixel.
... Repeat DATA/DATB pairs for each additional line
Last pair Two zero words ($0000 $0000) mark the end of sprite data

Sprites could be attached in pairs (0+1, 2+3, 4+5, 6+7). When attached, the two sprites combined their bitplanes into a single 4-bitplane sprite with 15 colors plus transparent — at the cost of reducing 8 independent sprites to 4.

Sprite priority relative to the playfield was controlled by BPLCON2 ($104). Each sprite pair could be placed in front of, between, or behind the two playfields. The mouse pointer was traditionally sprite 0.

$DFF040

Blitter

The Blitter was a hardware block-transfer engine inside Agnus, designed for three operations: bulk memory copies (with logic), area filling, and line drawing. It operated on rectangular regions of chip RAM at speeds the 68000 could not match.

The Blitter had four DMA channels: A, B, and C as data sources, and D as the output destination. For each word processed, the three source values were combined through a programmable logic function (the minterm) to produce the output. This single mechanism handled everything from simple copies to cookie-cut sprite rendering.

Bit Name BLTCON0 $040 — Blitter Control Register 0
15–12 ASH Shift value for source A (0–15 bits right)
11 USEA Enable DMA channel A
10 USEB Enable DMA channel B
9 USEC Enable DMA channel C
8 USED Enable DMA channel D (output)
7–0 LF7–LF0 Minterm logic function — 256 possible Boolean combinations of A, B, C

The minterm byte encoded the Boolean function as a truth table: each bit position corresponded to a combination of A, B, C inputs. For example, $F0 = copy A (D=A), $CA = cookie-cut (D=AC+BC̄, i.e., use A where C is set, B where C is clear), $00 = clear to zero.

Bit Name BLTCON1 $042 — Blitter Control Register 1
15–12 BSH Shift value for source B (0–15 bits right)
4 EFE Exclusive fill enable
3 IFE Inclusive fill enable
2 FCI Fill carry input (initial fill state)
1 DESC Descending mode (process from bottom-right to top-left)
0 LINE Line draw mode enable

The Blitter's area fill mode worked line by line, right to left. It tracked a carry bit that toggled every time it encountered a set bit in the input — filling the space between pairs of boundary pixels. Inclusive fill (IFE) kept the boundary pixels in the output; exclusive fill (EFE) removed them. This made it trivial to draw filled polygons: render the outline with the line-draw mode, then fill it in a single blitter pass.

Line drawing used a hardware Bresenham algorithm. The screen was divided into 8 octants (numbered 0–7); the programmer calculated which octant the line fell in and set the SUD/SUL/AUL bits in BLTCON1 accordingly. The Blitter could draw lines up to 1024 pixels long, with optional 16-bit repeating patterns for dashed or textured lines.

BLTSIZE ($058) started the operation: bits 15–6 held the height (number of rows), bits 5–0 held the width (in words). Writing to BLTSIZE triggered the Blitter — it was always the last register written in a blitter setup sequence.

$DFF0A0

Audio

Paula provided four independent 8-bit PCM audio channels with hardware DMA. Channels 0 and 3 were routed to the left speaker, channels 1 and 2 to the right. Each channel continuously read waveform samples from chip RAM and fed them through a DAC — the music played itself without CPU intervention.

Audio Channel Registers (×4 — channel 0 shown)
AUD0LC $0A0/$0A2 — Pointer to waveform data in chip RAM (high/low words)
AUD0LEN $0A4 — Length in words (the DMA will transfer this many words, then restart from AUD0LC)
AUD0PER $0A6 — Period (sample rate). Lower = higher pitch. Period = clock / (2 × frequency).
AUD0VOL $0A8 — Volume: 0 (silent) to 64 (maximum). 6-bit linear scale.
AUD0DAT $0AA — Audio data register (2 samples, high byte played first). Used for non-DMA playback.

Channels 1–3 had identical registers at offsets $0B0, $0C0, $0D0.

The period register set the playback rate. The PAL system clock was 3.546895 MHz. For a sample rate of 8000 Hz: period = 3546895 / (2 × 8000) ≈ 222. The minimum useful period was about 124 (28.6 kHz) — below that, audio DMA consumed too many bus cycles and starved the display.

Paula also supported channel modulation: one channel could modulate the period or volume of the next channel in the pair (0→1, 2→3). ADKCON ($09E) bits 4–7 controlled this. Period modulation enabled FM-like synthesis effects; volume modulation enabled amplitude modulation (tremolo). These modes were rarely used by tracker music but appeared in some demo effects.

When a channel finished playing its buffer (AUDxLEN words exhausted), it triggered an audio interrupt (AUD0–AUD3 in INTREQ). The interrupt handler could then set up the next buffer — enabling double-buffered streaming audio. MOD players used this mechanism: each channel's interrupt pointed to the next set of samples, while the CPU spent its time mixing and applying effects.

$DFF030

Serial Port

Paula contained a UART (Universal Asynchronous Receiver/Transmitter) for serial communication. The DB25 RS-232 connector carried the data lines; CIA-B handled the handshaking signals (DTR, RTS, CTS, DSR, CD).

UART Registers
SERDAT $030 Transmit data (write). Lower 8 or 9 bits = data, upper bits = stop bits (set to 1).
SERDATR $018 Receive data (read). Bit 14: RBF (buffer full), Bit 13: TBE (transmit empty), Bit 12: TSRE (shift register empty), Bit 11: RXD level, Bits 0–7: received data.
SERPER $032 Baud rate and mode. Bit 15: LONG (1 = 9-bit data). Bits 14–0: period value.

The baud rate was set through SERPER using the formula:

SERPER = (clock / baud_rate) − 1, where clock = 3,579,545 Hz.

For 9600 baud: SERPER = (3579545 / 9600) − 1 ≈ 372 = $0174. For 4800 baud: SERPER ≈ 745 = $02E9.

The UART generated two interrupts: TBE (transmit buffer empty, INTREQ bit 0, level 1) when ready for the next byte, and RBF (receive buffer full, INTREQ bit 11, level 5) when a byte arrived. In raw mode (ignoring handshaking), the Amiga could reach about 292 Kbaud — far beyond the standard RS-232 rates.

$DFF020

Disk Controller

Paula's disk controller used DMA to transfer raw MFM-encoded data between chip RAM and the floppy drive. CIA-B controlled the mechanical signals (motor, step, direction, side select), while Paula handled the data stream.

Disk Registers
DSKPTH/L $020/$022 — Pointer to disk DMA buffer in chip RAM
DSKLEN $024 Bit 15: DMAEN (start DMA), Bit 14: WRITE (1 = write mode), Bits 13–0: transfer length in words
DSKSYNC $07E Sync word — DMA waits for this pattern before transferring (typically $4489 for AmigaDOS)
DSKBYTR $01A Disk byte and status (read). Bit 15: BYTEREADY, Bit 14: DMAON, Bit 13: DSKWRITE, Bit 12: WORDEQUAL, Bits 7–0: raw data byte.
DSKDAT $026 Disk DMA write data register
DSKDAT $008 Disk DMA read data register (early-read, not CPU-accessible)

To read a track, the programming sequence was:

  1. Ensure no write operation is in progress (check DSKLEN)
  2. Set DSKPTH/L to the buffer address
  3. Set DSKLEN with the transfer length and DMAEN set
  4. Write DSKLEN again (safety: requires two writes to start DMA)
  5. Wait for DSKBLK interrupt (INTREQ bit 1)
  6. Clear DSKLEN to stop DMA

The write sequence added an extra safety measure: DSKLEN had to be written twice with the WRITE bit set before a write would begin. This prevented accidental disk corruption from a single stray write.

ADKCON ($09E) controlled MFM/GCR encoding selection, precompensation timing, and the WORDSYNC mode that made the controller wait for the sync word in DSKSYNC before starting the transfer. The standard Amiga 3.5" DD drive stored 880 KB per disk: 80 tracks × 2 sides × 11 sectors × 512 bytes.

$KBD001

Keyboard

The Amiga 500's keyboard contained its own 6500/1 microcontroller. It scanned the key matrix independently and transmitted 8-bit scan codes serially to CIA-A through a two-wire protocol: KDAT (data) and KCLK (clock).

The protocol was active-low, MSB first. After transmitting a complete byte, the keyboard waited for the host to acknowledge by pulling KDAT low for at least 85 microseconds. Without this handshake, the keyboard would not send the next keycode — providing built-in flow control.

The scan code format was: bit 7 = 0 for key press, 1 for key release. Bits 6–0 encoded the key identity. The raw codes were position-based, not ASCII — the OS keymap translated them into characters.

A special three-key combination (Ctrl + Amiga + Amiga) triggered a hard reset by asserting the /KBRESET line, which was directly wired to the system reset circuit. This was the infamous "three-finger salute" that every Amiga user knew by instinct.

The keyboard also transmitted a power-up key stream: a sequence of codes at startup that identified the keyboard type and language layout. The system could detect whether the keyboard was present by checking for this stream within a timeout period.

$CONN01

Connectors

The Amiga 500's rear panel carried a distinctive row of connectors, each with a specific purpose:

Video — DB23 Female (analog RGB)
Pins 3,4,5 Red, Green, Blue — analog 0–0.7V from Denise
Pin 10 /CSYNC — composite sync
Pin 11 /HSYNC — horizontal sync
Pin 12 /VSYNC — vertical sync
Timing 15.625 kHz horizontal (PAL), 50 Hz vertical. Directly drives Amiga monitors; needs a scan doubler for VGA.
Joystick / Mouse — DE-9 Male (×2)
Pins 1–4 Up, Down, Left, Right (directly active digital switches, read via JOY0DAT $00A / JOY1DAT $00C)
Pin 6 Fire button — active low, read via CIA-A PRA bit 6 (port 0) or bit 7 (port 1)
Pin 5 Middle button / pot X — active low digital or proportional analog input (read via POT0DAT / POT1DAT)
Pin 9 Right button / pot Y — same as pin 5
Pin 7 +5V power supply (max 50 mA)
Serial — DB25 Male (RS-232)
Pin 2 TXD — transmit data (from Paula)
Pin 3 RXD — receive data (to Paula)
Pins 4–6,8,20 Handshake signals (RTS, CTS, DSR, CD, DTR) — managed by CIA-B Port A
Pin 7 Signal ground
Parallel — DB25 Female (Centronics-compatible)
Pins 2–9 Data bits 0–7 — bidirectional via CIA-A Port B ($BFE101)
Pin 1 /STROBE — active low output pulse
Pin 11 BUSY — active low, directly read via CIA-B Flag input
Pin 12 POUT — paper out
Pin 13 /SEL — printer selected
Floppy — DB23 Male (active low control, custom Amiga pinout)
Pin 2 /CHNG — disk changed (to CIA-A PRA bit 2)
Pin 3 /INDEX — once per revolution
Pin 5 /TK0 — track zero (to CIA-A PRA bit 4)
Pin 6 /WPRO — write protect (to CIA-A PRA bit 3)
Pin 7 /RDY — drive ready (to CIA-A PRA bit 5)
Pins 15,18,19 /MTR, /DIR, /STEP — motor, direction, step (from CIA-B)
Pin 13 /SEL0 — drive 0 select (active low, from CIA-B PRA bit 3)
Pin 14 /SIDE — side select (from CIA-B PRA bit 2)

The 86-pin expansion connector on the bottom provided full access to the 68000's address and data bus, plus control signals. This was the gateway for accelerator boards, RAM expansions, and any add-on that needed to talk directly to the CPU bus. It was the Amiga's greatest strength and limitation — completely open, completely unprotected, completely trusting.

$DFF1FE

Custom Chip Register Map

All custom chip registers lived in a 512-byte block starting at $DFF000. The offset (e.g., $096 for DMACON) was added to this base address. Registers were either read-only (R), write-only (W), or strobe (S — writing any value triggers the action). Some register pairs shared addresses for reading and writing different values.

DMA & Control
$002 R DMACONR — DMA control read
$096 W DMACON — DMA control write (SET/CLR)
$01C R INTENAR — Interrupt enable read
$09A W INTENA — Interrupt enable write (SET/CLR)
$01E R INTREQR — Interrupt request read
$09C W INTREQ — Interrupt request write (SET/CLR)
$010 R ADKCONR — Audio/disk control read
$09E W ADKCON — Audio/disk control write (SET/CLR)
$004 R VPOSR — Beam position (V8 and frame ID)
$006 R VHPOSR — Beam position (V7–V0, H8–H1)
$02A W VPOSW — Beam position write (for genlock sync)
$02C W VHPOSW — Beam position write
$02E W COPCON — Copper control (bit 1 = Copper danger)
Copper
$080 W COP1LCH — Copper list 1 pointer (high)
$082 W COP1LCL — Copper list 1 pointer (low)
$084 W COP2LCH — Copper list 2 pointer (high)
$086 W COP2LCL — Copper list 2 pointer (low)
$088 S COPJMP1 — Restart Copper at list 1
$08A S COPJMP2 — Restart Copper at list 2
$08C W COPINS — Copper instruction fetch (debug)
Bitplane
$100 W BPLCON0 — Bitplane control (# planes, HIRES, HAM, DPF)
$102 W BPLCON1 — Scroll values (PF1 and PF2 horizontal delay)
$104 W BPLCON2 — Sprite/playfield priority
$108 W BPL1MOD — Odd bitplane modulo
$10A W BPL2MOD — Even bitplane modulo
$0E0–$0EE W BPL1PT–BPL6PT — Bitplane 1–6 pointers (high/low word pairs)
$110–$11E R BPL1DAT–BPL6DAT — Bitplane data (latched from DMA)
$08E W DIWSTRT — Display window start (V7–V0, H7–H0)
$090 W DIWSTOP — Display window stop (V7–V0, H7–H0)
$092 W DDFSTRT — Data fetch start
$094 W DDFSTOP — Data fetch stop
Sprites ($120–$17E)
$120–$13E W SPR0PT–SPR7PT — Sprite 0–7 DMA pointers (high/low pairs)
$140–$17E W SPR0POS/CTL/DATA/DATB through SPR7POS/CTL/DATA/DATB — position, control, image data
Blitter
$040 W BLTCON0 — Blitter control 0 (shifts, enables, minterms)
$042 W BLTCON1 — Blitter control 1 (B-shift, fill, line mode)
$044 W BLTAFWM — First word mask for source A
$046 W BLTALWM — Last word mask for source A
$048–$056 W BLTCPT, BLTBPT, BLTAPT, BLTDPT — Source C/B/A and dest D pointers
$058 W BLTSIZE — Start blitter (height × 64 + width in words)
$060–$066 W BLTCMOD, BLTBMOD, BLTAMOD, BLTDMOD — Modulo values for C/B/A/D
$070–$076 W BLTCDAT, BLTBDAT, BLTADAT — Data registers for C/B/A
$000 R BLTDDAT — Blitter destination data (early read)
Audio
$0A0–$0AE AUD0 — LC (pointer), LEN (length), PER (period), VOL (volume), DAT (data)
$0B0–$0BE AUD1 — same layout
$0C0–$0CE AUD2 — same layout
$0D0–$0DE AUD3 — same layout
Disk
$020/$022 W DSKPT — Disk DMA pointer (high/low)
$024 W DSKLEN — DMA length and control
$026 W DSKDAT — Disk DMA data write
$008 R DSKDATR — Disk DMA data read (early read)
$01A R DSKBYTR — Disk byte and status
$07E W DSKSYNC — Disk sync pattern
Serial
$018 R SERDATR — Serial receive data and status
$030 W SERDAT — Serial transmit data
$032 W SERPER — Serial period (baud rate)
Collision Detection
$00E R CLXDAT — Collision data (all sprite-sprite and sprite-playfield collisions)
$098 W CLXCON — Collision control (enable bits and match values)
Color Palette ($180–$1BE)
$180–$1BE W COLOR00–COLOR31 — 32 color registers, 12-bit RGB (----RRRRGGGGBBBB)
Mouse/Joystick
$00A R JOY0DAT — Joystick/mouse port 0 data (counters)
$00C R JOY1DAT — Joystick/mouse port 1 data (counters)
$036 W JOYTEST — Write to both joystick counters
$012 R POT0DAT — Pot counter pair 0 (analog paddle/proportional inputs)
$014 R POT1DAT — Pot counter pair 1
$034 W POTGO — Pot start / pin direction
$016 R POTGOR — Pot port data read
$DFF1FE

Deep Dive Pages

Each subsystem has a dedicated deep-dive page with full register documentation, instruction encoding, and programming examples — translated from the Bible de l'Amiga.

$A01000
Amiga Models
A1000 through A4000 — chipset generations, CPUs, release history
$CPU000
Motorola 68000
Pin configuration, control signals, addressing, interrupts
$BFE001
CIA 8520
CIA-A & CIA-B ports, timers, TOD counter, interrupt control
$DFF000
Custom Chips
Agnus, Denise, Paula — architecture and pin descriptions
$000000
Memory Organization
Chip RAM, Fast RAM, memory map, ROM, register space
$DFF096
DMA & Interrupts
DMACON, bus cycles, INTREQ/INTENA, priority levels
$DFF080
Copper Coprocessor
MOVE/WAIT/SKIP instructions, Copper lists, DMA
$DFF100
Playfields & Display
Bitplanes, resolutions, HAM, dual playfields, scrolling
$DFF120
Sprites
8 channels, control words, positioning, attached sprites
$DFF040
Blitter
Block transfers, minterms, shifting, masks, fill, line draw
$DFF0A0
Audio System
4 channels, DMA playback, volume, modulation, filter
$JOY00A
Mouse & Joystick
Game ports, quadrature decoding, paddle inputs
$DFF030
Serial Port
UART, baud rate, SERDAT/SERDATR/SERPER
$DFF020
Disk Controller
Floppy DMA, MFM encoding, DSKSYNC
$KBD001
Keyboard
6500/1 microprocessor, serial protocol, key codes
$CONN01
Connectors
RGB, serial, parallel, floppy, game ports, expansion