Skip to content

Buttons and motion

Button, motion and palettes

The following single-button mapping applies to legacy profiles. V2 uses the two-button policy below.

Gesture Action
Single click LEDs off/on; off clears flashlight; exit diagnostics when running
Double click Toggle temporary flashlight
Triple click Toggle BLE/Wi-Fi
Four clicks Enter LED diagnostics
Hold from 600 ms Ramp normal brightness, or independent flashlight brightness while active
Held during boot Configuration recovery; continued holding does nothing else
Boot hold → release → next press held 5 s Enter LED diagnostics; keep the selected radio mode

Single-button profiles wait 250 ms after the final release to distinguish clicks. Five or more clicks do nothing. Holds alternate ramp direction and stop at limits; continuing past five seconds does not switch radios. Effect selection is available through the native app/browser.

V2 shortcuts:

Gesture Action
Button 1 single / double click Global LED on/off / temporary flashlight
Button 1 four clicks Enter LED diagnostics
Button 1 hold 5 s Switch BLE/Wi-Fi
Both buttons held 5 s Request toggle of the configured temporary source-current override; no qualification/fault bypass
Button 2 single / double click Next / previous catalogue effect; either dismisses flashlight without changing effect
Button 2 hold from 600 ms Ramp normal brightness, or independent flashlight brightness while active

V2 waits 250 ms to distinguish single/double clicks; triples have no action. Ramps alternate direction on successive holds, stop at endpoints and keep an off device off. Each brightness target keeps its own direction. The chord consumes both individual holds and requires both releases before another gesture. Boot-held recovery still belongs to button 1; release, then hold it 5 s for diagnostics. In v2 diagnostics, button 1 single-click turns output off and button 2 click resumes normal operation. The input contract records timing, late-overlap/boot cases and live brightness/revision behaviour. Numeric power-path qualification and mounted button/current/white acceptance remain separate work.

On legacy strips, all palette-based effects distribute one colour sequence along the entire short-edge base → tip → long-edge base outline, identically on both logical ears. Flag stripes have approximately uniform pixel counts across the full chain. Comets, twinkles and aurora clouds animate brightness over those colours; Liquid light uses height for its fill, while its colours follow the outline. Chase bands moves one complete palette sequence around the outline. Rainbow generates one full hue sequence along it. Physical wiring reversal is applied only by the LED output component.

On v2, palettes repeat around each closed ring, using PCB-derived arc distance; spatial fields use physical X/height. The centre has an explicit policy rather than behaving as a strip endpoint. Raised tip sweeps both rings independently to four marked tip samples per ear. See the mapped rendering contract for effect-specific centre, closure and reflection semantics. V1 appearances remain covered by unchanged frame goldens.

Effects include static palette, breathing, gradient, sparkle, rainbow, travelling comet, Aurora, Twinklefox, Chase bands, Motion twinkle, Liquid light, Inertia, Stardust, Motion aurora and Sound bands. Palette and animation are independent. Presets include the four-colour mix, purple/orange, shades of purple, purple/pink, five-stripe lesbian flag, trans flag and PAX enforcer yellow. Custom palettes have 1–8 RGB colours, sampled as bands or a blend. Flag presets use recognisable base-to-tip bands; gradient effects can blend them. The enforcer shortcut selects steady yellow; press Apply & Save to use it.

Legacy IMU backends use native IDF I2C and 100 Hz host sampling. MPU6886 uses a coherent 14-byte burst, ±4 g and ±1000°/s. MPU6886 register setup is adapted from M5Stack's native-IDF driver, with its MIT licence retained under components/imu/. The driver retries an absent sensor and logs reminders at most once per minute. Motion-sensitive effects use their idle appearance when samples are unavailable; directional behaviour needs calibration.

V2 uses the LSM6DSV16BX's timestamped 120 Hz FIFO with a 100 kHz bring-up bus and the host gravity estimator by default. Optional SFLP gravity is experimental; mounting, saved gyro bias and gestures retain their existing host semantics. See the BX owner and qualification contract. The v2 capture owner coordinates internal air/contact requests with BX resets and render-owned flash pauses. Both sources default off; both phone apps can request a temporary diagnostic capture and inspect per-channel levels, clipping and loss, and explicitly record/download/save/share bounded WAV clips. Sound bands can independently request air capture while normal lighting is enabled; its separate Sound gain leaves PCM unchanged. Missing audio produces a dim static palette, with health/fallback shown by both phone apps and the browser. Recording still requires a diagnostic lease. Further contact-VAD work is pending hardware and worn recordings. ESPURR_AUDIO in menuconfig can omit capture, processing and recording. Its ESPURR_AUDIO_PDM and ESPURR_AUDIO_CONTACT sub-options independently select air and contact receivers. PDM reactivity requires neither VAD nor speech recognition.

The v2 ambient sensing owner polls both LTR-F216A devices independently and publishes expiring raw/nominal-light observations. ESPURR_SENSING can omit all slow sensing; its ESPURR_TOUCH sub-option can omit AW96105 sampling independently while retaining ALS. Both phone apps expose Settings → Light sensors with level/age and raw details; omitted sampling remains explicitly unsupported. Settings → Ear sensors also exposes AW96105 raw/baseline/electrode diagnostics. Automatic brightness and touch/proximity actions remain pending optical/worn qualification. See the build switches.

In the phone's calibration page, capture neutral while stationary, then tilt gently right by 10–60° and capture right tilt. Each capture waits for two seconds of continuous stillness, for up to five seconds, while LED rendering continues. Movement or a sample gap restarts the settling window; stale/missing motion cannot be captured. Pending BLE captures cancel on disconnect/mode closure, and the completed basis patches the latest settings. A failed capture is reported without disconnecting the updated native app; transport, crypto and ambiguous/protocol failures still close it. Update the app alongside firmware: older clients use a three-second command deadline. Serial logs explain rejection, timeout and accepted stages. That establishes mounting-independent head axes and gyro bias. Recalibrate neutral only preserves the learned axes. Re-run the full procedure after changing the board's mounting. Filtering and sensitivity are settings, not per-effect constants. There is no absolute heading or elaborate AHRS.