Skip to main content

PCB Design — JLCPCB PCBA

Custom 4-layer PCB designed for fabrication and assembly by JLCPCB. Maximum components assembled on-board to minimize manual soldering.

PCB Renders

3D Raytraced Renders

Photorealistic renders generated by KiCad 10 raytracer with 3D component models.

Top Side (F.Cu)Bottom Side (B.Cu)
PCBA TopPCBA Bottom
Isometric FrontIsometric Back
PCBA Iso FrontPCBA Iso Back
ESP32 DetailBottom Isometric
ESP32 DetailPCBA Iso Bottom

Interactive 3D Viewer

Open interactive 3D PCB viewer — rotate, zoom, explode view, top/bottom toggle.

Board Specifications

ParameterValue
Dimensions160 × 75 mm
Layers4 (F.Cu, In1.Cu GND, In2.Cu Power, B.Cu)
Thickness1.6 mm
Surface FinishENIG (gold)
Corner Radius6 mm
FPC Slot3 × 24 mm vertical cutout (40-pin ribbon pass-through)
Mounting Holes6× M2.5 (matches 3D enclosure)

Layer Stackup

LayerFunction
F.Cu (Top)Face buttons, menu button, charging LEDs
In1.CuFull GND copper pour
In2.Cu+3V3 / +5V power plane
B.Cu (Bottom)ESP32, ICs, connectors, passives, L/R shoulder buttons

Component Placement

Top Side (F.Cu) — User-facing

  • 11× SMT tact switches — D-pad (left), ABXY (right), Start/Select
  • SW13 Menu button — bottom right
  • LED1, LED2 — charging indicators (bottom left)
  • ILI9488 3.95" bare LCD panel sits on top (FPC ribbon passes through slot to J4 on back)

FPC Slot & Pin Reversal

  • 3 × 24 mm vertical cutout between display area and ABXY buttons
  • Allows the 40-pin FPC ribbon cable to pass from top (display) to bottom (J4 connector)
  • Located at x=127mm from left edge, vertically centered with display
  • Pin reversal: the display in landscape (CCW rotation) has Pin 1 at the south end of the FPC tail. The cable passes straight through the slot without twisting, so display Pin N contacts connector Pad (41−N). All PCB traces account for this reversal.

Bottom Side (B.Cu) — Electronics

  • SW11, SW12 — L/R shoulder buttons (top edge, rotated 90°)
  • U1 ESP32-S3-WROOM-1 — center
  • U2 IP5306 (eSOP-8) — charger + boost, left-center area
  • U3 AMS1117-3.3 (SOT-223) — 3.3V LDO, below center
  • U5 PAM8403 (SOP-16) — audio amp, left area
  • L1 1µH inductor — near IP5306
  • J1 USB-C — bottom center
  • U6 Micro SD slot — bottom right (VCC/GND connect via vias to inner power planes)
  • J4 FPC 40-pin 0.5mm — right of FPC slot (display ribbon, ILI9488)
  • J3 JST PH 2-pin — battery connector, center
  • SW_PWR — power slide switch, left edge
  • SPK1 — 22mm speaker, left area
  • C21-C25, R20-R21 — PAM8403 passives (near U5)
  • 26× passives — organized in 2 centered rows below ESP32

Bill of Materials (BOM)

JLCPCB-Assembled Components

RefComponentLCSCTypeQty
U1ESP32-S3-WROOM-1-N16R8C2913202Extended1
U2IP5306 charger+boostC181692Extended1
U3AMS1117-3.3 LDOC6186Basic1
U5PAM8403 audio ampC5122557Extended1
J1USB-C 16-pinC2765186Extended1
U6Micro SD slot (TF-01A)C91145Extended1
J4FPC 40-pin 0.5mm (display)C2856812Extended1
J3JST PH 2-pin (battery)C173752Extended1
L11µH inductor 4.5AC280579Extended1
LED1Red LED 0805 (charging)C84256Basic1
LED2Green LED 0805 (full)C19171391Basic1
R1-R25.1k 0805C27834Basic2
R3-R15,R1910k 0805C17414Basic14
R16100k 0805C149504Basic1
R17-R181k 0805 (LED)C17513Basic2
R20-R2120k 0805 (PAM8403)C4184Basic2
C3-C16,C20,C21100nF 0805C49678Basic16
C220.47µF 0805 (PAM8403)C1571Basic1
C23-C251µF 0805 (PAM8403)C15849Basic3
C1,C17,C1810µF 0805C15850Basic3
C2,C1922µF 1206C29632Basic2
SW1-SW13SMT tact switchC318884Extended13
SW_PWRSlide switch SS-12D00G3C431540Extended1
SPK122mm speaker padsManual1

