System VIA

6522 VIA at SHEILA &FE40-&FE4F. Owned by the MOS. The CPU does not directly access keyboard/sound/speech/CMOS — it talks to a “slow peripheral bus” routed through System VIA Port A, with destinations selected by an 8-bit addressable latch driven from Port B.

Hands off unless you really know what you’re doing — MOS IRQ handlers fight you for the chip. Direct manipulation requires SEI / careful state restore.

See via-6522 for the generic 6522 register layout (T1/T2/SR/ACR/PCR/IFR/IER are identical across both VIAs).

Line assignments

Port A (PA0-PA7) — slow peripheral data bus

8-bit bidirectional. Carries data to/from sound chip, speech, keyboard, and (Master only) CMOS RAM. Direction is set per-transaction via DDRA at &FE43.

  • Set DDRA = &FF (all output) before a write.
  • Set DDRA = &00 (all input) before a read.
  • Write/read happens at ORA &FE41.

The peripheral being addressed is selected by the addressable latch — see below.

Port B (PB0-PB7) — control / status

PinDirectionFunction
PB0outputLatch address bit 0
PB1outputLatch address bit 1
PB2outputLatch address bit 2
PB3outputLatch data bit (the value to store at the selected latch line)
PB4inputJoystick 1 fire (active low)
PB5inputJoystick 2 fire (active low)
PB6inputSpeech “interrupt” (B / B+) or CMOS chip enable (Master, output)
PB7inputSpeech “ready” (B / B+) or CMOS address strobe (Master, output)

Control lines

LineFunctionIFR bit
CA1Vsync input from 6845 — IRQ every 20 ms (50 Hz)1
CA2Keyboard key-press interrupt0
CB1ADC end-of-conversion from µPD70024
CB2Light pen strobe (LPSTB) from analogue port3

The addressable latch (8-line write-only)

Driven from PB0-PB3:

  • PB0-PB2 = latch line index (0-7).
  • PB3 = value to store at that line.

To “set line 3 to 1”: clock PB0-PB3 = 0,1,1,1 → addressable latch line 3 becomes high. The chip latches the value on each PB write.

Line assignments

LineFunction
0Sound chip /WE (write enable, active low)
1Speech READ (B / B+); CMOS R/W direction (Master)
2Speech WRITE (B / B+); CMOS DS (Master)
3Keyboard /WE
4Screen-size addend bit 0 — hardware-scroll wrap
5Screen-size addend bit 1 — hardware-scroll wrap
6CAPS LOCK LED
7SHIFT LOCK LED

Hardware-scroll wrap addend

hardware-scrolling mentions hardware wrap-around. Lines 4-5 of this latch select which value gets added to the 6845’s fetch address when it goes above &7FFF, so the screen image wraps cleanly through screen RAM:

ModeScreen sizeStartAddendB5 (line 5)B4 (line 4)
0, 1, 220 KB&300012 KB10
316 KB&400016 KB00
4, 510 KB&580022 KB11
68 KB&600024 KB01

(MODE 7’s small screen wraps via different MOS logic — not via this addend.) Source: NAUG §22.3.2 p386.

The MOS sets these correctly at mode-set time; you only need to know about them if you build a custom mode.

Writing to the addressable latch

; Set line N to value V (V ∈ {0, 1})
; Pseudocode — must guard with SEI/CLI as System VIA is busy
SEI
LDA &FE40       ; current ORB (read-back of last write)
AND #&F0        ; clear PB0-3
ORA #(N | (V<<3))
STA &FE40       ; write back
CLI

In MOS terms there’s an OSBYTE for some of these (e.g. OSBYTE &78/&79 for keyboard suppression), but for sound chip / hardware scroll, direct PB write is the norm.

IRQ sources from this chip

MOS hooks IRQ1V (&204/&205) and reads IFR at &FE4D to dispatch:

IFR bitSourceWhat MOS does
0CA2 (keyboard)Read keyboard column on slow bus, push to key buffer
1CA1 (vsync)Update flashing colours, run 100 Hz semaphores, kick paged-ROM 100 Hz call
2SR(typically unused on this VIA)
3CB2 (light pen)Read R16/R17 of 6845; only if user enabled
4CB1 (ADC EOC)Read conversion result
5T2 timeoutCurrently unused by MOS on most machines
6T1 timeoutUsed by sound chip envelope timing (MOS)

Performance use cases

  • Vsync IRQ hook: hook IRQ1V, in your handler check &FE4D bit 1, if set then run frame-start work and clear the flag by reading ORA (&FE41). Use BIT &FE41 rather than LDA &FE41 — same 4 cycles, same bus read (so the chip still clears the IFR bit), but BIT doesn’t clobber the accumulator. That matters in an IRQ handler, where A is already stashed at &FC by MOS and reloading it costs cycles. See fast-animation.
  • Free-running T1: if MOS isn’t using T1 for sound (test by reading IER bit 6), repurpose T1 to fire raster splits at a specific scan line within a frame. Set ACR for free-run + PB7 toggle, load latches with lines_per_split × 64.
  • Manual sound-chip writes are tricky — between writing the sound data byte to PA and pulsing line 0 of the latch you need to ensure MOS doesn’t preempt and overwrite. Many demos disable IRQs across the whole sequence.

This wiki is curated by Claude following the LLM-Wiki methodology — a human curates source documents, the LLM compiles structured cross-linked markdown. Content may contain errors, omissions, or stale claims. For authoritative information refer to the original source documents in the bbc-documents GitHub archive.