Skip to content

LED layout interchange and traversal

The canonical traversal is short-long-baseline-v1: start at the short-edge baseline corner, ascend the short edge, descend the long edge, then follow the baseline back towards the start. V1 has no baseline segment: 6 short pixels then 12 long pixels. V2 repeats the traversal independently on the outer and inner rings; its centre belongs to neither path.

Runtime and saved settings

Both phone apps label the legacy edge count Long edge. Its stored/wire field remains outer_pixels, retaining its meaning as the long-edge length. With an 18/12 ear, indices 0–5 ascend the short edge and 6–17 descend the long edge. The last short-edge sample and first long-edge sample form the tip pair. Empty, one-pixel and straight-strip configurations remain supported. A zero/full-length long-edge count selects a straight strip and keeps its existing direction convention.

Effects operate in this single logical order. V1's optional reverse applies only when mapping the finished logical frame onto its physical strip. Fresh v1 profiles default to both unreversed for short-edge DIN. V2 has no user reversal: its immutable map assigns logical component identities to electrical offsets.

NVS schema 22 converts explicit reversal flags from schema 1–21 for split legacy ears. The conversion inverts those flags once to retain their spatial orientation under the new coordinate convention. Missing flags use current defaults; straight strips and v2 remain unchanged. The parser rejects unknown newer schemas and the existing rollback guard prohibits overwriting them. Migration remains in memory until the next ordinary settings save; no eager NVS write is added. Palette/trail travel intentionally follows the new canonical direction. Geometry-dependent tip and height effects use the new short/long split. Protocol and catalogue versions are unchanged; native apps consume the same independently editable fields.

Build-time contract

The hardware exporter publishes UTF-8 JSON with schema 2. This is separate from NVS, application protocol and catalogue schemas. Ordinary firmware builds consume an explicitly reviewed/imported copy and never open CAD or run hardware tools. The current v2 consumer supports its 48+20+1 board profile.

Required root fields:

Field Meaning
schema Integer 2; booleans are rejected
id Bounded printable layout identity, currently espurr-v2-ear-69-r2
ordering short-long-baseline-v1
source Repository, full Git commit and exact saved-board SHA-256; exporter also supplies dirty state, recipe/input hashes and evidence limits
pixels Unique stable component references with finite x_mm, y_mm LED centres, millimetres and positive Y up
paths Outer then inner closed paths, each with ordered short, long, baseline segments containing component references
centre Independent component reference, outside both paths
chains Outer then inner electrical chains, each with ordered component references and connector ref/pin/net provenance
right_transform mirror-x, retaining path direction and component identities

The segments partition each ring; paths plus centre partition all 69 components. The electrical chains independently cover every component exactly once, including the centre. For this board, chain lengths are 48 and 21. Segment endpoints define the two baseline corners and tip pair; the apex belongs to the short segment and the long-baseline corner to the long segment. Component references are identities, not array offsets. Reordering the input pixel records has no semantic effect. Changing electrical order does not change artistic geometry.

Firmware normalises XY isotropically, derives global/per-ring height and cumulative closed-path distance, mirrors the right ear, then generates immutable topology and output tables. Its semantic SHA-256 covers identities, segments, geometry, traversal and electrical routing; provenance-only changes do not change this hash. Board GPIO ownership stays in firmware. No file parsing or CAD access occurs per frame. Invalid imports fail configuration before generating usable source.

The default reviewed copy is components/board/data/v2-ear-69.json. The v2 CMake cache variable ESPURR_LED_LAYOUT can select another reviewed interchange file; normal builds use the checked-in default. Keep imports explicit and review their source hashes, dirty-state evidence and electrical maps before accepting them.

python3 tools/generate_v2_geometry.py \
  --input components/board/data/v2-ear-69.json \
  --output build/artifacts/layout/geometry.c \
  --report build/artifacts/layout/geometry.json

Optional placement/PCB-hash cross-checks remain available on the importer. Generated outputs are restricted to this firmware workspace's build/, including symlink checks. Host geometry/effect/output tests establish software contracts, not mounted ear identity, visual direction, cable continuity, current or wearable acceptance.

Public render descriptor

Catalogue schema 1.2 adds optional led_layout, layout descriptor schema 1. It is immutable build metadata within the existing authenticated, hashed/paged catalogue; ordinary property polling and NVS are unchanged. Legacy descriptors have kind:"legacy", identity espurr-legacy-outline-v1, the canonical ordering and right_transform:"mirror-x". Counts and Long edge remain live settings.

Mapped descriptors are derived by the same importer and exact selected ESPURR_LED_LAYOUT as the board C tables. They contain id, source_sha256 (the importer's semantic hash), ordering, right_transform, ordered refs, pixels, paths and centre. Each pixel tuple is [x,y,height,arc,region,flags], using the same six-decimal values as firmware. XY is isotropic, positive Y up; height and path arc are independently normalised. Region values are 0 outline, 1 outer, 2 inner, 3 independent centre; flag bits are 1 base and 2 tip. Tuple index is the logical render index and indexes refs. Paths contain logical pixels, numeric region, closed, height_min and height_max; centre is a logical index outside every path. Right-ear geometry mirrors X once while retaining identities and traversal. A front-on app display places wearer-left on viewer-right; presentation does not change logical order.

CAD provenance and electrical chain/connector records remain in the reviewed input. The descriptor does not claim measured light output or hardware acceptance. Clients without this optional extension retain normal controls. Unknown layout schemas/conventions disable simulation only; they must not be guessed from counts.