ShiboSoftwareDev/linux-gameboy-advance

A multilayer PCB carrier/router with USB-C and battery power selection, buck regulation, microSD, LCD/backlight, UART/SPI/I²C service headers, controls, volume input, and RGB status LEDs, using vias and reviewed copper routing.

Version
1.0.123
License
unset
Stars
0

Files

README.md

# F1C100S Linux Game Boy Advance

A four-layer, GBA-shaped tscircuit handheld built around the tested F1C100S Linux design. The editable source is `index.circuit.tsx`; the generated PCB, schematic, circuit JSON, Gerbers, drill files, BOM and position data are derived artifacts.

This revision is designed and software-checked for fabrication, but it has not yet been physically assembled or boot-tested. Do not confuse zero software DRC with hardware qualification: first articles still need rail, thermal, display timing, audio and USB measurements.

## Hardware

- Allwinner F1C100S ARM9 SoC with 32 MiB integrated DDR1 and the complete tested support circuit.
- 16 MiB W25Q128 SPI NOR plus 4-bit microSD for boot/root filesystem. The TF-01A socket remains on the upper-right edge, above the palm grip: its real CAD-model card mouth is flush at x=72.25 mm and the complete rigid housing remains backed by PCB material. The enclosure wall now forms a short 2.2 mm protective access tunnel, recessing the card edge against accidental ejection without moving the socket or disturbing its verified routing.
- 50-pin 0.5 mm RGB666 connector for the 3.5-inch 320 × 480 ER-TFT035IPS-6 family. The panel is rotated 90° into landscape; its flex folds back into the right-side connector toward the left. The 3D view is converted from EastRising's official ER-TFT035-6 STEP model: the 56.54 × 84.96 mm capacitive-touch outline, active area, bezel, backlight, copper, stiffener and driver geometry remain unscaled. The rigid panel and the FPC tip retain the shared centerline from the vendor model—there is no artificial sideways displacement or kink. To keep the proven 50-pin connector fanout intact, the board's top datum was extended by 2.27 mm to y=43.27 mm and the shoulder switches moved with it; the rigid screen's top edge now coincides with that PCB edge. Only the explicitly flexible FPC is deformed along its installed fold path from `J_LCD`; its bend radius and 7 mm panel standoff remain enclosure-dependent installation constraints. The board also routes the panel serial-control and optional touch signals.
- Twelve controls: D-pad, A/B/X/Y and the central lower Start/Select pair use the verified Game Boy's 15 mm actuators; L/R use JLCPCB `C33543618` (`TS6695ZJ 022`), the 9.5 mm mid-stem variant of the same low-profile right-angle switch family. Start and Select are centred at x=-14/1 mm, away from both primary hand-control clusters. The shoulder housings stop flush with the top PCB edge while the round stems project 3.03 mm beyond it. Each shoulder control is a 21 × 5.8 mm rounded sliding key in a matching guide, not a flange wrapped around the switch. Two narrow rails straddle the actuator, independent 7.2 mm-high hidden tabs overhang the guide by 0.40 mm to retain the key, and a blind rear pocket leaves 1.835 mm of solid finger-face material. The evaluated assembly retains 0.30 mm lateral/vertical guide clearance, a 0.13 mm closed-case visual gap, 0.30 mm tab-to-wall clearance, a 0.25 mm actuator rest gap, and 0.40 mm usable switch stroke. Exact mesh intersections are checked at rest and across the full 0.65 mm inward sweep. A PCF8575 I²C expander presents the controls to Linux as active-low GPIO inputs.
- One USB-C port, `J_USB`, supplies the board from standard 5 V VBUS while also carrying the native USB 2.0 device/FEL data pair. It has independent 5.1 kΩ CC pull-downs, USBLC6-2 data-line ESD protection, local VBUS decoupling, and Schottky OR-ing into `SYS_IN`. No USB-PD controller or second receptacle is fitted.
- Two removable AA cells in series, matching the original GBA's battery count. The enclosure has an integrated under-PCB cell cradle sized from the 14.5 × 50.5 mm maximum AA envelope, internal series contacts, and a flush rear door with an insertion tongue, flex latch, and thumb dimple. The contacts wire internally through the PCB slot to `J_BAT`; there is no external battery cable or separate holder pod. The cells are user-replaceable and are **not charged by USB**. The power slider remains centered on the straight lower-left side wall at y=-24 mm, away from the rounded corner, and faces left. Measured from the real C136720 CAD geometry, the actuator projects 4.50 mm beyond the PCB edge while the housing face remains 0.50 mm inside the outline so it does not foul the enclosure.
- TPS63020 buck-boost conversion from the two-AA 1.8–3.2 V operating range to 3.3 V with a shielded 1.5 µH YHNR4020-1R5M inductor (JLCPCB C18199423), followed by dedicated 2.5 V DRAM, 1.2 V core and 2.8 V analog rails. A P-channel source selector disconnects the battery path when USB is present, avoiding a Schottky loss in the low-voltage battery path.
- F1C100S headphone output feeding a volume control and PAM8403 mono bridge amplifier. The volume wheel is on the upper-left rounded corner, faces diagonally outward at 46.778°, and is kept away from the user's lower grip. The visible enclosure opening is a close-fitted 15.2 × 3.2 mm capsule around the real 14 mm C231765 wheel; a 19 mm hidden wall-normal tunnel reaches the wheel without enlarging the exterior slot. The potentiometer sits 1.8 mm inward from the aperture, leaving 0.897 mm of usable wheel projection while its housing stays inside the shell. Both plated mounting slots remain on PCB material with a measured minimum 0.551 mm copper-to-edge clearance. `J_SPK` is the amplified two-wire **BTL speaker output** for a 4–8 Ω internal speaker: pin 1 is `SPK+`, pin 2 is `SPK-`, and neither pin may be connected to ground.
- One common-anode RGB status LED (`C7496855`) sits centrally below the display and is sunk by unused PCF8575 P14/P15/P16 outputs through 330/100/100 Ω resistors. Its reset state is deliberately off: the expander's quasi-bidirectional outputs power up high. This is a battery-safe programming/boot/fault indicator rather than a decorative always-on LED. A rear-flanged clear acrylic/polycarbonate light pipe bridges the PCB-to-lid gap without loading the LED package. Audible firmware feedback uses the existing PAM8403/speaker path, so there is no redundant buzzer.
- Reset button and a normally-open, copper-only `JP_BOOT` solder bridge outside the landscape LCD envelope. Both are internal service controls with no front-panel opening beside the display. Bridge `JP_BOOT` for SPI-flash boot and leave it open for FEL recovery; it is DNP and has no 3D body.
- Top-side rear-edge JST-SH service connectors for standard UART programming, I²C and SPI. Their intentional X/Y positions are fixed along with every user control and external connector; only supporting components may move during layout work. The UART RX/TX paths include the standard programmer's 100 Ω MCU-side series resistors.

