Skip to content

feat(mosaico): add experimental camera gestures - #8

Merged
eMUQI merged 15 commits into
mainfrom
mosaico-gestures
Oct 3, 2026
Merged

eMUQI merged 15 commits into
mainfrom
mosaico-gestures

Conversation

@eMUQI

@eMUQI eMUQI commented Oct 2, 2026 •

Copy link
Copy Markdown
Owner

Add experimental on-device camera gestures to ESP-Mosaico and shorten its startup to first data.

Camera gestures (experimental, off by default)

  • Uses the left-slot CameraBoard (OV3640 or SC101IOT, auto-detected) with ESP-DL hand detection and pose classification. Images are processed on the device only; nothing is uploaded or stored.
  • On usage pages, a swipe in any direction or a horizontal wave moves to the next page. Holding OK or thumbs-up for about half a second enters the clock. A swipe or wave wakes from the clock and restores the previous page.
  • The settings page gains a CAMERA switch, saved together with brightness and the auto-clock timeout as one NVS record.
  • A header camera indicator shows capture state; tapping it toggles a preview with the hand location box.
  • Gestures are ignored while settings, pairing confirmation or OTA are on screen. Touch, the AI button and Bridge commands keep working and cancel any gesture in progress.

Storage and OTA

  • App slots grow from 4 MiB to 7 MiB so both models ship inside the application and update or roll back with it.
  • The Folder Push transfer limit and the Bridge firmware image limit follow the target's slot size.
  • Devices on the 4 MiB layout need one wired install to move to the new partition table. The steps will be covered in the release notes.
  • Display settings move to one combined NVS record. Brightness and auto-clock timeout saved by earlier firmware are still read until the next save.

Startup

  • The panel starts at zero brightness and fades in after the first frame is written.
  • BLE advertising starts before the remaining peripherals initialize, and BQ27220 setup runs in a background task. The redundant second seal is removed and the seal settle time is set to 200 ms; the driver still confirms the sealed state.
  • The battery icon shows the no-data state until the first reading arrives.

Documentation

  • Gesture design, usage and installation guide, boot flow, and the AMOLED UI spec for the new indicator, preview and switch.
  • Dependency references and model digests in CAMERA_UPSTREAM.md, local BSP changes in UPSTREAM.md, and new components in THIRD_PARTY_LICENSES.md.

Verification

  • Bridge host tests: 625 passed, 7 skipped.
  • Firmware builds with ESP-IDF v6.1: firmware/targets/esp_mosaico (5,422,064-byte application), firmware/targets/esp_mosaico/test_apps/logic (also from a clean configure) and firmware/test_apps/panel_state.
  • Documentation: local links resolve and git diff --check is clean.
  • Hardware: camera gestures checked on an ESP-Mosaico with a left-slot CameraBoard.

eMUQI added 14 commits October 1, 2026 13:18
Add swipe navigation, wake-only screensaver input, and held OK clock entry.
Keep recognition local and disabled by default in display settings.

Expand OTA slots to 7 MiB to embed both models with the application.
Existing 4 MiB layouts require a first wired partition migration;
segmented installation preserves NVS but replaces the old fallback slot.

Validation: enabled/disabled firmware and test images build; 31 host
Unity tests pass with ASan/UBSan; Bridge tests pass (620, 7 skipped).
Camera behavior, performance, and rollback await hardware validation.
Every swipe direction and a horizontal greeting wave now advance to the
next page; OK or thumbs-up held for about 500 ms enters the clock.

- Recognize a wave as three alternating horizontal legs of at least 12%
  of the frame, for motion too small to be a swipe.
- Issue one command per burst of motion: after a swipe or wave the hand
  must rest for 400 ms or leave the view. This replaces the 500 ms
  cooldown.
- Anchor the stroke origin to a resting hand so the stroke window opens
  when the hand starts to move.
- Accept a wave without first requiring the view to clear, so the clock
  can be woken by the hand that entered it.
- Skip pose classification while the hand moves between frames, and log
  every observation with a hand for replay through GestureTracker.
- Load the classifier at capture start and mark context changes caused
  by an accepted gesture explicitly, so other input always requires the
  view to clear again.

Host tests: 13 gesture and image cases pass under ASan/UBSan. The wave
thresholds are trial values without device data; recognition and false
trigger rates are not validated on hardware.
A cold boot took about 12 s to the first bridge data because the main
loop and BLE advertising waited for every peripheral, including about
4.4 s in the battery gauge driver.

- Start BLE advertising right after the display so the bridge can
  reconnect while the remaining peripherals initialize.
- Attach the BQ27220 on its own task; the battery stays hidden and the
  OTA power verdict unavailable until it is ready.
- Bring the CO5300 up at zero brightness without the Display On delay
  and fade in after the first refresh, which removes the white flash of
  undefined frame memory. The board support change is recorded in
  UPSTREAM.md.

Measured from UART timestamps on one cold boot each: advertising 8.5 s
to 3.2 s, main loop 8.5 s to 3.8 s, first time sync 12.1 s to 5.1 s.
See docs/validation/mosaico-boot.md.
- Drop the second bq27220_seal() in bsp_battery_init(). The driver
  already seals and confirms on every path that returns a handle, and
  each seal waits 2000 ms unconditionally. The board support change is
  recorded in UPSTREAM.md.
- Colour the battery segments as unavailable when they are created.
  They used the default theme colour until the first render, which
  looked like a full battery before the first reading.

Measured on one cold boot: gauge ready at 5.9 s instead of 7.9 s. Two
other recorded boots found a mismatching stored gauge profile and
rewrote it; the cause is not established. See
docs/validation/mosaico-boot.md.
Set CONFIG_BQ27220_SEAL_SETTLE_MS to 200 instead of the driver default
of 2000 so the first battery reading is not held back by the wait. The
driver still confirms the sealed state after the wait and fails
initialization otherwise.

200 ms is a trial value without datasheet support. On the one boot
recorded with it the seal confirmation passed, but the stored gauge
profile mismatched again and was rewritten, and later recordings lost
the gauge output. Whether this value affects the stored profile is not
established; revert this commit alone to restore the default.
Record espressif/dhara 1.1.0 to match dependencies.lock; the distributed
license text is unchanged from 1.0.0.

Describe the gesture context word layout, and state that the first
completed refresh starts the brightness fade-in rather than begin().

Index the Mosaico boot flow document, list camera gestures in the
verified device coverage, and describe camera start as up to three
attempts, matching the code.
Without sdkconfig.defaults a clean configure selects the default esp32
target, whose DRAM cannot hold the 230400-byte gesture image buffer used
by the conversion tests, so the test image fails to link. The other
test applications already pin their target the same way.
@eMUQI

eMUQI commented Oct 2, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-03T00:05:52.154090Z 0c61451 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7d83ae8461

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread firmware/targets/esp_mosaico/partitions.csv
Comment thread firmware/targets/esp_mosaico/main/panel_settings.cpp Outdated
Comment thread bridge/src/quotaframe_bridge/sources/firmware_release.py
Earlier firmware stored brightness and the auto-clock timeout as separate
keys in the shared "display" NVS namespace. When the combined
mosaico/settings record is missing or invalid, load those keys before
falling back to defaults, so an upgrade that preserves NVS keeps the
user's preferences. Capture stays off, and the next save writes the
combined record.
@eMUQI

eMUQI commented Oct 3, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 0c61451841

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@eMUQI
eMUQI merged commit 4869310 into main Oct 3, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant