Restructure project documentation
Separate operator guides from development contracts, relocate implementation notes under `docs/devel/`, and update cross-references and hardware tooling paths. Add getting-started, user administration, and firmware update guides while preserving firmware behavior.
This commit is contained in:
@@ -40,9 +40,13 @@ a0=OUT/'pcb-a0-before-reposition.kicad_pcb'
|
||||
a1=ROOT/'serial-carrier.kicad_pcb'
|
||||
assert sha(a0)==report['a0_snapshot_sha256'], 'A0 snapshot changed'
|
||||
assert sha(OUT/'pcb-routing-input.kicad_pcb')==report['a1_unrouted_sha256'], 'A1 routing input changed'
|
||||
# These two handoff documents are intentionally updated during A1 integration.
|
||||
# Historical reports exempt these handoff documents, updated during A1 integration.
|
||||
# Keep the legacy key exemption; new reports use ../../docs/devel/hardware/PCB/
|
||||
# pcb-draft-notes.md and that relocated note must pass the normal hash check.
|
||||
intentional_updates=[name for name in ('README.md','pcb-draft-notes.md')
|
||||
if name in report['protected_file_sha256']]
|
||||
protected={name:digest for name,digest in report['protected_file_sha256'].items()
|
||||
if name not in ('README.md','pcb-draft-notes.md')}
|
||||
if name not in intentional_updates}
|
||||
for name,digest in protected.items():
|
||||
assert sha(ROOT/name)==digest, 'protected file changed: '+name
|
||||
old,new=parse(a0),parse(a1)
|
||||
@@ -88,7 +92,7 @@ assert [x for x in old if isinstance(x,list) and x[0]=='net']==[x for x in new i
|
||||
assert not (ROOT/'~serial-carrier.kicad_pcb.lck').exists(), 'PCB reopened before handoff'
|
||||
result=dict(a0_snapshot_unchanged=True,a1_unrouted_snapshot_unchanged=True,
|
||||
protected_files_unchanged=list(protected),
|
||||
intentional_documentation_updates=['README.md','pcb-draft-notes.md'],
|
||||
intentional_documentation_updates=intentional_updates,
|
||||
cad_projection_graphics=len(cad_owned),
|
||||
footprints_identical_except_authorized_placement=True,
|
||||
footprint_count=len(old_fp),unrelated_board_graphics_preserved=len(unchanged_old),
|
||||
|
||||
@@ -69,10 +69,14 @@ def main():
|
||||
before=PCB.read_bytes()
|
||||
assert before==BACKUP.read_bytes(), 'current board differs from A0 snapshot; refusing migration'
|
||||
protected=[ROOT/name for name in ('serial-carrier.kicad_pro','serial-carrier.kicad_sch',
|
||||
'serial-carrier.kicad_prl','README.md','pcb-draft-notes.md','fp-lib-table',
|
||||
'serial-carrier.kicad_prl','README.md','fp-lib-table',
|
||||
'sym-lib-table','Carrier.kicad_sym')]
|
||||
protected+=list((ROOT/'Carrier.pretty').glob('*'))
|
||||
hashes={str(path.relative_to(ROOT)):sha(path) for path in protected if path.is_file()}
|
||||
# Keep report keys relative to ROOT, including the relocated, required note.
|
||||
# Do not silently omit it through the optional project-file filter above.
|
||||
notes='../../docs/devel/hardware/PCB/pcb-draft-notes.md'
|
||||
hashes[notes]=sha(ROOT/notes)
|
||||
board=p.LoadBoard(str(PCB))
|
||||
immutable=normalized_footprints(board)
|
||||
net_table=identity(board)[-1]
|
||||
|
||||
@@ -1,253 +0,0 @@
|
||||
# A1 top-left-notch / bottom-USB routing — current result
|
||||
|
||||
Date: 2026-09-21. Actual revised board: `../serial-carrier.kicad_pcb`.
|
||||
|
||||
**38/38 connections across 17 multi-pad nets; 0 physical DRC violations,
|
||||
0 unconnected items; exactly 1 expected U2 footprint parity warning.**
|
||||
The warning is the board-only `Carrier:MAX3243_Reference_Provisional` assignment
|
||||
versus the intentionally blank schematic footprint, not a net mismatch.
|
||||
|
||||
## Geometry and preservation
|
||||
|
||||
Coordinates below are local to absolute origin (100,100) mm; all dimensions mm.
|
||||
|
||||
- Carrier: 82 x 80, outline `[(36,0),(82,0),(82,80),(0,80),(0,19),(36,19)]`.
|
||||
- U1 origin: (8,23), formerly (8,4). Header end-pad centres now Y=76.340;
|
||||
USB guide Y=83 is 3 mm below the bottom edge. No ESP32 body was invented.
|
||||
- U2 origin: (43,26.670), formerly (43,30). Actual reference F.Fab bare-PCB
|
||||
front edge is absolute Y=100.000, flush with carrier local Y=0.
|
||||
- Nominal male metal external dimensions are user-confirmed: shell overhang
|
||||
3.870, hex-mouth overhang 2.870, flange front 1.930 behind the carrier edge.
|
||||
With this placement their local Y positions are -3.870, -2.870 and +1.930.
|
||||
Integration added seven board-local Dwgs.User graphics for the CAD metal
|
||||
projections and screw-lock axes.
|
||||
- H1: (3.5,22.5), H2: (3.5,75). H3/H4 unchanged at (78,4)/(78,76).
|
||||
- OLED, resistors and switches unchanged.
|
||||
- RF reserve: local X=10..31 / Y=19..32, absolute X=110..131 / Y=119..132,
|
||||
both layers; no tracks, vias or fills inside it. Boundary remains provisional.
|
||||
|
||||
The existing A0 board was mutated, **not regenerated**. The one-time
|
||||
`pcb-a0-before-reposition.kicad_pcb` backup remains byte-for-byte intact.
|
||||
`pcb-routing-input.kicad_pcb` is now the A1 unrouted audit input, not A0.
|
||||
`pcb-routing-preservation.py` verified all 13 complete serialized footprints
|
||||
identical except the four authorized top-level placements, including schematic
|
||||
fields, pad/net definitions, electrical UUID paths and all footprint graphics.
|
||||
Non-owned board-graphic UUIDs and unrelated graphics are preserved. ESP/RS/RF
|
||||
annotations moved with placement; the post-routing silkscreen refresh replaced
|
||||
91 owned graphics. Its edge clipping avoids silk across U2's flush front edge.
|
||||
|
||||
All board saves used `SaveBoard(..., True)`. Project `.pro`, `.prl`, schematic,
|
||||
symbol/footprint libraries and library tables retain their original hashes.
|
||||
README and pcb-draft-notes were intentionally updated during integration. The generator's constants/text were updated but it was **not
|
||||
run**; its automatic project/netclass writes were removed. PCB Editor lock was
|
||||
absent at migration, routing, silkscreen refresh and final preservation check.
|
||||
|
||||
## Routing and independent measurements
|
||||
|
||||
- F.Cu/B.Cu; **565 segments, 22 through vias**.
|
||||
- **451 signal segments at 0.25 mm; 114 +3V3/GND segments at 0.5 mm**.
|
||||
- Vias: 0.7 mm copper / 0.3 mm drill. No copper pours needed.
|
||||
- Continuous measured minimum different-net/NPTH clearance: **0.270544 mm**.
|
||||
- Minimum copper/NPTH-to-edge gap: **1.900 mm**.
|
||||
- Minimum copper/NPTH-to-RF-reservation gap: **0.025 mm**.
|
||||
- Minimum via-drill edge to other drilled-hole edge: **0.820544 mm**.
|
||||
|
||||
Two bounded passes, each with 240 seconds / 1,200,000 expansions per search:
|
||||
|
||||
1. 31.18 seconds, 38/38, 674 segments / 16 vias, physical DRC clean. One GND
|
||||
connection required the router's 0.25 mm fallback; strict width validation
|
||||
correctly failed. Retained as `pcb-routing-a1-pass1.kicad_pcb` for evidence.
|
||||
2. 32.44 seconds, 38/38, 565 segments / 22 vias. Short GND connections (<=15 mm)
|
||||
now route before longer signal fanout; long GND links remain last. All power
|
||||
and ground now use 0.5 mm; no fallback. This is the saved current result.
|
||||
|
||||
The grid remains 0.05 mm, physical clearance 0.25 mm plus 0.02 mm routing margin.
|
||||
No rip-up/unbounded retry or external network router was used.
|
||||
|
||||
## Validation / rerun commands
|
||||
|
||||
From `hardware/PCB`:
|
||||
|
||||
```sh
|
||||
/usr/bin/python3 -B validate_pcb_draft.py
|
||||
/usr/bin/python3 -B validation/pcb-routing-check.py
|
||||
/usr/bin/python3 -B validation/pcb-routing-preservation.py
|
||||
kicad-cli pcb drc --format json --all-track-errors --severity-all --exit-code-violations -o validation/pcb-routing-all-drc.json serial-carrier.kicad_pcb
|
||||
```
|
||||
|
||||
All passed on A1. Validators perform fresh KiCad DRC, fresh schematic-netlist
|
||||
comparison, geometry checks, continuous copper-distance checks, and routing
|
||||
save-refusal tests. DRC was read-only to preserve project settings; no copper
|
||||
zones exist to refill. Existing ignored DRC checks were not changed; see reports.
|
||||
The preservation audit includes the intentional documentation updates and seven
|
||||
CAD projection graphics while retaining electrical and project preservation checks.
|
||||
|
||||
Rerouting remains explicitly destructive to existing/manual copper and requires:
|
||||
|
||||
```sh
|
||||
/usr/bin/python3 -B route_pcb_draft.py --route --overwrite --replace-routes --seconds 240 --max-expansions 1200000
|
||||
/usr/bin/python3 -B add_device_silkscreen.py
|
||||
```
|
||||
|
||||
Then rerun the validators. The one-shot `pcb-routing-reposition.py --apply`
|
||||
refuses anything except the original A0 snapshot and must **not** be rerun on A1.
|
||||
|
||||
Current evidence: `pcb-routing-a1-pass2.log`, `pcb-routing-run.json`,
|
||||
`pcb-routing-drc.json`, `pcb-routing-all-drc.json`, `pcb-parity-drc.json`,
|
||||
`pcb-validation-summary.json`, `pcb-routing-check.json`,
|
||||
`pcb-routing-reposition.json`, and `pcb-routing-preservation.json`.
|
||||
The current post-integration board SHA-256 is recorded in
|
||||
`pcb-routing-check.json`; the CAD projection additions do not change copper.
|
||||
|
||||
**Still a draft, not fabrication-ready.** ESP32 geometry/antenna/USB access,
|
||||
module pinout/header fit, full assembly/height clearances, power integrity and
|
||||
hardware operation remain unqualified. Nominal RS-232 metal dimensions alone
|
||||
are not assembly qualification. Placement PDF, SVG/PNG and carrier-only 3D
|
||||
preview were refreshed after CAD envelope integration. No Gerbers generated.
|
||||
|
||||
---
|
||||
|
||||
# Historical A0 routing result — superseded by A1 above
|
||||
|
||||
The following records the earlier A0 routing/integration. Its dimensions, counts,
|
||||
measurements and no-save reproduction do not describe current A1. A0 `pass1`,
|
||||
`pass2`, `pass3`, `baseline` and `dry-run` files are historical; use the A1 and
|
||||
current reports listed above.
|
||||
|
||||
Date: 2026-09-20. KiCad 10.0.6; system `/usr/bin/python3`.
|
||||
|
||||
## Saved result
|
||||
|
||||
Actual copper routing is saved in `../serial-carrier.kicad_pcb`, not just a preview
|
||||
or an exported proposal. **38/38 required spanning-tree connections across 17
|
||||
multi-pad nets routed; KiCad reports 0 unconnected items, 0 errors, 0 warnings.**
|
||||
Intentional single-pad `unconnected-(...)` nets retain their original names and
|
||||
are not connected to anything else.
|
||||
|
||||
- Two copper layers, F.Cu and B.Cu.
|
||||
- 569 straight track segments: 425 at 0.25 mm for signals and 144 at 0.5 mm for
|
||||
+3V3/GND. No narrow power-track fallback was necessary.
|
||||
- 20 through vias, 0.7 mm copper diameter / 0.3 mm drill.
|
||||
- No copper pours: all ground connections were routed explicitly.
|
||||
- Original RF rule area, x110..131 / y100..113 mm on both copper layers, preserved.
|
||||
No tracks, vias or fills enter the reservation. Minimum copper-to-reservation
|
||||
gap measured independently is 0.025 mm; this is geometric compliance with the
|
||||
specified provisional boundary, **not validation of an antenna's RF needs**.
|
||||
- All 9 electrical footprints and 4 standalone mounting footprints preserved.
|
||||
Pad positions, shapes, sizes, drills, types, nets, functions, pin types and UUIDs;
|
||||
footprint placement, orientation, library IDs, values, UUIDs and schematic UUID
|
||||
paths; net table, outline and RF rule-area geometry/flags match the input.
|
||||
- Generator, README, schematic, project and libraries were not edited by routing.
|
||||
No external network dependency or manufacturing exports were used.
|
||||
|
||||
## Validation performed
|
||||
|
||||
From `hardware/PCB`:
|
||||
|
||||
```sh
|
||||
kicad-cli pcb drc --format json --refill-zones --save-board -o validation/pcb-routing-drc.json serial-carrier.kicad_pcb
|
||||
kicad-cli pcb drc --format json --all-track-errors --severity-all --exit-code-violations -o validation/pcb-routing-all-drc.json serial-carrier.kicad_pcb
|
||||
/usr/bin/python3 -B validation/pcb-routing-check.py
|
||||
```
|
||||
|
||||
Both DRC runs: **0 violations and 0 unconnected items**. No DRC settings or
|
||||
exclusions were added or changed. Existing project rules specify 0.25 mm minimum
|
||||
clearance, 0.5 mm copper-edge clearance, 0.25 mm minimum track width and 0.7 mm
|
||||
minimum via diameter.
|
||||
|
||||
Independent continuous-geometry audit (`pcb-routing-check.json`):
|
||||
|
||||
| Check | Measured minimum | Requirement |
|
||||
|---|---:|---:|
|
||||
| Different-net copper / copper-to-NPTH clearance | 0.275 mm | 0.25 mm |
|
||||
| Copper or NPTH edge to board edge | 0.525 mm | 0.5 mm |
|
||||
| Copper / NPTH edge to RF reserve | 0.025 mm | No intersection |
|
||||
| Via drill edge to another drilled hole edge | 0.840175 mm | 0.25 mm |
|
||||
|
||||
The audit uses exact straight-line/point/rectangle distance calculations with
|
||||
copper radii, rather than the router's raster masks. It also verifies dimensions,
|
||||
source-preservation invariants, and three overwrite-refusal cases. Requires
|
||||
locally installed `pcbnew`, NumPy and Shapely; the router itself only needs
|
||||
`pcbnew` and NumPy.
|
||||
|
||||
DRC still honors the project's pre-existing ignored checks:
|
||||
`missing_courtyard`, `track_not_centered_on_via`,
|
||||
`tuning_profile_track_geometries`, `footprint_filters_mismatch`, and
|
||||
`footprint_type_mismatch`. `--severity-all` does not enable ignored checks.
|
||||
The routing subtask compared electrical UUID linkage and pad-net assignments
|
||||
with the input board. Subsequent integration also ran fresh schematic-parity DRC
|
||||
and added missing symbol metadata fields to the PCB without changing copper.
|
||||
That check reports exactly one expected U2 footprint warning (provisional PCB
|
||||
footprint versus intentionally blank schematic assignment); no net mismatch.
|
||||
See `pcb-parity-drc.json` and `pcb-validation-summary.json`.
|
||||
|
||||
## Method and bounded passes
|
||||
|
||||
`../route_pcb_draft.py` uses a two-layer 8-direction raster A* search, an explicit
|
||||
via cost, exact-pad-centre terminal stubs, conservative foreign-copper and hole
|
||||
obstacles, and only collinear path compression. It preserves the L-shaped edge
|
||||
and RF reservation. Per-net minimum spanning trees connect every physical pad,
|
||||
including duplicate switch contacts; short links precede longer links and GND is
|
||||
last. It does not optimize return-current paths, topology or total via count.
|
||||
|
||||
1. Initial 0.1 mm raster / 0.04 mm safety margin / 250,000 expansions per search:
|
||||
29/38 connections; DRC 0 violations, 9 unconnected.
|
||||
2. Increased search allowance to 1,200,000 expansions: 30/38; DRC 0 violations,
|
||||
8 unconnected. Some raster header passages were blocked, not just expensive.
|
||||
3. Final 0.05 mm raster / 0.02 mm additional safety margin, with 0.25 mm physical
|
||||
clearance unchanged: 38/38 in approximately 26.5 seconds; DRC fully connected.
|
||||
Each pass had a 240-second routing deadline. No unresolved routing remains.
|
||||
|
||||
A KiCad Python binding ownership problem in the first replacement attempt caused
|
||||
an exception/segfault before any board save. Replacement now uses `board.Delete`
|
||||
instead of `board.Remove`; the subsequent save and no-save rerun both passed.
|
||||
The known startup PROPERTY_ENUM assertions do not prevent validation.
|
||||
|
||||
## Rerun safety
|
||||
|
||||
By default the script never saves. The existing routed board is protected even
|
||||
from a preview unless `--replace-routes` is given. A preview can be run with:
|
||||
|
||||
```sh
|
||||
/usr/bin/python3 -B route_pcb_draft.py --replace-routes --seconds 240
|
||||
```
|
||||
|
||||
This exact no-save workflow was tested: it again found 38/38 connections, 569
|
||||
segments and 20 vias, and left the board byte-for-byte unchanged.
|
||||
|
||||
**The following command discards all existing/manual tracks and vias**, then
|
||||
replaces them with fresh draft routing. Back up manual work first:
|
||||
|
||||
```sh
|
||||
/usr/bin/python3 -B route_pcb_draft.py --route --overwrite --replace-routes --seconds 240 --max-expansions 1200000
|
||||
```
|
||||
|
||||
The script refuses a PCB-editor lock, unexpected outline/RF/board structure,
|
||||
unsupported pad orientation/layers, unapproved existing routes, or detected board
|
||||
changes before save. Candidate serialization must preserve immutable geometry
|
||||
and linkage before replacing the board. It deliberately does not run DRC itself:
|
||||
rerun the validation commands after any routing change. Runtime/expansion limits
|
||||
can produce a partial board; inspect both the run report and actual DRC, not just
|
||||
the script exit status.
|
||||
|
||||
## Evidence and remaining limitations
|
||||
|
||||
- `pcb-routing-input.kicad_pcb`: unrouted input snapshot, after baseline DRC save.
|
||||
- `pcb-routing-baseline.json`: 38 unconnected / no violations before routing.
|
||||
- `pcb-routing-pass1-drc.json`, `pcb-routing-pass2-drc.json`: intermediate DRC.
|
||||
- `pcb-routing-pass2.log`, `pcb-routing-pass3.log`: bounded routing progress.
|
||||
- `pcb-routing-run.json`: final saved-route metrics and connection list.
|
||||
- `pcb-routing-drc.json`, `pcb-routing-all-drc.json`: final KiCad DRC evidence.
|
||||
- `pcb-routing-check.py`, `pcb-routing-check.json`: repeatable independent audit.
|
||||
- `pcb-routing-dry-run.log`: successful final no-save reproduction.
|
||||
|
||||
Routing-only DRC-saved snapshot SHA-256 (before integration copied schematic
|
||||
metadata fields): `bf94b6c9b00c43a97f933054758a2c9d6541981ae09f2f285dcdb567bd73d9b1`.
|
||||
The current post-integration hash is recorded by `pcb-routing-check.json`;
|
||||
geometry, pad-net linkage and copper are unchanged by the metadata copy.
|
||||
|
||||
**Still DRAFT / NOT FOR FABRICATION.** Provisional module/connector geometry,
|
||||
antenna envelope, assembly/courtyard clearances, USB access, male RS-232 connector
|
||||
fit, physical pin mapping, power integrity, EMI and hardware operation are not
|
||||
qualified by routing or DRC. All previously documented mechanical/electrical
|
||||
release gates remain. No physical-device or manufacturing validation performed.
|
||||
Reference in New Issue
Block a user