diff options
| author | Luke Hoersten <[email protected]> | 2026-06-14 15:53:33 -0500 |
|---|---|---|
| committer | Luke Hoersten <[email protected]> | 2026-06-14 15:53:33 -0500 |
| commit | d5cdb6b4e4424d80ac9bfd8e12c129334c23d6f2 (patch) | |
| tree | f9b5e838061f76af8160863548758311857b1c75 /main/state_machine.c | |
| parent | 8d740665777af6d74b334e2dee98a53ebb9a29aa (diff) | |
M3 WIP: DSI bring-up + state machine + identity overlay
DSI / panel:
- LDO_VO3 acquired at 2500 mV (VDD_MIPI_DPHY) — without this the PHY
PLL busy-waits forever inside esp_lcd_new_dsi_bus.
- PSRAM bumped to 200 MHz (CONFIG_IDF_EXPERIMENTAL_FEATURES) to keep
the DPI fed without underruns.
- Pi-7"-style 800x480 panel init (REG_POWERON, PORTA/PORTB/PWM/PORTC)
+ 16-bit RGB565 framebuffer with portrait-mode rotation buffer in
PSRAM. Currently shows garbled output — known issue, next commit
switches to the TC358762-bridge-aware init sequence.
State + UX:
- viewport_state simplified to AWAKE/ASLEEP only; "unconfigured" is
a flag, not a state. Tap always toggles; content choice (identity
vs frame) is driven by the configured flag.
- BOOT button arms a 15 s identity overlay via local_screens_overlay;
expired callback returns to prior state.
- Boot-done indicator: two backlight flashes (no usable LED GPIO on
the Waveshare board — GPIO 35 BOOT is shared with EMAC TXD1).
- Best-effort subsystem init in app_main; display init deferred to
its own task so a panel hang can't block networking.
Display test pattern: solid R/G/B for 2 s each on boot to characterize
the garble independent of text rendering.
Diffstat (limited to 'main/state_machine.c')
| -rw-r--r-- | main/state_machine.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/main/state_machine.c b/main/state_machine.c index 8f0b3e1..c9e4367 100644 --- a/main/state_machine.c +++ b/main/state_machine.c @@ -50,24 +50,25 @@ esp_err_t state_machine_set(viewport_run_state_t target) viewport_state_lock(); viewport_state_t *st = viewport_state_get(); - if (!st->configured) { - viewport_state_unlock(); - return ESP_ERR_INVALID_STATE; - } if (st->state == target) { viewport_state_unlock(); return ESP_OK; // idempotent no-op } st->state = target; + bool configured = st->configured; viewport_state_unlock(); if (target == VIEWPORT_STATE_AWAKE) { if (display_is_up()) { display_wake(); - local_screens_show_loading(); // until next /frame paints + // Content choice: configured devices show "Loading…" until + // Scrypted pushes a /frame; unconfigured devices show the + // identity screen since there's no Scrypted to push anything. + if (configured) local_screens_show_loading(); + else local_screens_show_ip(); } arm_idle_timer_unlocked(); - ESP_LOGI(TAG, "AWAKE"); + ESP_LOGI(TAG, "AWAKE (%s)", configured ? "configured" : "unconfigured"); } else { disarm_idle_timer(); if (display_is_up()) display_sleep(); @@ -86,12 +87,14 @@ void state_machine_frame_painted(void) void state_machine_set_local(viewport_run_state_t target) { - // For idempotent no-op (already in target), state_machine_set returns OK - // without changing state; we still call state_client to keep Scrypted in - // sync if it's drifted. State POSTs are idempotent on both ends. esp_err_t err = state_machine_set(target); - if (err != ESP_OK) return; // unconfigured / invalid - state_client_post(target); + if (err != ESP_OK) return; + // Only POST when there's a Scrypted to talk to. Unconfigured tap toggles + // change the local display state without notifying anyone. + viewport_state_lock(); + bool configured = viewport_state_get()->configured; + viewport_state_unlock(); + if (configured) state_client_post(target); } viewport_run_state_t state_machine_current(void) |