The LCD panel, speaker, AA contacts/springs, screws and gasket are mechanical parts and are not placed by JLCPCB. Every fitted PCB component has an explicit JLCPCB/LCSC part number and a renderable, non-placeholder 3D model; `jlc-availability.json` is the point-in-time, quantity-aware live-stock audit.

## Enclosure

The housing is native, manually authored tscircuit CAD in
`mechanical/GbaEnclosure.tsx`: 14 connected `assembly.printedpart` solids cover
the base, lid, integral-latch battery door, LCD and speaker retainers, D-pad, six face
keys and two shoulder paddles. It is not a rectangular
`enclosure.fdm.box`, a post-build Circuit JSON rewrite, or a visual-only model.
The base and lid are constant-offset extrusions of the same 18-segment
rounded/chamfered outline used by the PCB. The outside profile has 2.2 mm total
edge offset, 1.4 mm walls, 1.6 mm floor/lid and 0.8 mm horizontal PCB clearance. The
continuous base provides 15 mm beneath the PCB for the two-AA bay and rear
speaker—there is no localized add-on pod. The battery bay is centered at
(-24, 5) and provides a 32 × 57.7 × 14.5 mm cell/contact envelope. Side rails,
a low center separator, end walls and alternating contact shelves locate two
bare AA cells in series. A stepped 36.4 × 58.8 mm rear door uses a 0.9 mm
perimeter flange in the shallow 37 × 59.4 mm rebate and a 1.2 mm reinforced
centre inside the 33.6 × 56 mm through-opening. This preserves a flush,
collision-free fit without weakening the broad centre panel; its inner tongue
closes the seam and its integral cantilever latch permits tool-free replacement.

