diff --git a/restoration/rio-hardware/README.md b/restoration/rio-hardware/README.md new file mode 100644 index 00000000..858b1843 --- /dev/null +++ b/restoration/rio-hardware/README.md @@ -0,0 +1,170 @@ +# RIO cockpit hardware — boards, schematics, GAL dump + +Physical documentation of the VWE Tesla-cockpit **RIO** (Remote Input/Output) +board set, gathered during the 2026 restoration: board photos (Signal, +2026-07-15), a scan of the original paper wire schematics, and the fuse map +read out of the RIO board's GAL address decoder. + +All boards are **Copyright 1994 V.W.E. Inc.** — the schematic title blocks +spell it out: **Virtual World Entertainment, 1100 W Cermak Suite B404, +Chicago, Illinois**, every sheet and silkscreen credited **"Design by M.C."** +Schematic plots are dated 1/11/1996 (peripheral boards) and 6/26/1996 (RIO +board), so these drawings post-date the Rev. 0/1 boards they describe. + +## Board family + +| P/N | Title | Rev photographed | Key silicon | +|-----|-------|------------------|-------------| +| **1407** | RIO board ("CPU board") | Rev. 3 | Toshiba **TMP68HC11** @ 8 MHz, GAL20V8A decoder, 27C512 EPROM, LH52B256 32K SRAM, 5× HCTL-2016 | +| **1401** | Buttons board | Rev. 0 | 2× UCN5821A lamp drivers, 2× 74HCT165, 74HCT164, 74LS00/05 | +| **1402** | Keypad board | Rev. 1 | 2× 74HCT164, CD74HCT165, 74LS00/05 | +| **1408** | Display board ("RIO external display") | Rev. 1 | Intersil **ICM7228B** 8-digit driver, 8× LTS313A 7-segment | +| **1413** | Quad Amplifier Board | Rev. 1 | **Pyramid PB-150P "Pro Plus"** car amp (bolt-on) + passive 3-way crossovers | + +Plus the cockpit position sensors: **HP HEDS-5700** two-channel quadrature +optical encoders (option code **I** = 512 counts/rev; the photographed unit is +date-coded 9515, Singapore), one per analog axis, read by the five HCTL-2016 +counters on the RIO board (`OPT1`–`OPT5` = stick X/Y, throttle, left/right +pedals). + +## RIO board 1407 (schematic sheets 1–3, `RIO_1407`) + +**Sheet 1 — CPU : Memory Decoder.** The TMP68HC11 runs in expanded +multiplexed mode: a 74HCT573 latches A[0:7] off the AD bus, and **U7 — drawn +as a 20L8, fitted as a GAL20V8A-15LP** — decodes A[8:15] into `ROM_SEL*` +(27C512 EPROM, U10), `RAM_SEL*` (LH52B256-70LL 32K SRAM, U11), `PH_SEL*` +(HCTL-2016 bank via two 74LS138s), `DSP_SEL*` (external display port) and +`BND_SEL` (I/O-interface latch, sheet 3). Each HCTL-2016 feeds a 5-pin +header (`J4`–`J8`) carrying CHA/CHB from a HEDS-5700. The DB9 COM port goes +through a MAX231/MAX232-class level shifter; the schematic's `IN_RESET*` from +the serial side is the hardware behind the **DTR reset pulse** described in +[PROTOCOL.md](../PROTOCOL.md) §1. The "display interface" block (ALS541 +buffers, HEADER14) exports latched data lines `HD[00:04]` + digit address +`AS0-2` to the display board — this is a memory-mapped port, *not* the pod +bus. A 22V10 site (U31) is drawn mostly N/C and is **unpopulated** on the +photographed board. + +**Sheet 2 — Power & Reset Interface.** A MAX690 supervisor provides +power-fail reset and a **watchdog (WDI)**; reset can also come from the +front-panel `RESET` toggle (SW1) or remotely through an **H11L1 optocoupler** +fed from an isolated 3-pin `+5 VDC` input (J8) — the game PC can hard-reset +the board. The `ABORT` toggle (SW2) pulls the HC11 `IRQ*`. A 74LS241 drives +the status LED bank: `POWER ON`, `FAULT`, `RESET`, `RUN`, `TX`, `RX`. Power +enters on J9 through 5 A/10 A fuses, LC filters and 1N5341B clamp zeners, +producing separate logic `VCC` and peripheral `VCC_EXT` rails. + +**Sheet 3 — I/O Interface ("pod bus").** Eight identical 16-pin IDC ports +(`J11`–`J18`) fan out through ALS541 buffers and SIP resistor packs. All +ports share the outbound signals; each port has its own return line +(`DI[0..7]`, selected by a 74LS138 from `SEL0-2`) and its own buffered +brightness line (`BRT_CTR0-7`, all copies of one PWM signal). A 74HC574 +latch written via `BND_SEL` holds the bus control bits (`SEL0-2`, `RD_SB`, +`WR_SB`, `D_OUT`, `CCK`) — so the firmware bit-bangs the bus by rewriting +this latch. + +### Pod bus signal set (per port) + +| Signal | Direction | Purpose | +|--------|-----------|---------| +| `CCK` | RIO → pod | shift clock | +| `DD_IN` | RIO → pod | serial data into the pod's 74HCT164s (address select + payload) | +| `WR_SB` | RIO → pod | write strobe (latch lamp/display data) | +| `RD_SB` | RIO → pod | read strobe (parallel-load the pod's 74HCT165) | +| `DD_OUT` | pod → RIO | serial readback, **open-collector 74LS05** so pods can share a cable | +| `BRT_CTR` | RIO → pod | global lamp-brightness PWM, gates the UCN5821A output enable | +| `VCC_EXT`, GND | — | peripheral power rail | + +Every pod board carries a 74HCT164 whose parallel outputs go to an +**`ADR. SEL.` jumper block (`A-0`…`A-7`)**: the RIO shifts an address +pattern down the cable, the jumper picks which bit this board answers to, +and 74LS00 gates qualify `RD_SB`/`WR_SB` with that selection. This +hardware addressing is what the 0x00–0x6F logical input map in +[PROTOCOL.md](../PROTOCOL.md) ultimately resolves to. + +## Peripheral boards + +- **1401 Buttons board** (`PBE_1401`) — eight 4-pin connectors (`J3`–`J10`), + pinout `1 = buttons GND, 2 = button in, 3 = lamps +5V, 4 = lamps logic GND`. + Two UCN5821A serial-in latched sink drivers light the button lamps + (brightness = `BRT_CTR` PWM on their OE), two 74HCT165s read the buttons + back, one of them also echoing board status/address. +- **1402 Keypad board** (`KEY_1402`) — hosts the COTS 16-key hex pad (0–F) + on an 8-line header (4×4 matrix). A second 74HCT164 drives the matrix + rows through open-collector 74LS05 inverters; the 74HCT165 reads the four + columns (`IN0-3`, 2.7K pull-ups) plus a board-detect line `BRD_DT*`. +- **1408 Display board** (`DSP_1408`) — ICM7228B driving eight LTS313A + digits (hex decode) from the RIO's dedicated 14-pin *external display* + port; write-only, plus an isolated 26-pin **"IBM printer port"** LED + monitor block. Silkscreen reads "P/N 140B" but the schematic title block + confirms **1408**. Full pin-level output definition — and what the + firmware actually displays (boot banner + the keypad-A-9-E test mode) — + in [display-board-1408.md](display-board-1408.md). +- **1413 Quad Amplifier Board** (`AMP_PLT`, silkscreen "Quad Amplifier + Board … P/N 1413 REV. 1") — the actual amplification is a stock + **Pyramid PB-150P "Pro Plus"** 4-channel 12 V car-audio amplifier bolted + to the board as a module; the schematic only drew the VWE-designed + passive circuitry around it. The board feeds the Pyramid's `B+12V / GND + / REMOTE` screw terminals and speaker-level `HIGH INPUT` connectors, and + its four outputs (`1CH/L`…`4CH/R`) return through terminal strips into + per-corner 3-way passive crossovers: Dale IHB-3 inductors (820 µH woofer + low-pass, 180 µH midrange, date-coded 9531), MMP 100 VDC film capacitors + (2.2 µF/10 µF), and Dale CP-5 2 Ω 5 W pad resistors. Corner speaker + connectors J1–J4 (front/back × left/right) are 6-pin: `1 woofer+, + 2 midrange+, 3 tweeter+, 4 woofer−, 5 midrange−, 6 tweeter−` (silkscreen, + matching sheet 5). Power enters on J5 (4-pin: `+12VDC ×2, GND ×2`) with a + green POWER ON LED; the per-channel red LED pairs across the outputs are + the schematic's "speaker outputs checking circuit". PCB etch NT 1-0A 3695 + — the same fab batch series (week 36 '95) as the buttons board. + +## GAL dump — [`gal/GAL20v8a_5764.JED`](gal/GAL20v8a_5764.JED) + +Fuse map read 2023-03-09 from **U7 on the 1407 board** (GAL20V8A-15LP, +hand-labeled **"5764"** — which matches the JEDEC fuse checksum `*C5764`, the +source of the file name). Per sheet 1 it is the CPU **memory decoder** +(drawn as a 20L8). **Decoded** — equations, the recovered memory map +(`$2000-$9FFF` SRAM, `$A000/$A010/$A020` I/O windows, `$C000-$FFFF` EPROM) +and the firmware cross-check are in [`gal/README.md`](gal/README.md); the +chip's programmed signature even reads `U7`. + +## Schematic scan — [`schematics/Scans_018-014.pdf`](schematics/Scans_018-014.pdf) + +| PDF page | Sheet | Title block | +|----------|-------|-------------| +| 1 | RIO_1407 sheet 1/3 | CPU : Memory Decoder | +| 2 | RIO_1407 sheet 2/3 | Power & Reset Interface | +| 3 | RIO_1407 sheet 3/3 | I/O Interface | +| 4 | PBE_1401 1/1 | Buttons Board | +| 5 | AMP_PLT (P/N 1413) 1/1 | Amplifier Board | +| 6 | KEY_1402 1/1 | Keypad Board | +| 7 | DSP_1408 1/1 | Display Board | + +## Photo index ([`photos/`](photos/)) + +Original Signal filenames preserved here for provenance (taken 2026-07-15; +amplifier board 2026-07-19). + +| File | Original | Shows | +|------|----------|-------| +| `encoder-heds5700-control-assembly.jpeg` | `signal-2026-07-15-093011.jpeg` | HP HEDS-5700 I02 encoder (9515 A, Singapore) on a control-mechanism shaft | +| `display-board-1408-front-digits.jpeg` | `signal-2026-07-15-093017.jpeg` | Display board digit side, 8× LTS313A (U2–U9), PCB etch NT 1-0 5094 | +| `display-board-1408-back-driver.jpeg` | `signal-2026-07-15-093023.jpeg` | Display board driver side: ICM7228BIPI (date 9438), 16-pin IDC, "RIO EXTERNAL DISPLAY / P/N 140B REV. 1" | +| `keypad-1402-front-keys.jpeg` | `signal-2026-07-15-093032.jpeg` | 16-key hex keypad module (keys 0–F), front bezel | +| `keypad-board-1402-back-logic.jpeg` | `signal-2026-07-15-093038.jpeg` | Keypad board logic: DM74LS00N, 2× MM74HCT164N, SN74LS05N, CD74HCT165E, ADR. SEL. jumpers, "P/N 1402 REV. 1" | +| `buttons-board-1401-solder-side.jpeg` | `signal-2026-07-15-093045.jpeg` | Buttons board solder side, PCB etch NT 1-0 3695 | +| `buttons-board-1401-component-side.jpeg` | `signal-2026-07-15-093051.jpeg` | Buttons board: 2× CD74HCT165E, 74HCT00AP, 2× UCN5821A-type drivers, 74HCT164N, 8× lamp/button connectors, "P/N 1401 REV. 0" | +| `rio-board-1407-solder-side.jpeg` | `signal-2026-07-15-093058.jpeg` | RIO board solder side, PCB etch NT 3-0 4996 | +| `rio-board-1407-component-side.jpeg` | `signal-2026-07-15-093105.jpeg` | RIO board: TMP68HC11 QFP, GAL20V8A ("5764" sticker), AM27C512 EPROM, LH52B256 SRAM, 5× HCTL-2016 + OPT1–5, J11–J18 pod ports, status LEDs, "P/N 1407 REV. 3" | +| `amp-board-1413-component-side.jpeg` | `signal-2026-07-19-134932.jpeg` | Quad Amplifier Board full view: Pyramid PB-150P module, corner crossovers, "P/N 1413 REV. 1", J5 pinout silkscreen | +| `amp-board-1413-solder-side.jpeg` | `signal-2026-07-19-134926.jpeg` | Amplifier board solder side, PCB etch NT 1-0A 3695 | +| `amp-board-1413-pyramid-inputs.jpeg` | `signal-2026-07-19-134921.jpeg` | Pyramid input face: HIGH INPUT connectors, LEVEL pots, LOW INPUT RCAs; front-corner crossovers | +| `amp-board-1413-pyramid-outputs.jpeg` | `signal-2026-07-19-134915.jpeg` | Pyramid output face: SPEAKERS terminals 1CH/L–4CH/R, blade FUSE, B+12V/GND/REMOTE; check LEDs, J1–J4 pinout silkscreen | + +## Cross-references + +- [`../PROTOCOL.md`](../PROTOCOL.md) — the 9600 8N1 wire protocol this + hardware speaks; its DTR reset pulse and 0x00–0x6F input map both have + their physical explanation above. +- [`../../rio-firmware/`](../../rio-firmware/) — v4.2 EPROM dump (from the + AM27C512 at U10) and 68HC11 disassembly/patches. +- [`../Win32RIO/`](../Win32RIO/) — FASA's original Windows driver for the + same hardware. diff --git a/restoration/rio-hardware/display-board-1408.md b/restoration/rio-hardware/display-board-1408.md new file mode 100644 index 00000000..db44d776 --- /dev/null +++ b/restoration/rio-hardware/display-board-1408.md @@ -0,0 +1,148 @@ +# Display Board 1408 — outputs, and what the RIO shows on it + +Complete definition of the RIO External Display board (P/N 1408 Rev. 1, +`DSP_1408` sheet 7), from the schematic, the board photos, the GAL decode, +and the firmware disassembly (`RIOv4_2.disasm.asm`). + +## Outputs: light only — the board is electrically write-only + +No signal leaves the board toward the RIO or anything else. J1 has no +readback line, matching the GAL's write-only `DSP_SEL*` decode, and the +PC↔RIO protocol has no display command — only the firmware writes it. + +### 1. Eight multiplexed 7-segment digits (U2–U9, LTS313A, red, common-cathode) + +The ICM7228B (U1) does all driving. `HEX/B/SHD` is strapped high via 2.7 K +(R1): **hexadecimal decode mode, always enabled** — each digit renders 0–F +plus a decimal point; no raw-segment access exists as built. + +- **Segment bus** — U1 pins 16, 17, 20, 18, 21, 22, 23, 15 drive + `SEGA`–`SEGG`, `SEGDP`, shared by all digits (digit pins A–G, DP = + 10, 9, 8, 5, 4, 2, 3, 7). Segments source the multiplexed current + (~20 mA peak). +- **Digit commons** — U1 outputs `DSP1`–`DSP8` (pins 4, 25, 3, 1, 26, 2, + 27, 24) each sink one digit's tied-together commons (CC1+CC2, pins 6+1). + `DSP1`→U2 (leftmost) … `DSP8`→U9 (rightmost). +- Multiplex scanning is internal to the ICM7228; the host only writes + digit registers. + +From the 68HC11 the digits are bytes at **`$A000`–`$A007`** (`AS0-2` = +A0–A2, strobed by `DSP_SEL*` = `E & /R/W`-qualified, arriving as the +7228's `/WR` on J1 pin 7). Data format per write: bits 0–3 = hex value +(`MD[00:03]`→`ID0-3`), bit 4 = decimal point (`MD[04]`→`ID7`; DP lights +when the bit is **low** — the firmware always sets it, so the DP is never +used). **`$A000` = leftmost digit (U2), `$A007` = rightmost (U9)**; the +firmware's render buffer (`$2038`, routine `$CB49`) fills right-to-left so +multi-digit hex numbers read naturally. + +### 2. Twelve passive monitor LEDs on the "IBM printer port" header (J2) — an input, not an output + +J2 (26-pin IDC, standard LPT-ribbon mapping to a DB25) is electrically +isolated from the display circuit; its `DD` nets touch nothing but LEDs +and 1 K resistors referenced to the PC's own ground (`IBM_GND`). With a PC +parallel port plugged in, the LEDs show: **D0–D7** = data bits (J2 pins +3, 5, 7, 9, 11, 13, 15, 17), **D8** = `/STROBE` (pin 1), **D9–D11** = +`/AUTOFD`, `/INIT`, `/SELECTIN` (pins 2, 6, 8). The LPT status returns are +strapped to ground so a PC streams without waiting. It is a built-in +parallel-port activity monitor / bench tool, powered entirely by the PC. + +### 3. Nothing else + +J1 (14-pin, from the RIO's EXTERNAL DISPLAY port) is all input: +`MD[00:04]` on pins 2, 4, 6, 8, 10; `AS0-2` on 1, 3, 5; `BF_DSP_SEL*` on +7; GND on 9, 11, 13; VCC on 12, 14. + +## What the RIO firmware displays (v4.2) + +All display writes go through `$CB49` (buffer render) or five canned +patterns at `$CB7C–$CC52`, driven from four contexts: initialization, +the built-in **test mode**, the **serial error/crash displays**, and +the **CheckRequest self-test** (all below). During normal, healthy +gameplay the display is static. + +**Normal operation:** `F0000000` — written at cold boot (`$C068`) and warm +re-init (`$C64B`), then left alone. + +**Test mode** — entered by typing the keypad sequence **A, 9, E** on a +cockpit keypad (`$C1CB` tracks the sequence at `$20F8`); entry sets flag +`$2421`, shows `F1000000`, and notifies the PC (`TestModeChange`, cmd +`0x8C` — see [PROTOCOL.md](../PROTOCOL.md)). Within test mode the next +keypad digit selects a sub-test; **F** ends a sub-test (back to +`F1000000`), **D** exits test mode (back to `F0000000`). + +Display format convention: **left pair = test number, right = value**, +zeros as filler; the decimal points are never used. + +| Key | Display | Test | +|-----|---------|------| +| *(entry)* | `F1000000` | test-mode banner | +| `0` | `00000000` | encoder-counter reset: presets the five 16-bit accumulators to `$FAFA` and re-reads all HCTL-2016s (`$C446`) | +| `1` | `0100hhll` | axis test, channel 01 — counter at `$A028/$A038` | +| `2` | `0200hhll` | axis test, channel 02 — `$A020/$A030` | +| `3` | `0300hhll` | axis test, channel 03 — `$A022/$A032` | +| `C` | `0C00hhll` | axis test, channel 0C — `$A024/$A034` | +| `4` | `0400hhll` | axis test, channel 04 — `$A026/$A036` | +| `5` | `050000nn` | button test — `nn` = index of the pressed input (scan at `$D004` over the pod input state at `$2152`), with lamp feedback | +| `6` | `06000003` | lamp test, pattern 3 (`$D34A`) — right digit is the pattern code | +| `7` | `07000001` | lamp test, pattern 1 (`$D370`) | +| `8` | `080000kk` | keypad test — `kk` = keypad status byte `$204B`, refreshed while scanning (`$CC7E`) | + +In the axis tests `hhll` is the **live 16-bit quadrature count in hex** +(high:low = `$201D:$201E`, alternating with the raw latched bytes +`$2026:$2025` as the loop runs) — spin the stick/throttle/pedal encoder +and watch the number move. The channel IDs are literally the keypad keys +that start them, which is why the fourth axis reads `0C`. + +## The CheckRequest self-test leftover: `04000000` + +The host `CheckRequest` (`0x80`) triggers a full self-test in the +handler at `$C5A6`: it sets the same display flag test mode uses +(`$2421`), brackets itself with `TestModeChange 0x8C` notifications, +flashes a lamp pattern, scans the pods, and sweeps the five encoder +channels — rendering each channel's `cc00hhll` frame as it goes. It +clears the flag on exit but **never repaints the display**, so after +every status check the digits are left showing the last frame: +channel 4, usually `04000000` with idle encoders. It is a stale +snapshot (axis movement does not update it — bench-confirmed +2026-07-19), purely cosmetic, and the board keeps operating normally. +Any reset repaints `F0000000`. + +## Error displays (the third use) + +Two more display writers live in the serial machinery — the display is +also the RIO's **error annunciator**: + +- **`E0` serial-diagnostics readout** (`$D5F2`) — `E0xxyyzz` where + `xx` = TX-ring overflow count (`$3187`, outbound byte dropped because + the ring was full, `$D66A`), `yy` = give-up count (`$3184`, `$D96A` — + reply cycles whose 5 timeout retransmits all went unACKed), `zz` = + reply-teardown count (`$3185`, `$DA2F` — any reply cycle that needed + at least one retransmission; the counter behind a lone `E0000001`). + Semantics bench-confirmed 2026-07-19: display read `E0000105` after + one give-up + five teardowns. Each increment site immediately re-renders, + so the display live-updates as serial trouble accumulates. If a + cockpit's display reads `E0…` instead of `F0000000`, the serial link + has been dropping or retrying. Note there is **no threshold in stock + firmware** — the first event paints `E0000001` permanently; the + **RIO 4.3** firmware (`make_patch.py --e0thresh`, see + [RIOv4_2-ANALYSIS.md](../../rio-firmware/RIOv4_2-ANALYSIS.md)) keeps + the display quiet until a counter reaches 5, and repaints honestly + after every check self-test. +- **`dEAd` crash screen** (`$DAB8`, loop at `$DAB2`) — the TX-ISR ring + drain (`$D8C2`) looks each outgoing command byte up in an 8-entry + dispatch table at `$3158`; an unmatched byte means internal state + corruption, and the firmware jumps to an infinite loop that renders + `#$DE #$AD` → **`dEAd`** followed by RAM bytes `$0000/$0001` (nothing + in this build writes them — vestigial debug data). The board is dead + until reset; there is no watchdog to rescue it (the MAX690's WDI is + not connected to the CPU and no strobe code exists in the firmware). + +## Cross-references + +- [README.md](README.md) — board family, photos, schematic page map +- [gal/README.md](gal/README.md) — `DSP_SEL*` decode (`$A000-$A00F`, + write-only) recovered from the GAL fuse map +- [`rio-firmware/RIOv4_2.disasm.asm`](../../rio-firmware/RIOv4_2.disasm.asm) + — display routines `$CB20/$CB36/$CB49` (buffer render), `$CB7C` (`F0`), + `$CBA7` (`F1`), `$CBD2`/`$CBFD` (lamp-test banners), `$CC28` (zeros), + test dispatcher `$C241`, entry-sequence tracker `$C1CB` diff --git a/restoration/rio-hardware/gal/GAL20v8a_5764.JED b/restoration/rio-hardware/gal/GAL20v8a_5764.JED new file mode 100644 index 00000000..fb43e5c1 --- /dev/null +++ b/restoration/rio-hardware/gal/GAL20v8a_5764.JED @@ -0,0 +1,38 @@ + +Device : GAL20V8A +Created By: http://www.autoelectric.cn +Date : 2023-03-09 19:02 +*QP24 +*QF2706 +*G0 +*F0 +*L00000 11111111111111111111111111111111 +*L00032 11111111111111011111111111111111 +*L00064 11111111110111110000000000000000 +*L00320 11111111111111111111111111111111 +*L00352 11111111111111111111111111111111 +*L00384 11111110111111110000000000000000 +*L00640 11111111111111111111111111111111 +*L00672 11111111100101111011101110111011 +*L00704 10111011101101110000000000000000 +*L00960 11111111111111111111111111111111 +*L00992 11111111111001111111111111111111 +*L01024 11111111110111110110111111111111 +*L01056 11111111111111111101111110011011 +*L01088 11111111111111111111111111011111 +*L01280 11111111111111111111111111111111 +*L01312 11111111100101101011101110111011 +*L01344 10111011100110010000000000000000 +*L01600 11111111111111111111111111111111 +*L01632 11111111100101101011101110111011 +*L01664 10111011100110100000000000000000 +*L02240 11111111111111111111111111111111 +*L02272 11111111010111111111111111111111 +*L02304 11111111111111110000000000000000 +*L02560 01000000010101010011011100101110 +*L02592 00101110001011100010111000000000 +*L02624 00000000111111111111111111111111 +*L02656 11111111111111111111111111111111 +*L02688 111111111111111111 +*C5764 +*F676 diff --git a/restoration/rio-hardware/gal/README.md b/restoration/rio-hardware/gal/README.md new file mode 100644 index 00000000..17f6e57e --- /dev/null +++ b/restoration/rio-hardware/gal/README.md @@ -0,0 +1,71 @@ +# U7 GAL20V8A decode — the RIO memory map, recovered + +[`GAL20v8a_5764.JED`](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`](../../../rio-firmware/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`](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`](u7-pin-names.txt). Reproduce with: + +```sh +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. diff --git a/restoration/rio-hardware/gal/galdecode.py b/restoration/rio-hardware/gal/galdecode.py new file mode 100644 index 00000000..cba3afb4 --- /dev/null +++ b/restoration/rio-hardware/gal/galdecode.py @@ -0,0 +1,91 @@ +"""Decode a GAL20V8 JED (complex mode) into boolean equations. + +Fuse-map semantics taken from MAME jedutil.cpp (config_gal20v8_pins, +get_pin_fuse_state, is_gal20v8_product_term_enabled, +does_output_enable_fuse_row_allow_output). +""" +import re +import sys + +JEDPATH = sys.argv[1] if len(sys.argv) > 1 else r"C:\VWE\riojoy\docs\hardware\gal\GAL20v8a_5764.JED" + +QF = 2706 +fuses = [0] * QF # *F0 default +text = open(JEDPATH).read() +for m in re.finditer(r"\*L(\d+)\s+([01]+)", text): + start = int(m.group(1)) + for i, ch in enumerate(m.group(2)): + fuses[start + i] = int(ch) + +SYN, AC0 = fuses[2704], fuses[2705] +mode = {(1, 1): "complex", (1, 0): "simple", (0, 1): "registered", (0, 0): "registered"}[(SYN, AC0)] +print(f"SYN={SYN} AC0={AC0} -> {mode} mode") +assert mode == "complex", "decoder only handles complex mode" + +# UES signature 2568-2631, 8 bytes MSB-first +ues = bytes( + int("".join(map(str, fuses[2568 + 8 * i : 2576 + 8 * i])), 2) for i in range(8) +) +print("UES signature:", ues, "->", ues.decode("ascii", "replace")) + +# complex-mode column map: pin -> (lowfusecolumn, highfusecolumn) +COLS = {1: (3, 2), 2: (1, 0), 3: (5, 4), 4: (9, 8), 5: (13, 12), 6: (17, 16), + 7: (21, 20), 8: (25, 24), 9: (29, 28), 10: (33, 32), 11: (37, 36), + 13: (39, 38), 14: (35, 34), 16: (31, 30), 17: (27, 26), 18: (23, 22), + 19: (19, 18), 20: (15, 14), 21: (11, 10), 23: (7, 6)} +# complex-mode rows: pin -> (OE row fuse, first PT fuse, last PT fuse) +ROWS = {22: (0, 40, 280), 21: (320, 360, 600), 20: (640, 680, 920), + 19: (960, 1000, 1240), 18: (1280, 1320, 1560), 17: (1600, 1640, 1880), + 16: (1920, 1960, 2200), 15: (2240, 2280, 2520)} +XOR = {15: 2567, 16: 2566, 17: 2565, 18: 2564, 19: 2563, 20: 2562, 21: 2561, 22: 2560} + +# Optional net names for pins, filled after reading the schematic: +NAMES = {} +if len(sys.argv) > 2: + for kv in open(sys.argv[2]): + kv = kv.strip() + if kv and not kv.startswith("#"): + p, n = kv.split(None, 1) + NAMES[int(p)] = n + +def name(pin): + return NAMES.get(pin, f"pin{pin}") + +def pt_enabled(fuserow): + return fuses[2640 + fuserow // 40] == 1 + +def term(fuserow): + """Return list of literals, or None if term is always-false, '1' if always-true.""" + lits = [] + for pin in sorted(COLS): + lo, hi = COLS[pin] + l, h = fuses[fuserow + lo], fuses[fuserow + hi] + if l == 0 and h == 1: + lits.append("/" + name(pin)) + elif l == 1 and h == 0: + lits.append(name(pin)) + elif l == 0 and h == 0: + return None # both intact -> always false + return lits if lits else ["1"] + +for pin in sorted(ROWS, reverse=True): + oerow, first, last = ROWS[pin] + oe = term(oerow) if pt_enabled(oerow) else None + if oe is None: + print(f"\npin {pin} ({name(pin)}): OE never true -> used as INPUT") + continue + pol = "active-HIGH" if fuses[XOR[pin]] else "active-LOW" + pts = [] + for f in range(first, last + 40, 40): + if not pt_enabled(f): + continue + t = term(f) + if t is not None: + pts.append(" & ".join(t)) + lhs = name(pin) if fuses[XOR[pin]] else "/" + name(pin) + oestr = " & ".join(oe) + print(f"\npin {pin} ({name(pin)}): {pol}, OE = {oestr}") + if pts: + print(f" {lhs} = " + ("\n" + " " * (len(lhs) + 5) + "| ").join(pts)) + else: + print(f" {lhs} = 0 (no active product terms)") diff --git a/restoration/rio-hardware/gal/u7-pin-names.txt b/restoration/rio-hardware/gal/u7-pin-names.txt new file mode 100644 index 00000000..3ba5c110 --- /dev/null +++ b/restoration/rio-hardware/gal/u7-pin-names.txt @@ -0,0 +1,23 @@ +# U7 (GAL20V8A, "20L8" on schematic RIO_1407 sheet 1) pin -> net name +1 A15 +2 A14 +3 A13 +4 A12 +5 A11 +6 A10 +7 A9 +8 A8 +9 A7 +10 A6 +11 A5 +13 A4 +14 E +23 RW +16 A3 +15 ROM_SEL +22 OE +21 NOT_A3 +20 PH_SEL +19 RAM_SEL +18 BRD_SEL +17 DSP_SEL diff --git a/restoration/rio-hardware/photos/amp-board-1413-component-side.jpeg b/restoration/rio-hardware/photos/amp-board-1413-component-side.jpeg new file mode 100644 index 00000000..3c814900 Binary files /dev/null and b/restoration/rio-hardware/photos/amp-board-1413-component-side.jpeg differ diff --git a/restoration/rio-hardware/photos/amp-board-1413-pyramid-inputs.jpeg b/restoration/rio-hardware/photos/amp-board-1413-pyramid-inputs.jpeg new file mode 100644 index 00000000..523deda6 Binary files /dev/null and b/restoration/rio-hardware/photos/amp-board-1413-pyramid-inputs.jpeg differ diff --git a/restoration/rio-hardware/photos/amp-board-1413-pyramid-outputs.jpeg b/restoration/rio-hardware/photos/amp-board-1413-pyramid-outputs.jpeg new file mode 100644 index 00000000..c54793e3 Binary files /dev/null and b/restoration/rio-hardware/photos/amp-board-1413-pyramid-outputs.jpeg differ diff --git a/restoration/rio-hardware/photos/amp-board-1413-solder-side.jpeg b/restoration/rio-hardware/photos/amp-board-1413-solder-side.jpeg new file mode 100644 index 00000000..d5825141 Binary files /dev/null and b/restoration/rio-hardware/photos/amp-board-1413-solder-side.jpeg differ diff --git a/restoration/rio-hardware/photos/buttons-board-1401-component-side.jpeg b/restoration/rio-hardware/photos/buttons-board-1401-component-side.jpeg new file mode 100644 index 00000000..90f32c33 Binary files /dev/null and b/restoration/rio-hardware/photos/buttons-board-1401-component-side.jpeg differ diff --git a/restoration/rio-hardware/photos/buttons-board-1401-solder-side.jpeg b/restoration/rio-hardware/photos/buttons-board-1401-solder-side.jpeg new file mode 100644 index 00000000..1aead52a Binary files /dev/null and b/restoration/rio-hardware/photos/buttons-board-1401-solder-side.jpeg differ diff --git a/restoration/rio-hardware/photos/display-board-1408-back-driver.jpeg b/restoration/rio-hardware/photos/display-board-1408-back-driver.jpeg new file mode 100644 index 00000000..bd555693 Binary files /dev/null and b/restoration/rio-hardware/photos/display-board-1408-back-driver.jpeg differ diff --git a/restoration/rio-hardware/photos/display-board-1408-front-digits.jpeg b/restoration/rio-hardware/photos/display-board-1408-front-digits.jpeg new file mode 100644 index 00000000..111ad665 Binary files /dev/null and b/restoration/rio-hardware/photos/display-board-1408-front-digits.jpeg differ diff --git a/restoration/rio-hardware/photos/encoder-heds5700-control-assembly.jpeg b/restoration/rio-hardware/photos/encoder-heds5700-control-assembly.jpeg new file mode 100644 index 00000000..b29bf359 Binary files /dev/null and b/restoration/rio-hardware/photos/encoder-heds5700-control-assembly.jpeg differ diff --git a/restoration/rio-hardware/photos/keypad-1402-front-keys.jpeg b/restoration/rio-hardware/photos/keypad-1402-front-keys.jpeg new file mode 100644 index 00000000..89dae75c Binary files /dev/null and b/restoration/rio-hardware/photos/keypad-1402-front-keys.jpeg differ diff --git a/restoration/rio-hardware/photos/keypad-board-1402-back-logic.jpeg b/restoration/rio-hardware/photos/keypad-board-1402-back-logic.jpeg new file mode 100644 index 00000000..9c7b46cf Binary files /dev/null and b/restoration/rio-hardware/photos/keypad-board-1402-back-logic.jpeg differ diff --git a/restoration/rio-hardware/photos/rio-board-1407-component-side.jpeg b/restoration/rio-hardware/photos/rio-board-1407-component-side.jpeg new file mode 100644 index 00000000..471dfde4 Binary files /dev/null and b/restoration/rio-hardware/photos/rio-board-1407-component-side.jpeg differ diff --git a/restoration/rio-hardware/photos/rio-board-1407-solder-side.jpeg b/restoration/rio-hardware/photos/rio-board-1407-solder-side.jpeg new file mode 100644 index 00000000..3993e1ee Binary files /dev/null and b/restoration/rio-hardware/photos/rio-board-1407-solder-side.jpeg differ diff --git a/restoration/rio-hardware/schematics/Scans_018-014.pdf b/restoration/rio-hardware/schematics/Scans_018-014.pdf new file mode 100644 index 00000000..be55baba Binary files /dev/null and b/restoration/rio-hardware/schematics/Scans_018-014.pdf differ