Manual Assembly — Buy Separately

These components are NOT provided by JLCPCB and must be purchased from AliExpress (see BOM):

ComponentBuyConnectionSoldering
LiPo 3.7V 5000mAh (105080)~$6-8Plug into JST PH connector (J3)No — plug-in connector
ILI9488 3.95" bare LCD panel (40P FPC, touch NC)~$3.95Insert 40-pin FPC ribbon into J4 connector, close latchNo — plug-in FPC
28mm 8Ω speaker~$0.80Solder 2 wires to pads on PCBYes — 2 solder points
PSP joystick (removed)Removed — GPIOs reassigned to USB data and BTN_R
Display purchase

Buy the bare LCD panel (NOT a module with PCB breakout):

  • ILI9488 3.95" 320×480, 40-pin FPC 0.5mm pitch
  • Resistive touch (not connected on PCB)
  • AliExpress
  • The FPC ribbon slides into J4 and locks — zero soldering.

JLCPCB Ordering

Files Needed

All production files are pre-packaged in the release_jlcpcb/ folder at the project root (v1.6, 2026-02-21):

  1. Gerber ZIPrelease_jlcpcb/gerbers.zip (ready to upload, inner layers with zone fill)
  2. BOM.csvrelease_jlcpcb/bom.csv (71 components)
  3. CPL.csvrelease_jlcpcb/cpl.csv (71 component placements)

Order Settings

  • Layers: 4
  • PCB Qty: 5
  • Thickness: 1.6mm
  • Surface Finish: ENIG
  • Assembly: Both sides
  • Tooling holes: Added by JLCPCB

Estimated Cost (5 boards)

ItemCost
PCB fabrication (4-layer)~$20
SMT setup + extended fees~$35
Components~$35
Total~$90 (~$18/board)

Schematic Architecture

The design uses a hierarchical schematic with a root file referencing 7 sub-sheets:

SheetFileComponents
Rootesp32-emu-turbo.kicad_sch7 sheet references
101-power-supply.kicad_schUSB-C, IP5306, AMS1117, battery, LEDs, power switch
202-mcu.kicad_schESP32-S3 + decoupling
303-display.kicad_schILI9488 bare panel + FPC 40-pin connector (J4)
404-audio.kicad_schPAM8403 + speaker (SPK1)
505-sd-card.kicad_schMicro SD SPI interface
606-controls.kicad_sch13 buttons + pull-ups + debounce caps
707-usb-data.kicad_schNative USB data (D-/D+, firmware flash + debug)

Total: 75 unique component references across all sheets, 72 assembled by JLCPCB.

Generation

# Generate schematics (7 sheets + root)
python3 -m scripts.generate_schematics hardware/kicad

# Generate PCB + JLCPCB exports
make generate-pcb

# Render PCB images
make render-pcb

# Verify schematic/PCB/JLCPCB consistency
python3 scripts/verify_schematic_pcb.py

Output files:

  • hardware/kicad/esp32-emu-turbo.kicad_sch — Hierarchical root schematic
  • hardware/kicad/01-07-*.kicad_sch — 7 sub-sheet schematics
  • hardware/kicad/esp32-emu-turbo.kicad_pcb — KiCad PCB layout
  • hardware/kicad/jlcpcb/cpl.csv — Component Placement List (72 parts)

Routing Architecture

All traces use Manhattan (orthogonal) routing — horizontal segments on F.Cu, vertical segments on B.Cu, with vias at every direction change.

Trace Widths

CategoryWidthNets
Power0.5mmVBUS, +5V, +3V3, BAT+, GND returns
Signal0.25mmButtons, passives
Data0.2mmDisplay bus, SPI, I2S, USB
Audio0.3mmPAM8403 → speaker