Four 3.3 mm PCB holes at (-59.5, -34), (55.5, -38), (-66, 14), and (62, 34.5)
carry M3 x 24 rear screws through the base towers and PCB, across 0.5 mm nylon
washers, and into blind heat-set inserts in the front-shell pillars.
All four bosses are outside both the battery-holder pocket and the rigid display
outline. The display does **not** load its 50-pin FPC connector or those board
supports: four additional 2.7 mm PCB holes at (-48.75, 32.75), (51, 33), (-49, -35.5),
and (66, -31) accept M2.5 screws from the PCB underside into a separate
four-point LCD carrier. Its reinforced 1.8 mm-thick routed arms and 4 mm-wide
bezel rails support the rigid OEM panel through a 0.5 mm rear gasket from
a Z=8.20 mm bearing plane while
leaving the right-side flex-fold corridor open. The upper-left boss and ledge
clear `SW_L`; the lower arms route around Select, Start and the tall `J_SPK`
body, while the long left rail is split around the full `SW_RIGHT` D-pad-switch
envelope. The open centre avoids an unnecessary non-contact spine above the
component field. An evaluated-GLB envelope scan covers every fitted PCB component and
blocks export if any carrier boss or rail intersects one. The carrier is also
mesh-checked against both enclosure shells. The lid has an 86.46 × 57.04 mm underside relief around
the complete panel, a
74.24 × 49.76 mm active-area window, and a compressed 0.50 mm closed-cell bezel
gasket so the printed lid cannot bear directly on the glass. The evaluated GLB
checks both front and rear gasket contact rather than accepting visible but
floating or embedded gasket geometry.

Every user-operated interface has an intentional opening: all twelve game
controls, the single power/data USB-C port, edge-entry microSD, left-facing
power slider, diagonal volume wheel, RGB status light pipe, and L/R shoulder controls. The battery cells,
contacts and lead are fully internal, so the enclosure has no battery-cable
opening; only the PCB has a routing slot from the under-board pocket to J_BAT.
The evaluated GLB places both L/R bore centers at 4.979 mm versus the real
actuator centers at 4.978 mm; the assembly exporter rejects more than 0.02 mm
of vertical center error so the openings cannot silently drift above the stems.
The UART, I²C and SPI programming/service JST headers are deliberately internal
and have no enclosure holes; open the enclosure to connect them. Internal ICs,
passives and `JP_BOOT` remain covered. The base also includes a 20 mm × 3.8 mm speaker cradle, cable space to
`J_SPK`, a rear acoustic grille and four molded feet that preserve a 1.6 mm
table gap. Four rear screws close the base and lid; four broad 0.8 x 1.8 mm
internal registration tongues align the butt seam before tightening.

Install the Keystone 209, 210 and 228 contacts and insulated output lead in the cradle before fitting the PCB, route
the contact lead through the PCB's 5 × 11 mm rounded edge slot, and plug it into `J_BAT`;
the surrounding enclosure wall remains closed. Fit cells only after checking polarity, then engage
the door's top tongue and snap the lower latch. Recommended first-article hardware is
four M3 x 24 closure screws, four M3 heat-set inserts and nylon washers, four
M2.5 LCD-carrier screws, and two 0.5 mm closed-cell display gaskets. The case is dimensioned CAD,
but FDM shrinkage, snap fit, screw-pilot sizing, real cable dress, shoulder feel,
and panel tolerances still require a physical prototype before production.

## Fabrication rules

