# CM5 Carrier Port — Status & Handoff > Handoff doc for whoever (human or LLM) continues this work. Read this first, then > `.claude/skills/kicad-port/SKILL.md` (the mandatory workflow/verify-loop), then > `CM5_Carrier_Design.md` (frozen rev-A spec). ## What this repo is Two intertwined goals: 1. **Improve Claude's EDA tooling** — the [`kicad-happy`](https://github.com/aklofas/kicad-happy) skill suite (`kicad`, `datasheets`, `spice`, …), wired in as Claude Code skills via `~/.claude/skills/{kicad,datasheets,spice} -> kicad-happy/skills/*` symlinks. The toolkit clones (`kicad-happy/`, `kicad-claude-toolkit/`, `MCP-KiCad/`) are gitignored — re-clone if missing. 2. **Port the Raspberry Pi CM5IO reference into a custom CM5 carrier board** — the real test bed (PTP/timing instrumentation node: 15V→5V front end, GbE magjack, M.2 E-key Wi-Fi (AW7915/MT7915), 2×USB-A, USB-C programming, RTC, GPS-PPS distribution). Method is **diff-from-reference**: `refs/` holds the untouched CM5IO reference; `carrier/` is the working copy. Every edit is verified against `analysis/baseline/cm5io.json`. ## Environment / tooling state (macOS, Homebrew) - `kicad-cli` ✅ (`/opt/homebrew/bin/kicad-cli`) — ERC + netlist export - `poppler` ✅ (pdftotext) — datasheet page selection - `ngspice` ✅ — `spice` skill; full verify loop validated on the reference (8 subcircuits pass) - Python ≥3.10 (Homebrew 3.14) ## The verify loop (run after EVERY schematic edit) ```bash SCH=carrier/CM5IO.kicad_sch ; KSCR=~/.claude/skills/kicad/scripts kicad-cli sch erc --exit-code-violations --format json -o /tmp/erc.json "$SCH" # hard gate python3 $KSCR/analyze_schematic.py "$SCH" -o /tmp/head.json # structural python3 $KSCR/diff_analysis.py analysis/baseline/cm5io.json /tmp/head.json --text # vs baseline ``` - **Track the ERC DELTA, not the absolute** — the reference already has 182 pre-existing violations (mostly `unconnected_wire_endpoint`). A good edit introduces **zero new types**. - The **analyzer diff is the semantic gate** (names broken design intent); **ERC is the hygiene gate**. - For kept-block integrity, also diff `kicad-cli sch export netlist` before/after — it caught a mis-inventoried part (see R8 below). ## Datasheet extraction (done) CM5 module extracted to `datasheets/extracted/SC1466_43a9ec.json` (200 pins, score 8.7/10, queryable via `~/.claude/skills/datasheets/scripts/datasheet_features.py`). Drove the NC pin lists for every strip (e.g. HDMI Module1 pins = all pins whose datasheet name starts `HDMI`). ## The strip tool: `tools/retire_block.py` General block-retirement for these s-expr sheets. Capabilities: - excise symbols by Reference; retire nets by name-glob (all label types: local / hierarchical / global) - **anchor-aware wire removal** (union-find): removes a wire only if its connected component reaches no *kept* anchor (kept non-power pin or kept label) AND is seeded by this edit — so shared nets survive and pre-existing dangles are untouched - place `(no_connect)` on exposed Module1 pins (pin coords via a validated transform `abs=(px+rot(lx,ly).x, py-rot(lx,ly).y)`, rot0/no-mirror; refuses other orientations) - clean orphaned power flags, dangling NCs, orphaned labels - `--sheet-ports NAME,...` removes root-sheet hierarchical pins + connecting wires Usage: `python3 tools/retire_block.py --symbols J7,U18 --nets 'SD_*' --nc-pins 57,61 [--sheet-ports ...] [--apply]` (dry-run without `--apply`). **Known gap (next improvement):** does NOT auto-prune orphaned power-label/wire *stubs* left after a connector is removed (e.g. leftover `+3.3v`/`HDMI_5v` labels). Those were cleaned manually — see git history. ## Strip phase — DONE (microSD + HDMI + MIPI), ERC 182 → 136, 0 new violations, 0 regressions | Block | Sheet(s) | Command(s) (run with `--apply`) | |---|---|---| | **microSD** | CM5_GPIO | `--symbols J7,U18,C5 --nets 'SD_*' --nc-pins 57,61,62,63,67,69,75` | | **HDMI** | CM5_HighSpeed | `--symbols J22,J10 --nets 'HDMI0_*,HDMI1_*,HDMI_5v' --nc-pins 143,145,146,147,148,149,151,152,153,154,158,160,164,166,170,172,176,178,182,184,188,190,199,200` | | **MIPI/camera** | CM5_HighSpeed, CM5_GPIO, CM5IO(root) | (1) HighSpeed `--symbols J5,J16 --nets 'DPHY0_*,DPHY1_*,SCL1,SDA1' --nc-pins 115,117,121,123,127,129,133,135,139,141,175,177,181,183,187,189,193,194,195,196` (2) GPIO `--nc-pins 80,82,97,100` (3) root `--sheet-ports SCL0,SDA0,CAM_GPIO0,CAM_GPIO1` (4) HighSpeed `--symbols R8 --nets 'SCL0,SDA0'` (5) manual: remove 3 orphaned +3.3v labels + 2 wire stubs | Notes that bit us (don't re-learn the hard way): - **MIPI lanes are labeled `DPHY0_*`/`DPHY1_*`, NOT `MIPI*`.** The connectors J5/J16 are camera FFCs bundling DPHY + cross-sheet I2C0 (`SCL0/SDA0`) + `CAM_GPIO0/1` — a 3-sheet hierarchical block. - **`R8` is a camera pull-up, not USB** (the Explore-agent inventory was wrong). Confirmed via `kicad-cli sch export netlist` (`R8.2 → J16.17`). Always verify inventory against the netlist. - **`SCL0/SDA0` (I2C0) are camera-only 2-node nets** (netlist-proven). NC'd to **reserve I2C0 for a future external I2C RTC** (CM5's own RTC is on-module via VBAT). If you add an external RTC, wire it here. ## Next steps 1. **Drop the PCIe-M2 sheet entirely** (NVMe M-key — not used; the M.2 **E-key** Wi-Fi will be a FRESH sheet in the add phase, per design decision). Use `--sheet-ports` for its root hierarchical pins. 2. **Re-baseline**: capture a new analyzer baseline of `carrier/` so the add phase diffs against the stripped design, not the original reference. 3. **Add phase**: 15V→5V buck front-end (reverse-protection + TVS), M.2 E-key (PCIe Gen2 ×1 + CLKREQ/PERST/RF_KILL + 3.3V), GPS connector, PPS distribution (GPS PPS → TVS → Schmitt buffer → fan-out: CM5 `Ethernet_SYNC_OUT` + 2 header taps). SPICE-validate the buck divider + PPS network. ## Out-of-repo notes Richer running notes live in this machine's Claude memory: `~/.claude/projects/-Users-noise-Documents-obsidian-rpiboard/memory/` (`project-cm5-eda`, `port-progress`, `eda-tooling-gaps`, `tooling-installs-cm5`). This doc is the portable subset.