---
name: led-nameplate
description: >
  Generate a KiCad PCB that spells any name in addressable WS2812B-2020 RGB
  LEDs. Dot-font (5x9) letters are auto-placed and auto-routed with a
  clearance-aware, no-right-angle Dijkstra router; each letter is an
  independent LED string. Includes an interactive routing visualizer with a
  custom 5x9 shape editor. Use when the user wants an LED name sign / nameplate
  / light-up name PCB, a WS2812B matrix that spells text, or wants to see/iterate
  the serpentine chain routing. Trigger words: led nameplate, ws2812b nameplate,
  addressable led name sign, light up name, dot font pcb, name sign pcb, led
  matrix letters, serpentine led routing, dijkstra pcb router, routing visualizer,
  kicad nameplate generator.
---

# LED Nameplate Generator

Generates a KiCad PCB spelling any word in WS2812B-2020 LEDs, plus an
interactive routing visualizer. The tool lives at `~/apps/led-nameplate/`.

## Generate a nameplate

```bash
cd ~/apps/led-nameplate
python3 generate_nameplate.py ADONIS      # 1-10 uppercase chars (A-Z, 0-9)
```

Writes `<name>-nameplate/` with `.kicad_pcb`, `.kicad_sch`, `.kicad_pro`, and
`nameplate_config.h` (LED counts per letter for firmware). Add `--no-desktop`
to skip shipping to a desktop KiCad workspace.

## How it works (so you can extend it safely)

- **`dijkstra_alg.py` is the single source of truth for routing.** Both the PCB
  generator and the visualizer import `route_chain()` from it — never duplicate
  the algorithm. Grid is 0.5 mm; orthogonal step cost 1, diagonal √2; right
  angles (perpendicular direction changes, including diagonal⊥diagonal) are
  forbidden so traces only turn 45°.
- **Keepout** is rectangle-based: every pad + the LED body + the cap, expanded
  by 0.2 mm clearance + 0.1 mm trace-half. The template's GND vias/traces are
  fed in as extra keepout so chain bridges never short to GND.
- **Per-letter parity:** odd-position letters use the normal serpentine chain
  (top-left start); even-position letters use the *inverted* chain (bottom-left
  start) so data enters from the opposite corner — the glyph still reads upright
  because the bitmap is not mirrored, only the visitation order.
- **Net assignment is by pad number per cell** (not by template net id) — this
  avoids the collision bug where the template's shared net ids clobber under
  inverted ordering.

## Interactive routing visualizer

```bash
python3 route_server.py 7702          # serves HTML + live /api/route
# open route_visualizer.html through the container proxy on port 7702
```

- **Glyphs mode:** every A–Z / 0–9 glyph, toggle normal vs inverted chain,
  show footprint+keepout, grid, blocked nodes, chain numbering.
- **Custom Shape mode:** draw any 5×9 pattern; it routes live via the backend
  using the same `route_chain`.

`python3 route_visualizer.py` regenerates the static HTML (custom mode then
shows a "needs the server" hint).

## Verifying changes

There are two standalone audits used during development (re-create as needed):
a union-find **connectivity** check (every chain link's DOUT↔DIN physically
connected) and a **pad-clearance** check (every chain segment ≥0.2 mm from
non-connected pads). After any router change, regenerate and confirm both are
clean before shipping. Fill zones in KiCad (or via `pcbnew` `ZONE_FILLER`) to
clear zone-dependent unconnected/dangling DRC reports.