- Board envelope: 144.5 × 84.27 mm, custom rounded handheld outline.
- Stack: four copper layers, 1.6 mm FR-4, 1 oz outer copper / default JLC inner copper.
- Minimum routed trace/clearance: 0.12 / 0.10 mm.
- Every signal/power via: **0.30 mm finished hole, 0.45 mm copper pad**.
- Minimum via finished-hole edge spacing: 0.20 mm.
- Battery-cable edge cut: 5 mm wide, 11 mm overall cutout length, with 9.5 mm extending into the PCB and a rounded closed end.
- MicroSD edge: no access bay or cutout; the outer edge remains at x=72.25 mm and the real TF-01A card-entry face is flush with it without extending the rigid housing beyond the PCB.
- Ground pours on all four layers; the dense processor module is routed first and reserved from carrier routing.

JLCPCB currently lists 0.30/0.45 mm vias within its multilayer capability and requires 0.20 mm via hole-to-hole spacing. Re-run the fab’s own upload DFM because fabrication capabilities and panelization decisions can change.

## Build and verify

```sh
bun install
bun run typecheck
bun run build
bun run verify
bun run check:source
bun run check:netlist
bun run check:shorts
bun run audit:jlc
bun run assembly:3d
```

`bun run verify` rejects any emitted `*_error`, any via not exactly 0.30/0.45 mm, insufficient via finished-hole spacing, missing critical hardware, missing controls, a fitted part without a JLCPCB number, or a fitted part without a non-placeholder 3D model. `check:shorts` performs the independent Gerber-mode shorts test on all copper layers. The inventory audit also requires stock to cover this board's fitted quantity. Inventory is not reserved; check it again at order time.

`bun run assembly:3d` exports `assembly/linux-gameboy-advance-assembly.glb`
from the verified Circuit JSON and rejects the result if any fitted component
body or the native enclosure is missing. The GLB contains the PCB, all fitted
component bodies, the cable-connected OEM display with folded flex, and the
native base, removable battery door, lid, and four-point LCD carrier.

## Linux bring-up

Use an F1C100S-capable U-Boot and Linux configuration. Mainline Linux supports the CPU, SPI NOR, microSD, UART, I²C/GPIO expander and USB device path; the complete LCD pipeline still normally uses the display-enabled Lichee Pi Nano/F1C100S BSP.

1. Build U-Boot/SPL for 32 MiB F1C100S DRAM and enable SPI0, MMC0, UART0 and USB FEL.
2. Include `firmware/carrier.dtsi` in the board DTS. It enables storage, console, fixed-device USB and the PCF8575 gamepad.
3. For a display-enabled BSP, adapt `firmware/display-bsp-example.dtsi` and initialize the ILI9488 over PE7–PE10 before enabling RGB scanout. Confirm the exact panel order code and timing table; the example timings are only a safe bring-up starting point.
4. Bridge `JP_BOOT` with solder for SPI-flash boot. Clear the bridge for reliable USB FEL recovery from blank/bad flash.
5. Use a 3.3 V UART adapter at 115200 8N1 on `J_UART`; its standard-programmer order is pin 1 RX, pin 2 GND, pin 3 TX.
6. The RGB indicator is exposed as `STATUS_R_N`, `STATUS_G_N`, and `STATUS_B_N` on the PCF8575 gpiochip. All three are active-low and named in `firmware/carrier.dtsi`; `firmware/rgb-demo.py` provides a libgpiod 2.x smoke test and always returns the indicator to off.

The controller appears as a normal Linux input device through `gpio-keys-polled`. The 8 ms polling interval avoids depending on GPIO-expander interrupt support in older BSP kernels.

## Display connector notes

The selected 50-pin family uses RGB666 mode straps on pins 7–9. Pins 11–14 carry VSYNC, HSYNC, DOTCLK and DE; pins 15–32 carry DB17–DB0. Pins 33–38 carry the serial-control bus used for panel initialization. Pins 44–47 are available for optional I²C touch clock/data/reset/interrupt. The board supplies 3.3 V panel logic/analog power. An AP3031 boost/current regulator drives the three series backlight LEDs at a regulated 100 mA using a 2 Ω sense network; the backlight is enabled whenever the 3.3 V rail is on.