SPI Bus Routing (v1.3 fix)

SD_MOSI and SD_MISO originally ran as long horizontal traces on F.Cu (~45mm, from ESP32 to SD card), crossing the FPC approach zone where LCD data bus and button traces also run on F.Cu. This caused 3 trace shorts:

ShortCause
SD_MOSI (y=32.58) ↔ LCD_D4 (y=32.75)Parallel traces within 0.2mm on F.Cu
SD_MOSI (y=32.58) ↔ BTN_Y (y=32.5)Parallel traces within 0.2mm on F.Cu
SD_MISO (y=33.85) ↔ LCD_D6 (y=33.75)Parallel traces within 0.2mm on F.Cu

Fix: SD_MOSI and SD_MISO now use B.Cu vertical bypass columns at x=120 and x=118 respectively. The traces drop to B.Cu before the conflict zone, run vertically to the SD card y-level, then continue on F.Cu to the SD card pins. SD_CLK and SD_CS were unaffected and use the direct route.

Inner Layer Power Planes

LayerNetCoverageZone Priority
In1.CuGNDFull board0
In2.Cu+3V3Full board (base)0
In2.Cu+5VCenter-right (100-140, 35-65)1 (higher)

The +5V island on In2.Cu covers the IP5306/AMS1117/L1 area. Priority 1 ensures +5V wins in the overlap region. Components outside this area connect to +3V3 via the base zone.

Zone Fill Pipeline

The Python PCB generator creates zone boundaries but does not fill them — zone fill requires the KiCad pcbnew API. The make export-gerbers pipeline runs kicad_fill_zones.py via Docker before exporting Gerber files, ensuring inner layers contain full copper pour data.

Pre-Production Verification

All automated checks passed before JLCPCB production order (v1.6, 2026-02-21):

Short Circuit Analysis — PASS

CheckResult
Trace Shorts✅ PASS (0 shorts)
Zone Fill Data✅ PASS (7 filled polygons)
Zone Priorities✅ PASS
Gerber File Sizes✅ PASS (In1_Cu=243KB, In2_Cu=260KB)

Script: python3 scripts/short_circuit_analysis.py

DRC (Design Rule Check) — PASS

RuleJLCPCB MinOur DesignStatus
Trace width0.09mm0.2mm (signal), 0.5mm (power)PASS
Trace spacing0.09mm0.2mmPASS
Via drill0.15mm0.2mmPASS
Via pad0.35mm0.35–0.46mmPASS
Annular ring0.075mm0.075–0.13mmPASS
Board edge clearance0.3mm0.5mmPASS

DRC Engine: KiCad native DRC with JLCPCB custom rules (hardware/kicad/esp32-emu-turbo.kicad_dru)

Script: python3 scripts/drc_native.py --run (zone fill + DRC + smart analysis)

Electrical Simulation — PASS (6 warnings)

Power Budget:

  • +3V3 rail: 335mA max / 800mA capacity (42% utilization)
  • +5V rail: 387mA max / 2.4A capacity (16% utilization)
  • AMS1117 thermal: 0.57W dissipation, Tj=91°C (safe)
  • Battery life: 11.8h typical, 8.6h heavy use (5000mAh LiPo)

Signal Timing:

  • Display 8080 bus: 18.4 MB/s required, 20 MB/s available (8% margin)
  • SPI SD card: 6MB ROM loads in 1.3s
  • I2S audio: 32kHz SNES rate, BCLK 1.024MHz (ESP32 max 8MHz)
  • Button debounce: RC = 1.0ms (acceptable range 1-10ms)

Component Values:

  • USB-C CC pull-down: R1,R2 = 5.1kΩ (USB-C spec: 4.7k-5.6k) ✓
  • LED current: 1.1-1.3mA (safe, visible) ✓
  • Pull-up logic: 3.3V > Vih 2.475V ✓
  • Decoupling caps present near all ICs ✓

GPIO Mapping:

  • 35/45 GPIOs used, no conflicts with PSRAM (GPIO 26-32)
  • Strapping pins documented (GPIO0, GPIO3, GPIO45, GPIO46)
  • GPIO19/20 used for native USB data (D-/D+); GPIO43 reassigned from TX0 to BTN_R

Script: python3 scripts/simulate_circuit.py

Schematic/PCB Consistency — PASS

  • All 71 JLCPCB CPL components matched between schematic, PCB, and CPL
  • 3 off-board components excluded: battery (BT1), display module (U4), speaker (SPK1)
  • PCB: 431 trace segments, 260 vias, 45 nets, 78 footprints

Script: python3 scripts/verify_schematic_pcb.py

Run All Verifications

# All checks in one command
make verify-all

# Or individually:
python3 scripts/drc_native.py --run # JLCPCB DRC with smart analysis
python3 scripts/simulate_circuit.py # Electrical verification
python3 scripts/verify_schematic_pcb.py # Schematic/PCB consistency
python3 scripts/short_circuit_analysis.py # Short circuits + zone fill

# Export Gerbers with zone fill (requires Docker)
make export-gerbers

DRC Improvements (Feb 2026):

  • Integrated JLCPCB custom .kicad_dru rules (4-layer, standard vias)
  • Smart violation categorization (known-acceptable vs real issues)
  • Baseline tracking for delta detection (regression prevention)
  • Source file mapping with fix suggestions for real issues
  • Reduced critical violations from 186 → 10 borderline clearance issues (0.032-0.085mm vs 0.09mm JLCPCB min)
  • Fixed 8 unconnected items in power routing (VBUS, +5V, +3V3, BAT+, LX nets)

v2 PCB — Audio Coprocessor

The v2 revision adds an ESP32-S3-MINI-1-N8 audio coprocessor to the bottom side of the PCB. See Phase 5 — Software Architecture for the full rationale.

v2 Component Placement

RefComponentSideLocationNotes
U7ESP32-S3-MINI-1-N8B.Cu (bottom)Near PAM8403 (left area)SPI slave + I2S output
C26,C27100nF 0805B.Cu (bottom)Adjacent to U7Decoupling

v2 Routing Changes

Connectionv1v2
GPIO 15 (main ESP32)I2S_BCLK → PAM8403SPI_CLK → U7 (MINI-1)
GPIO 16 (main ESP32)I2S_LRCLK → PAM8403SPI_MOSI → U7 (MINI-1)
GPIO 17 (main ESP32)I2S_DOUT → PAM8403SPI_MISO ← U7 (MINI-1)
GPIO 20 (main ESP32)USB_D+ (native USB)SPI_CS → U7 (MINI-1)
U7 GPIO 15I2S_BCLK → PAM8403
U7 GPIO 16I2S_LRCLK → PAM8403
U7 GPIO 17I2S_DOUT → PAM8403

The PAM8403 audio amplifier input changes from the main ESP32-S3 to the MINI-1 coprocessor. The I2S bus traces from U7 to U5 (PAM8403) are short and direct since both are on the bottom side in the left area.

v2 Schematic Architecture

SheetFileComponents
Rootesp32-emu-turbo.kicad_sch8 sheet references
1–7(same as v1)(same as v1)
808-audio-coprocessor.kicad_schESP32-S3-MINI-1-N8 + decoupling

v2 Total: 78 unique component references, 75 assembled by JLCPCB.


Next Steps

v1 (current)

  1. Upload release_jlcpcb/gerbers.zip to jlcpcb.com
  2. Upload release_jlcpcb/bom.csv and release_jlcpcb/cpl.csv for SMT assembly
  3. Order 5× PCBs with SMT assembly (72 components)
  4. Buy off-board components: bare LCD panel (40P FPC), LiPo battery, speaker (see table above)
  5. Manual assembly: plug battery into J3, insert 40-pin FPC into J4, solder speaker wires

v2 (audio coprocessor)

  1. Add ESP32-S3-MINI-1-N8 to KiCad schematic (Sheet 8) and PCB layout
  2. Re-route I2S traces from U7 to U5 (PAM8403), SPI traces from U1 to U7
  3. Re-export Gerbers, BOM, and CPL for JLCPCB
  4. Order v2 PCBs with 75 assembled components
  5. Flash coprocessor firmware via separate USB connection or SPI bootloader