Skip to content

Ear geometry and output mapping

This component contains bounded, allocation-free geometry helpers and descriptor validation. It has no device, settings, renderer or ESP-IDF dependencies. Board profiles supply immutable mapped geometry and physical routing separately.

EAR_TOPOLOGY_LEGACY retains the existing open-path contract. outer_pixels is the long-edge length. Logical order starts at the short-edge baseline, ascends count - outer_pixels samples, then descends the long edge. Zero or the complete count selects a straight strip. Each split edge independently spans base to tip, including duplicated tip samples and one-pixel edges. Empty and one-pixel ears retain their existing behaviour. Legacy XY describes a canonical outline, not measured physical positions.

EAR_TOPOLOGY_MAPPED supports up to 69 logical pixels per ear. Each pixel has normalised XY, height, region and path arc. Ordered path indices define logical traversal independently of array/wire order. Closed paths use arc coordinates in [0, 1) and at least three pixels; open paths allow [0, 1]. Arc coordinates increase strictly in path order. Paths have distinct region identities and cover each non-centre pixel once. At most one centre pixel is allowed, with arc zero and no path membership or base/tip flags. Optional explicit base/tip flags identify regional subsets. Optional per-path height bounds let ear_topology_path_height() span that region without stretching its physical XY; 0/0 retains global height. Empty mapped ears are valid.

Call ear_topology_valid() before publishing a descriptor. The pixel lookup checks index/pointer bounds but assumes that mapped values have already been validated. Keep the descriptor and referenced tables alive and immutable while consumers use them; no per-frame validation, allocation, file parsing or hardware access is needed.

The board-owned output map assigns each logical pixel a physical chain and offset. Validate both ears together with ear_output_map_valid() so cross-ear collisions are rejected too. Four chains, with up to 69 pixels each, are supported by this data contract. Unmapped fixed physical tails are permitted; the eventual output owner must still clear them and account for their idle draw. Physical reversal is represented in routing, never by changing artistic geometry.

The legacy renderer uses the extracted legacy height/path helpers. V2 imports PCB-derived 48+20+1 geometry, with a revision/hash identity and startup validation against the separate four-chain map. Mapped effect adapters consume these descriptors with the same canonical short-edge-first convention. The original host circular fixture stays synthetic and is not physical acceptance.

The versioned layout/export contract also describes saved-direction migration and the independent electrical map.