The intended panel is the [BuyDisplay 3.5-inch IPS 320×480 capacitive-touch display](https://www.buydisplay.com/3-5-inch-ips-320x480-tft-lcd-display-capacitive-touch-screen). Its native portrait shape does not lock the Linux framebuffer to portrait: mount the panel 90° clockwise for a landscape handheld and configure the framebuffer/application rotation accordingly. In that mounting, the flex tail is on the display's right, folds/rises under the panel, and enters the bottom-contact `J_LCD` toward the left. The rigid display geometry is taken directly from the vendor STEP file and is not scaled. Its back is positioned 7 mm above the component-side PCB surface; that standoff and the flexible cable's bend path are enclosure constraints that must be checked against the first physical sample. Confirm the ordered panel's 50-pin pinout and touch option against ER-TFT035IPS-6 before fabrication, because BuyDisplay offers multiple interface options on the same product page.

## Rear service connectors

All three service headers are top-side JST-SH connectors along the top/rear PCB edge. They are internal to the closed product, with no enclosure apertures; remove the lid for programming or debug access. I²C and SPI are side-entry; UART uses the upward-entry `C160389` from the official standard-programmer package because its side-entry sibling is no longer stocked:

- `J_UART` (3-pin): RX, GND, TX. This follows the standard tscircuit JST programmer pin order.
- `J_I2C` (4-pin): GND, 3V3, SDA (PE12), SCL (PE11).
- `J_SPI` (6-pin): GND, 3V3, SCLK (PE9), MOSI (PE8), MISO (PE10), CS (PE7).

`J_SPI` intentionally exposes the same SPI1 bus used to initialize the LCD controller. Disconnect external SPI hardware during panel initialization, or guarantee that its chip-select is inactive and its MISO output is high-impedance, to avoid contention.

## Power and first-article checks

- Use two alkaline or NiMH AA cells in series. The marked board input range is 1.8–3.2 V; actual low-cell cutoff and runtime must be qualified under peak Linux/display/audio load on first articles. USB does not charge the cells, so remove NiMH cells for charging in an approved external charger. Do not fit lithium cells or attempt to charge primary alkaline cells.
- `J_USB` is the board's only USB-C receptacle: a USB 2.0 device/FEL port and standard 5 V power input. It is not a host and does not negotiate USB-PD voltages.
- Before fitting the SoC, verify the switched input and 3.3/2.5/1.2/2.8 V rails for polarity and tolerance.
- On the first assembled unit, current-limit the supply, confirm power sequencing and thermal rise, then validate the 24 MHz oscillator and UART before booting flash.
- Final USB differential impedance depends on the ordered JLCPCB four-layer stackup. Ask the fab to impedance-check the selected stackup if USB margin matters.

## References

- Tested starting point: https://tscircuit.com/seveibar/f1c100s-linux-dev-board
- Game Boy reference: https://tscircuit.com/abse/gameboy
- Earlier GBA work-in-progress: https://tscircuit.com/abse/gameboy-advance
- Standard JST programmer: https://tscircuit.com/tscircuit/standard-jst-programmer
- Official Nintendo AGB-001 manual and physical-control diagram: https://www.nintendo.com/eu/media/downloads/support_1/game_boy_advance_4/GBA_Manual_UK_DE_FR.pdf
- JLCPCB capabilities: https://jlcpcb.com/capabilities/pcb-capabilities/
- TPS63020 buck-boost product page and datasheet: https://www.ti.com/product/TPS63020
- AP3031 LED-driver datasheet: https://datasheet.lcsc.com/lcsc/1811081712_Diodes-Incorporated-AP3031KTR-G1_C82636.pdf
- ER-TFT035IPS-6 datasheet: https://www.buydisplay.com/download/manual/ER-TFT035IPS-6_Datasheet.pdf
- Intended BuyDisplay panel: https://www.buydisplay.com/3-5-inch-ips-320x480-tft-lcd-display-capacitive-touch-screen
- Energizer AA maximum dimensions: https://data.energizer.com/pdfs/nh15-2500.pdf
- Linux F1C100S pinctrl: https://github.com/torvalds/linux/blob/master/drivers/pinctrl/sunxi/pinctrl-suniv-f1c100s.c