From fdb8a1299eafdedf68902c4c785f9fb0390e80c4 Mon Sep 17 00:00:00 2001 From: Luke Hoersten Date: Sat, 13 Jun 2026 23:15:27 -0500 Subject: M8: local screens (IP + Loading) + BOOT button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit local_screens.{h,c}: - Embedded 8x8 bitmap font sized to a 95-char table; only the glyphs used by today's strings (viewport.local, the IPv4 string, Loading...) are populated. Unsupported chars render blank. - 768 KB PSRAM scratch FB at panel-native dims. - local_screens_show_ip() — two centered lines: "viewport.local" Scale 3x portrait / 4x landscape; centered vertically. - local_screens_show_loading() — centered "Loading..." at scale 4x/5x. - local_screens_restore_for_state() — repaint after BOOT-overlay expiry: UNCONFIGURED -> IP screen; AWAKE/ASLEEP -> black FB (next /frame or sleep handles the rest). - All paths go through display_present_rgb565() so orientation rotation is automatic. button.{h,c}: - Polling task at 30ms, active-low with internal pull-up. - Short press (<5s, released) → backlight on, IP overlay for 15s via esp_timer one-shot, then restore. - Hold ≥ 5s → nvs_config_reset() + esp_restart(). - PIN_BOOT_BUTTON = GPIO 0 is a TODO placeholder. ESP32-P4 strap pin GPIO35 is owned by RMII TXD1 at runtime so Waveshare must expose a separate user button on a free pin; confirm against the schematic. Fail-soft if mis-wired: input reads stuck-high and the task never fires. state_machine on AWAKE transition now calls local_screens_show_loading() right after display_wake() — so every wake (tap or POST /state) flashes a clear "Loading..." until the next /frame paints over it. app_main on boot: - Calls local_screens_init() after display_init(). - UNCONFIGURED → paint IP screen (replaces the M3 test pattern). - ASLEEP → backlight off (unchanged). - After all subsystems: button_init(). Build clean against ESP-IDF 5.4 (binary ~870 KB; the font/glyph data is under 800 bytes). TESTING.md M8 documents the visual checks, the BOOT-pin placeholder caveat, the AWAKE-overlay-overwrite behavior, the open follow-up about post-overlay backlight when ASLEEP, and the font fallback policy. --- TESTING.md | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) (limited to 'TESTING.md') diff --git a/TESTING.md b/TESTING.md index 38c127b..151fff2 100644 --- a/TESTING.md +++ b/TESTING.md @@ -457,15 +457,32 @@ Tap rapidly (faster than the receiver can ack) and confirm the receiver only see **Acceptance**: IP screen on first boot; loading screen on every wake; BOOT button works. -**How to verify** +**Visual checks (panel-attached)** -- Fresh flash → screen shows `viewport.local` and the device IP centered. -- `POST /config` → IP screen clears; backlight off (device enters sleep). -- Tap while asleep → "Loading…" screen until next `/frame`. -- BOOT short-press (any state) → IP screen overlays for 15s, then prior state restored. -- BOOT 5s-hold → NVS clears, device reboots, IP screen reappears. +- Fresh flash (or after factory reset) → screen shows two centered white-on-black lines: + ``` + viewport.local + 192.168.x.y + ``` +- `POST /config` with viewport + scrypted → device transitions to ASLEEP, backlight off. +- `POST /state {state:wake}` (or tap) → backlight on, `Loading...` centered until the first `/frame` lands. +- `POST /frame` while AWAKE → loading screen replaced by the JPEG. +- `POST /state {state:sleep}` (or idle timeout, or tap-while-awake) → backlight off. -**Status**: ⬜ pending. +**BOOT button** (GPIO 0 placeholder — see Hardware note below) + +- Short press at any state: backlight wakes if it was off, IP screen overlays for 15s, then `local_screens_restore_for_state()` paints black (Scrypted's next `/frame` repaints if awake; the state machine handles backlight if asleep). Does not change wake/sleep state. +- Hold ≥ 5s: serial logs `BOOT held 5000ms → factory reset`, NVS clears via `nvs_config_reset()`, `esp_restart()`. After reboot the device comes back UNCONFIGURED with the IP screen. + +**Hardware note**: `PIN_BOOT_BUTTON = 0` in `button.c` is a guess. ESP32-P4's official strap pin is GPIO35 but that's owned by RMII TXD1 at runtime. Most Waveshare ESP32-P4 boards expose a separate user button on a free GPIO — confirm against the schematic and update `PIN_BOOT_BUTTON` if needed. If the wrong pin is wired, the button just never triggers (input reads stuck-high) and the rest of M8 still works. + +**Negative / edge** + +- BOOT overlay during AWAKE: the overlay paints over the live frame. Scrypted's next `/frame` (within ~1s in a normal stream) overwrites it. Acceptable: the operator sees the IP for ≤ 1 frame interval then the live view resumes. +- BOOT overlay during ASLEEP: backlight comes on for the overlay, then `restore_for_state` paints black. The state machine's `display_sleep()` is NOT re-issued — that's an open follow-up if the test pattern stays lit after expiry. +- Font fallback: any character outside the supported set (digits, dot, colon, `L`, lowercase a/c/d/e/g/i/l/n/o/p/r/t/v/w, space) renders as blank. Today the only strings drawn are `viewport.local`, the IPv4 string, and `Loading...` — all covered. + +**Status**: 🟡 builds clean against ESP-IDF 5.4 (binary ~870 KB). Hardware verification awaits panel + BOOT-pin confirmation. --- -- cgit v1.2.3