Files
vela-snake-m/docs/CROWN.md
T

1.8 KiB

Crown control experiment (v0.9)

Firmware study of the O63 OTA (upd_miwear.watch.o63.zip) found how the crown reaches quickapps: there is no crown/rotary JS event (no onCrown, onRotary, wheel keyevents in vela_quickapp.bin), but the native layer (vela_ap.bin, inputmanager/lv_touchpad_wheel_interface.c + the crown_scroll input tag in lvx_inputmanager.c) routes crown rotation into scroll deltas of the focused scrollable container.

So Snake listens to the crown indirectly:

  • the page is wrapped in a full-screen vertical scroll component with the dial centered inside it,
  • onscroll fires for both crown rotation and finger scroll,
  • the page converts each scroll delta into a queued 90° turn (snake.rotateDir, already in the codebase): positive delta = clockwise, negative = counterclockwise, CROWN_STEP_PX px of scroll per turn,
  • because turns are 90° relative steps, the crown always turns the snake left/right regardless of where the head is pointing, and reversals are structurally impossible (rotateDir never emits a 180° flip),
  • the scroll position is actively re-centered (scrollTo({ top: center })) after each event so the board never visually moves; only the idle-swipe fallback path (when no scroll events arrive, e.g. some firmwares coalesce crown scroll with the swipe handler) uses onswipe as before,
  • swipes still work exactly as in 0.8; both input paths feed the same two-slot turn queue.

Open questions that need the physical watch:

  • does the Crown S4 emit scroll deltas with sign, and at what px granularity?
  • does onscroll fire for crown motion at all on this firmware, or only for touch scroll? If not, the CROWN_STEP_PX accumulator still catches the swipe-path fallback but true crown control would need native access.