From d5cdb6b4e4424d80ac9bfd8e12c129334c23d6f2 Mon Sep 17 00:00:00 2001 From: Luke Hoersten Date: Sun, 14 Jun 2026 15:53:33 -0500 Subject: M3 WIP: DSI bring-up + state machine + identity overlay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- main/state_machine.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'main/state_machine.c') 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) -- cgit v1.2.3