Sibling links (hardware<->firmware) now resolve within restoration/; links to RIOjoy's PROTOCOL.md and Win32RIO/ (which stayed in the RIOjoy repo) point to gitea web URLs.
U7 GAL20V8A decode — the RIO memory map, recovered
GAL20v8a_5764.JED is the fuse map read out of U7
on the RIO board (P/N 1407 Rev. 3) — the chip the schematic draws as a
"20L8" memory decoder. Decoding the fuses (see below for how) yields the
complete address decode, which cross-checks perfectly against both the
schematic net names and the firmware disassembly.
Three provenance details line up: the chip's hand-written sticker reads
"5764" = the JED fuse checksum (*C5764); the fuse map is in complex
(20L8-emulation) mode exactly as the schematic symbol suggests; and the
programmed electronic signature (UES) literally reads U7 — VWE
signed the chip with its own reference designator.
Recovered equations
Inputs: A[15:3] (A3 arrives via the pin-16 feedback path), E, R/W.
All outputs are combinatorial, always enabled.
/ROM_SEL = A15 & A14 ; pin 15
/RAM_SEL = /A15 & A14 & E | /A15 & A13 & E | A15 & /A14 & /A13 & E ; pin 19
/PH_SEL = A15 & /A14 & A13 & /A12../A6 & A5 ; pin 20
/BRD_SEL = A15 & /A14 & A13 & /A12../A6 & /A5 & A4 & E & /RW ; pin 18
/DSP_SEL = A15 & /A14 & A13 & /A12../A6 & /A5 & /A4 & E & /RW ; pin 17
/OE = E & RW ; pin 22
NOT_A3 = /A3 ; pin 21
(/A12../A6 abbreviates the run /A12 & /A11 & /A10 & /A9 & /A8 & /A7 & /A6;
full machine output comes from galdecode.py, below.)
The memory map
| Address | Select | Device | Notes |
|---|---|---|---|
$0000-$1FFF |
(none) | 68HC11 internal | RAM $0000-$00FF, registers $1000-$103F |
$2000-$9FFF |
RAM_SEL* |
LH52B256 32K SRAM | E-qualified, read/write; exactly 32K |
$A000-$A00F |
DSP_SEL* |
External-display write port | write-only (E & /RW) |
$A010-$A01F |
BRD_SEL |
Pod-bus control latch (74HC574, sheet 3) | write-only (E & /RW) |
$A020-$A03F |
PH_SEL* |
HCTL-2016 encoder counters ×5 | A3 picks high/low count byte via NOT_A3, A[2:0] picks chip via the 74LS138s |
$C000-$FFFF |
ROM_SEL* |
27C512 EPROM | top 16K of the 64K device |
OE* (E & R/W) is the shared read-side output enable for
EPROM/SRAM/counters; the write-only decodes double as write strobes.
Firmware cross-check — RIOv4_2.disasm.asm
touches precisely these windows and nothing else in $A0xx: digit writes to
$A000-$A007, pod-bus latch writes to $A010, and encoder reads at
$A021/$A023/$A025/$A027/$A029 + $A028/$A030-$A038 (five chips × two count
bytes). It also explains the EPROM dump being FF below $C000: with
ROM_SEL* = A15·A14 and all 16 address lines wired, only the top quarter of
the 27C512 is ever addressed.
How the decode was done
galdecode.py parses the JED and applies the GAL20V8
complex-mode fuse geometry — row/column-to-pin tables, product-term-disable
fuses, XOR polarity, SYN/AC0 mode bits — taken from MAME's jedutil.cpp
(the reference implementation for PLD fuse maps). Pin-to-net names come
from schematic sheet 1 (RIO_1407) and live in
u7-pin-names.txt. Reproduce with:
py docs/hardware/gal/galdecode.py docs/hardware/gal/GAL20v8a_5764.JED docs/hardware/gal/u7-pin-names.txt
The JED itself was read from the chip on 2023-03-09 (header says an
autoelectric.cn / XGecu-style programmer). Note *F0 in the header: unlisted
fuse rows default to 0, i.e. unused product terms are all-connected
(always-false) rather than blown — the decoder handles this.