# 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.