Slow sensing ownership¶
sensing owns the two v2 LTR-F216A band sensors at seven-bit address 0x53
and two AW96105DNR ear sensors at 0x12, on board-owned I2C0 (left) and I2C1
(right). The four physical interrupt pins are unused.
ESPURR_SENSING defaults on only for v2; disabled/legacy profiles allocate nothing
and publish AMBIENT_UNSUPPORTED / EAR_SENSE_UNSUPPORTED. Its ESPURR_TOUCH
sub-option also defaults on; disabling it omits AW96105 device handles, driver/
publication state and register traffic while retaining ALS sampling. Ear snapshots
then remain EAR_SENSE_UNSUPPORTED, including after shared-task allocation failure.
Both switches are under Espurr cat ears in menuconfig. Startup failure permits degraded operation and
does not participate in pending-image input/render health acceptance.
One priority-2 core-0 owner with a 4096-byte internal stack polls all four devices, then delays 100 ms without catch-up. Each native I2C transaction has a 20 ms timeout. The owner borrows the board's buses and owns only its device handles: no bus reset, bus deletion, GPIO setup, per-sample allocation or register access from rendering, transport handlers or snapshot readers. A failed side retries independently after one second. Failed task creation removes its handles; failed removal retains the handle and rejects another startup rather than losing a live allocation.
ltr_f216a_poll() is a bounded, host-testable register driver. The selected diagnostic
exposure is fixed at 3x gain, 18 bits and 100 ms integration. Configuration disables
conversion and waits 450 ms before changing exposure. The datasheet's control-register
and operating-state descriptions differ on in-flight conversion cancellation; waiting
beyond the longest 400 ms integration avoids depending on immediate cancellation.
The owner sets exposure/gain and masks the unused interrupt, drains old data, then
enables conversion. A 250 ms settling interval starts after that last write completes.
Part identity, control/exposure readback and the power-on/glitch flag are checked.
The status/clear/ALS burst stays within the device's data-lock range, preserving one
coherent conversion. Reserved/out-of-range data, transport failure, reset/configuration
drift and a missing conversion deadline invalidate the observation and restart the
bounded recovery sequence. This service never changes another peripheral's registers.
The driver publishes independent sequence/configuration generation, observation time,
health/error, clear/ALS counts, exposure, nominal millilux and saturation for each side.
No-new-data polls retain the prior sequence/time. sensing_snapshot() copies both
under one short lock and independently expires READY observations older than 500 ms,
including when sampling stalls during other work. Only READY data may be used live;
non-READY numeric fields describe a historical observation. Saturation of either
channel is inferred from digital full scale and disqualifies the nominal lux as an
ordinary unsaturated measurement. A zero READY count is distinct from missing data.
The timestamp is the conservative host poll start, not a hardware conversion clock
or synchronisation between sensors.
At the selected exposure, nominal millilux is 150 * ALS. Window/fur transmission,
mounted orientation and LED spill are unqualified. There is no autoranging, fusion,
automatic brightness or proximity reaction yet. Authenticated read-only 40-byte
light.left.status / light.right.status records provide matching diagnostics on
both phones under Settings → Light sensors. Non-READY ADC/lux fields are masked;
records retain exposure and age provenance. See the wire contract.
The minimal browser/watch retain their current scope. No setting/catalogue schema changes or automatic reactions are introduced.
Experimental ear measurements¶
aw96105_poll() advances a per-device reset/configuration/calibration state machine
without sleeping or allocating. The native adapter sends big-endian 16-bit register
addresses and 32-bit values. It requires the documented 0xA9610B00 identity and
five-pad variant, records firmware version, resets only this chip through
HOSTCTRL2 at 0xFF0C, waits at least 20 ms after the write finishes, and requires
the initialization latch within a further 200 ms. Unknown identities/revisions fail
explicitly; package similarity does not imply compatibility with AW96105A/AW93xxx.
The diagnostic configuration uses public fields and preserves reserved bits. A poll configures/readbacks one register, keeping startup work bounded. It masks the unused host interrupt pin, selects 100 ms scans without doze, enables only logical channels 0–2 at 20-bit resolution/1.1 pF range and 100 kHz sampling, bypasses RawFilter2/LPF and disables reference correction. Unused physical pads remain high-impedance; no driven-shield experiment is selected. Electrode identity is explicit:
| Observation index / logical channel | Electrode | Physical input |
|---|---|---|
| 0 | T1, short side, /TOUCH_SIDE_A |
CS4, U1.9 |
| 1 | T2, long side, /TOUCH_SIDE_B |
CS0, U1.7 |
| 2 | T3, tip, /TOUCH_TOP |
CS3, U1.8 |
After requesting AOT on those three channels and entering active mode, the driver requires the calibration-complete latch, cleared compensation requests and cleared in-progress bits within two seconds. The first published scan must follow that calibration transition. COFF target/limits and baseline/classifier tuning remain at chip reset defaults: this is a datasheet-derived diagnostic experiment, not a vendor-qualified electrode configuration. Host interrupt masking must be verified to leave completion latches observable on the fitted revision. A missing completion fails/retries rather than assuming calibration succeeded or lifting another gate.
The sample contains raw, valid, baseline and difference banks as signed S21.10
integers, current per-channel offset codes, all three chip status words and the
observed IRQ flags. RAW - BASELINE is not substituted for DIFF; the latter uses
filtered VALID. Chip saturation, COFF error and startup-proximity flags remain
visible quality observations; EAR_SENSE_READY means only that a fresh coherent
diagnostic scan was acquired. It does not qualify the data for user actions.
There is no documented multi-bank data latch. Reads are bracketed with the conversion-complete latch and idle/busy state; an overlapping conversion is discarded. Configuration readback detects drift, and initialization/watchdog flags or unexpected AOT activity invalidate the epoch. Confirm actual latch/update ordering and burst auto-increment on hardware. No-new-data/discarded polls retain sequence/time. Missing usable data for 500 ms fails/restarts that device; getters independently expire READY data after 500 ms, including when the owner stalls. Transport/reset/config/calibration failures restart only that ear after one second. A prior scan remains historical while non-READY.
sensing_ear_snapshot() provides short, allocation-free left/right copies under
the existing publication lock. The owner stack and task count are unchanged; each
native transaction retains the 20 ms timeout. Authenticated read-only 64-byte ear.left.status / ear.right.status
records now expose raw/baseline/difference banks, chip identity, channel quality,
counters and age on both phones under Settings → Ear sensors. Other internal fields
remain off the wire to preserve older clients' per-value bound. See the
wire contract. Qualification
still precedes through-fur smoothing, thresholds or gestures. No proximity/touch reaction, automatic brightness or new
persistent setting is enabled.
Register facts are from Awinic's June 2020 AW96105 V1.0 full datasheet, pages 11–16
and 21–38, for the selected AW96105DNR:
public manufacturer-authored distributor copy.
The reset overview says 0xFF0F; the aligned register table/detailed HOSTCTRL2
specification and vendor-authored upstream Linux driver agree on a 32-bit zero at
0xFF0C. The latter is the implementation's address. The public V1.5 brief does
not contain a replacement register contract. The
upstream Linux AW96103/AW96105 driver
was inspected for initialization/configuration behavior; its GPL code and opaque
configuration table were not copied. No suitable exact-part IDF component was
identified. Public research inputs/hashes stay under ignored
build/artifacts/v2-aw96105-2026-10-31/, not in tracked source.
Tests inject failures at every startup/capture I2C operation, signed extremes, conversion overlap, drift/reset, missing init/AOT/data deadlines and concurrent publication. Native fixtures cover big-endian packets, independent ear/ALS failures, missing buses/devices, cleanup, recovery and stalled-owner expiry. They do not prove real AOT, latch ordering, analogue range/signal quality, through-fur detection, LED/cable interference or timing/heap/stack margins on a running wearable.
Register and conversion facts come from Lite-On's LTR-F216A datasheet, sections 4–7,
pages 8–16 and 21–22 in the 32-page copy:
manufacturer link,
public distributor copy.
No suitable exact-part managed IDF component was identified. The small driver uses
native IDF I2C; no Linux GPL driver or opaque configuration table was copied.
The public PDF, hash and bounded facts record are retained under ignored
build/artifacts/v2-light-sensors-2026-10-31/.
Native fixtures cover coherent byte order, exposure/readiness, lux/dark/saturation, every configuration/read failure, reset/configuration drift, conversion timeout, settling after delayed writes, independent devices/bus failures, cleanup and concurrent publication. They cannot establish real register auto-increment, bus timing, physical identity, optical calibration, spill/occlusion behaviour or combined workload headroom.