src.nth.io/

summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorLuke Hoersten <[email protected]>2026-06-14 18:30:44 -0500
committerLuke Hoersten <[email protected]>2026-06-14 18:30:44 -0500
commit186fd85422f99dfb59d89ae9338dc50627f7c3e5 (patch)
tree59db53e2962dc815151b9e70a4d6f1ce53c22a98 /main
parent4a6bbdb075a5e4f9910cb9b85e615ff8c50aa4ec (diff)
Tidy: delete dead code, inline single-use helpers, fix double-lock
Code-review pass after the M5 colour fix. -126 net lines (-215 / +89). Dead code removed: - display_fill, display_test_pattern — M3 bring-up self-tests, no callers - net_eth_is_up — no callers - nvs_config_reset — no callers (factory-reset gesture was removed earlier; NVS wipe now goes through `idf.py erase-flash`) Helpers inlined or collapsed (each had one call site): - state_name / orientation_name — ternaries at the cJSON site - fmt_bytes / fmt_uptime — inline scope in local_screens_show_info - expected_dims (http_api) + effective_dims (local_screens) — merged into viewport_state_effective_dims() in viewport_state, one canonical source state_machine cleanup: - arm_idle_timer_unlocked / disarm_idle_timer collapsed to one arm_idle_timer(ms) that takes the snapshotted timeout (ms==0 disables). Removes the misleading name and the second viewport_state lock acquisition per painted frame. - state_machine_set + state_machine_frame_painted now snapshot state + idle_ms under one lock. mdns_service cleanup: - snapshot_state / apply_hostname / apply_txt collapsed into a single apply_state(include_hostname) helper; mdns_service_start grabs hostname once for hostname_set + log instead of going under the lock three times. http_api cleanup: - POST /config brightness-changed path uses the local `bright` it already validated instead of re-locking + re-reading st->brightness. - Trimmed verbose bring-up comments (stack-size justification, M5 saga, DSI shadow struct) to one line each — kept the load-bearing facts. Smoke-tested on hardware: boot clean, display + JPEG + touch all up ([DJT]), info screen renders, no crashes.
Diffstat (limited to 'main')
-rw-r--r--main/display.c57
-rw-r--r--main/display.h8
-rw-r--r--main/http_api.c38
-rw-r--r--main/local_screens.c56
-rw-r--r--main/mdns_service.c81
-rw-r--r--main/net_eth.c5
-rw-r--r--main/net_eth.h2
-rw-r--r--main/nvs_config.c13
-rw-r--r--main/nvs_config.h3
-rw-r--r--main/state_machine.c25
-rw-r--r--main/viewport_state.c11
-rw-r--r--main/viewport_state.h5
12 files changed, 89 insertions, 215 deletions
diff --git a/main/display.c b/main/display.c
index 13babdb..a704891 100644
--- a/main/display.c
+++ b/main/display.c
@@ -101,13 +101,8 @@ enum {
#define TC_PPI_STARTPPI 0x0104
#define TC_DSI_STARTDSI 0x0204
-// Shadow of esp_lcd_dsi_bus_t. The IDF private struct is
-// { int bus_id; mipi_dsi_hal_context_t hal; esp_pm_lock_handle_t pm_lock; }
-// (esp-idf/components/esp_lcd/dsi/mipi_dsi_priv.h). We only need bus_id +
-// hal to reach the LL/HAL APIs, so the trailing pm_lock is fine to ignore.
-// If the IDF layout shifts in a future release this is the place that
-// breaks first — guarded by ESP-IDF version is overkill until it actually
-// breaks.
+// Mirror of esp_lcd_dsi_bus_t (esp-idf/components/esp_lcd/dsi/mipi_dsi_priv.h)
+// — needed to reach the HAL/LL APIs for the TC358762 bridge init.
typedef struct {
int bus_id;
mipi_dsi_hal_context_t hal;
@@ -424,12 +419,9 @@ esp_err_t display_wake(void)
return err;
}
-// RGB565 → RGB888 in B,G,R byte order. The ESP32-P4 DSI engine + TC358762
-// bridge pipeline expects BGR on the wire for the panel's RGB channels —
-// writing R first paints pure blue as solid red on the panel (verified
-// with the M5 self-test: decoded buffer holds 0x001F, panel showed red).
-// Symmetric pixels (white text on black) don't expose this; saturated
-// channel inputs do.
+// RGB565 → 24-bit pixel in B,G,R memory order — what the DSI engine +
+// TC358762 + Pi panel pipeline expects (the "RGB888" label refers to the
+// MIPI wire bit order, not byte position in PSRAM).
static inline void rgb565_to_rgb888(uint16_t px, uint8_t *out)
{
out[0] = (uint8_t)(( px & 0x1F) * 255 / 31); // B
@@ -437,22 +429,6 @@ static inline void rgb565_to_rgb888(uint16_t px, uint8_t *out)
out[2] = (uint8_t)(((px >> 11) & 0x1F) * 255 / 31); // R
}
-esp_err_t display_fill(uint16_t rgb565)
-{
- if (!s_up || !s_rot_buf) return ESP_ERR_INVALID_STATE;
- uint8_t rgb[3];
- rgb565_to_rgb888(rgb565, rgb);
- size_t n = PANEL_H_ACTIVE * PANEL_V_ACTIVE;
- for (size_t i = 0; i < n; ++i) {
- s_rot_buf[i * 3 + 0] = rgb[0];
- s_rot_buf[i * 3 + 1] = rgb[1];
- s_rot_buf[i * 3 + 2] = rgb[2];
- }
- return esp_lcd_panel_draw_bitmap(s_panel, 0, 0,
- PANEL_H_ACTIVE, PANEL_V_ACTIVE,
- s_rot_buf);
-}
-
esp_err_t display_present_rgb565(const uint16_t *src,
uint16_t src_w,
uint16_t src_h)
@@ -463,8 +439,6 @@ esp_err_t display_present_rgb565(const uint16_t *src,
viewport_orientation_t orient = viewport_state_get()->orientation;
viewport_state_unlock();
- if (!s_rot_buf) return ESP_ERR_INVALID_STATE;
-
if (orient == VIEWPORT_ORIENTATION_LANDSCAPE) {
if (src_w != PANEL_H_ACTIVE || src_h != PANEL_V_ACTIVE)
return ESP_ERR_INVALID_SIZE;
@@ -489,24 +463,3 @@ esp_err_t display_present_rgb565(const uint16_t *src,
PANEL_H_ACTIVE, PANEL_V_ACTIVE,
s_rot_buf);
}
-
-esp_err_t display_test_pattern(void)
-{
- if (!s_up || !s_rot_buf) return ESP_ERR_INVALID_STATE;
- static const uint16_t bars[8] = {
- 0xFFFF, 0xFFE0, 0x07FF, 0x07E0,
- 0xF81F, 0xF800, 0x001F, 0x0000,
- };
- const int bar_w = PANEL_H_ACTIVE / 8;
- for (int y = 0; y < PANEL_V_ACTIVE; ++y) {
- for (int x = 0; x < PANEL_H_ACTIVE; ++x) {
- int b = x / bar_w;
- if (b > 7) b = 7;
- size_t idx = ((size_t)y * PANEL_H_ACTIVE + x) * 3;
- rgb565_to_rgb888(bars[b], &s_rot_buf[idx]);
- }
- }
- return esp_lcd_panel_draw_bitmap(s_panel, 0, 0,
- PANEL_H_ACTIVE, PANEL_V_ACTIVE,
- s_rot_buf);
-}
diff --git a/main/display.h b/main/display.h
index 3119a60..9092efb 100644
--- a/main/display.h
+++ b/main/display.h
@@ -27,14 +27,6 @@ esp_err_t display_set_brightness(uint8_t brightness_0_100);
esp_err_t display_sleep(void);
esp_err_t display_wake(void);
-// Paint a solid RGB565 color to the entire framebuffer + flush.
-// Used by M3 for the test pattern and by local_screens for the IP and
-// loading screens (M8).
-esp_err_t display_fill(uint16_t rgb565);
-
-// Show a deterministic test pattern (vertical color bars). M3 acceptance.
-esp_err_t display_test_pattern(void);
-
// Blit an RGB565 source image to the panel, applying the current
// orientation. Source dimensions must match the effective resolution:
// portrait -> src is 480x800 (rotated 90° CW into the 800x480 panel)
diff --git a/main/http_api.c b/main/http_api.c
index dce57bb..028d3a7 100644
--- a/main/http_api.c
+++ b/main/http_api.c
@@ -24,16 +24,6 @@ static const char *TAG = "http_api";
#define MAX_BODY_BYTES 2048
#define MIN_IDLE_TIMEOUT 5000
-static const char *state_name(viewport_run_state_t s)
-{
- return (s == VIEWPORT_STATE_AWAKE) ? "awake" : "asleep";
-}
-
-static const char *orientation_name(viewport_orientation_t o)
-{
- return (o == VIEWPORT_ORIENTATION_LANDSCAPE) ? "landscape" : "portrait";
-}
-
// ============================================================================
// GET /state
// ============================================================================
@@ -54,7 +44,8 @@ static esp_err_t state_get_handler(httpd_req_t *req)
: cJSON_CreateNull());
cJSON_AddStringToObject(root, "version", VIEWPORT_VERSION);
cJSON_AddBoolToObject (root, "configured", st->configured);
- cJSON_AddStringToObject(root, "state", state_name(st->state));
+ cJSON_AddStringToObject(root, "state",
+ (st->state == VIEWPORT_STATE_AWAKE) ? "awake" : "asleep");
cJSON_AddNumberToObject(root, "uptime_ms", (double)up_ms);
cJSON_AddItemToObject (root, "last_frame_ms_ago",
last_age_ms < 0 ? cJSON_CreateNull()
@@ -97,7 +88,8 @@ static esp_err_t config_get_handler(httpd_req_t *req)
st->scrypted_url[0] ? cJSON_CreateString(st->scrypted_url)
: cJSON_CreateNull());
cJSON_AddNumberToObject(root, "idle_timeout_ms", (double)st->idle_timeout_ms);
- cJSON_AddStringToObject(root, "orientation", orientation_name(st->orientation));
+ cJSON_AddStringToObject(root, "orientation",
+ (st->orientation == VIEWPORT_ORIENTATION_LANDSCAPE) ? "landscape" : "portrait");
cJSON_AddNumberToObject(root, "brightness", (double)st->brightness);
viewport_state_unlock();
@@ -254,10 +246,7 @@ static esp_err_t config_post_handler(httpd_req_t *req)
}
if (brightness_changed && display_is_up()) {
- viewport_state_lock();
- uint8_t b = viewport_state_get()->brightness;
- viewport_state_unlock();
- display_set_brightness(b);
+ display_set_brightness(bright);
}
if (name_or_orient_changed) {
mdns_service_refresh();
@@ -317,15 +306,6 @@ static esp_err_t respond_status(httpd_req_t *req, const char *status, const char
return httpd_resp_send(req, body, body ? HTTPD_RESP_USE_STRLEN : 0);
}
-static void expected_dims(uint16_t *w, uint16_t *h)
-{
- viewport_state_lock();
- bool portrait = (viewport_state_get()->orientation == VIEWPORT_ORIENTATION_PORTRAIT);
- viewport_state_unlock();
- if (portrait) { *w = 480; *h = 800; }
- else { *w = 800; *h = 480; }
-}
-
static esp_err_t frame_post_handler(httpd_req_t *req)
{
// Content-Type must be image/jpeg.
@@ -383,7 +363,7 @@ static esp_err_t frame_post_handler(httpd_req_t *req)
}
uint16_t want_w, want_h;
- expected_dims(&want_w, &want_h);
+ viewport_state_effective_dims(&want_w, &want_h);
if (w != want_w || h != want_h) {
viewport_state_lock();
viewport_state_get()->decode_errors++;
@@ -439,11 +419,7 @@ esp_err_t http_api_start(void)
cfg.server_port = 80;
cfg.max_uri_handlers = 8;
cfg.lru_purge_enable = true;
- // Default 4 KiB is tight: /config alone has ~2.4 KiB of stack locals
- // (2 KiB body buffer + 256 B scrypted URL + 64 B name + cJSON frames)
- // and POST /frame pushes a JPEG header onto the stack too. 8 KiB gives
- // both handlers comfortable headroom without doubling RAM usage.
- cfg.stack_size = 8192;
+ cfg.stack_size = 8192; // POST /config alone has ~2.4 KiB of stack locals
httpd_handle_t server = NULL;
ESP_RETURN_ON_ERROR(httpd_start(&server, &cfg), TAG, "httpd_start");
diff --git a/main/local_screens.c b/main/local_screens.c
index 7459d9a..f25754d 100644
--- a/main/local_screens.c
+++ b/main/local_screens.c
@@ -84,16 +84,6 @@ static void clear(uint16_t color)
for (int i = 0; i < MAX_BUF_PX; ++i) s_fb[i] = color;
}
-// Get current effective dimensions (rotated dims for portrait).
-static void effective_dims(uint16_t *w, uint16_t *h)
-{
- viewport_state_lock();
- viewport_orientation_t o = viewport_state_get()->orientation;
- viewport_state_unlock();
- if (o == VIEWPORT_ORIENTATION_PORTRAIT) { *w = 480; *h = 800; }
- else { *w = 800; *h = 480; }
-}
-
// Draw a single 8x8 glyph at (ox, oy) into the effective-dim buffer with
// integer scale. Pixels outside the buffer are clipped.
static void draw_char(uint16_t fb_w, uint16_t fb_h, int ox, int oy,
@@ -199,26 +189,6 @@ void local_screens_overlay_dismiss(void)
if (display_is_up()) display_sleep();
}
-// Format `n` as a compact value with K / M suffix for thousands / millions.
-// Output max 8 chars, e.g. "168k", "30M", "1234".
-static void fmt_bytes(char *out, size_t cap, uint32_t n)
-{
- if (n >= 1000000) snprintf(out, cap, "%um", (unsigned)(n / 1000000));
- else if (n >= 1000) snprintf(out, cap, "%uk", (unsigned)(n / 1000));
- else snprintf(out, cap, "%u", (unsigned)n);
-}
-
-// Format an uptime in milliseconds as "h:mm:ss" or "m:ss".
-static void fmt_uptime(char *out, size_t cap, uint64_t ms)
-{
- uint64_t s = ms / 1000;
- unsigned hh = (unsigned)(s / 3600);
- unsigned mm = (unsigned)((s % 3600) / 60);
- unsigned ss = (unsigned)(s % 60);
- if (hh > 0) snprintf(out, cap, "%u:%02u:%02u", hh, mm, ss);
- else snprintf(out, cap, "%u:%02u", mm, ss);
-}
-
esp_err_t local_screens_show_info(void)
{
if (!s_fb) return ESP_ERR_INVALID_STATE;
@@ -293,9 +263,25 @@ esp_err_t local_screens_show_info(void)
else snprintf(idle_str, sizeof(idle_str), "%us",
(unsigned)(idle_ms / 1000));
- char up_str[16]; fmt_uptime(up_str, sizeof(up_str), uptime_ms);
- char heap_str[12]; fmt_bytes(heap_str, sizeof(heap_str), free_heap);
- char psram_str[12]; fmt_bytes(psram_str, sizeof(psram_str), free_psram);
+ // Compact "h:mm:ss" / "m:ss" uptime
+ char up_str[20];
+ uint64_t up_s = uptime_ms / 1000;
+ unsigned hh = (unsigned)(up_s / 3600),
+ mm = (unsigned)((up_s % 3600) / 60),
+ ss = (unsigned)(up_s % 60);
+ if (hh) snprintf(up_str, sizeof(up_str), "%u:%02u:%02u", hh, mm, ss);
+ else snprintf(up_str, sizeof(up_str), "%u:%02u", mm, ss);
+
+ // Compact byte counts with k / M suffix
+ char heap_str[12], psram_str[12];
+ #define FMT_BYTES(buf, n) do { \
+ if ((n) >= 1000000) snprintf((buf), sizeof(buf), "%uM", (unsigned)((n)/1000000)); \
+ else if ((n) >= 1000) snprintf((buf), sizeof(buf), "%uk", (unsigned)((n)/1000)); \
+ else snprintf((buf), sizeof(buf), "%u", (unsigned)(n)); \
+ } while (0)
+ FMT_BYTES(heap_str, free_heap);
+ FMT_BYTES(psram_str, free_psram);
+ #undef FMT_BYTES
const char *state_str = (state == VIEWPORT_STATE_AWAKE) ? "awake" : "asleep";
@@ -327,7 +313,7 @@ esp_err_t local_screens_show_info(void)
// Auto-scale: largest scale where the longest line fits within 90% of
// width and all lines + spacing fit within 90% of height.
uint16_t w, h;
- effective_dims(&w, &h);
+ viewport_state_effective_dims(&w, &h);
size_t longest = 0;
for (int i = 0; i < n_lines; ++i) {
@@ -363,7 +349,7 @@ esp_err_t local_screens_show_loading(void)
if (!s_fb) return ESP_ERR_INVALID_STATE;
uint16_t w, h;
- effective_dims(&w, &h);
+ viewport_state_effective_dims(&w, &h);
int scale = (w < 800) ? 4 : 5;
int line_h = 8 * scale;
int y = (h - line_h) / 2;
diff --git a/main/mdns_service.c b/main/mdns_service.c
index d389161..21cd464 100644
--- a/main/mdns_service.c
+++ b/main/mdns_service.c
@@ -14,48 +14,30 @@ static const char *SERVICE = "_scrypted-viewport";
static const char *PROTO = "_tcp";
static const uint16_t PORT = 80;
-// Pull the current hostname + TXT values from viewport_state under the lock.
-static void snapshot_state(char *hostname, size_t host_cap,
- const char **resolution,
- const char **orientation,
- char *name, size_t name_cap)
-{
- viewport_state_lock();
- viewport_state_t *st = viewport_state_get();
-
- if (st->viewport_name[0]) {
- snprintf(hostname, host_cap, "viewport-%s", st->viewport_name);
- } else {
- snprintf(hostname, host_cap, "viewport");
- }
- *resolution = viewport_state_resolution_str();
- *orientation = (st->orientation == VIEWPORT_ORIENTATION_PORTRAIT)
- ? "portrait" : "landscape";
- snprintf(name, name_cap, "%s", st->viewport_name[0] ? st->viewport_name : "");
-
- viewport_state_unlock();
-}
-
-static esp_err_t apply_hostname(void)
+// Pull hostname + TXT values from viewport_state under one lock acquisition,
+// then push them at the mDNS service. mdns_service_add() rejects with
+// INVALID_ARG if the hostname isn't set, so order matters on first apply.
+static esp_err_t apply_state(bool include_hostname)
{
char hostname[80];
- const char *resolution, *orientation;
char name[64];
- snapshot_state(hostname, sizeof(hostname),
- &resolution, &orientation,
- name, sizeof(name));
- return mdns_hostname_set(hostname);
-}
-
-static esp_err_t apply_txt(void)
-{
- char hostname[80];
const char *resolution, *orientation;
- char name[64];
- snapshot_state(hostname, sizeof(hostname),
- &resolution, &orientation,
- name, sizeof(name));
+ viewport_state_lock();
+ viewport_state_t *st = viewport_state_get();
+ snprintf(hostname, sizeof(hostname), "viewport%s%s",
+ st->viewport_name[0] ? "-" : "",
+ st->viewport_name[0] ? st->viewport_name : "");
+ snprintf(name, sizeof(name), "%s",
+ st->viewport_name[0] ? st->viewport_name : "");
+ resolution = viewport_state_resolution_str();
+ orientation = (st->orientation == VIEWPORT_ORIENTATION_PORTRAIT)
+ ? "portrait" : "landscape";
+ viewport_state_unlock();
+
+ if (include_hostname) {
+ ESP_RETURN_ON_ERROR(mdns_hostname_set(hostname), TAG, "hostname_set");
+ }
mdns_txt_item_t txt[] = {
{ "version", VIEWPORT_VERSION },
{ "resolution", resolution },
@@ -68,21 +50,21 @@ static esp_err_t apply_txt(void)
esp_err_t mdns_service_start(void)
{
- // Order matters: mdns_service_add() rejects with INVALID_ARG if the
- // hostname isn't set yet. So: init -> hostname -> service_add -> TXT.
- ESP_RETURN_ON_ERROR(mdns_init(), TAG, "mdns_init");
- ESP_RETURN_ON_ERROR(apply_hostname(), TAG, "hostname_set");
+ char hostname[80];
+ viewport_state_lock();
+ viewport_state_t *st = viewport_state_get();
+ snprintf(hostname, sizeof(hostname), "viewport%s%s",
+ st->viewport_name[0] ? "-" : "",
+ st->viewport_name[0] ? st->viewport_name : "");
+ viewport_state_unlock();
+
+ ESP_RETURN_ON_ERROR(mdns_init(), TAG, "mdns_init");
+ ESP_RETURN_ON_ERROR(mdns_hostname_set(hostname), TAG, "hostname_set");
ESP_RETURN_ON_ERROR(
mdns_service_add(NULL, SERVICE, PROTO, PORT, NULL, 0),
TAG, "service_add");
- ESP_RETURN_ON_ERROR(apply_txt(), TAG, "txt_set");
+ ESP_RETURN_ON_ERROR(apply_state(false), TAG, "txt_set");
- char hostname[80];
- const char *resolution, *orientation;
- char name[64];
- snapshot_state(hostname, sizeof(hostname),
- &resolution, &orientation,
- name, sizeof(name));
ESP_LOGI(TAG, "mDNS up — %s.local advertising %s.%s.local on :%u",
hostname, SERVICE, PROTO, PORT);
return ESP_OK;
@@ -90,6 +72,5 @@ esp_err_t mdns_service_start(void)
esp_err_t mdns_service_refresh(void)
{
- ESP_RETURN_ON_ERROR(apply_hostname(), TAG, "hostname_set");
- return apply_txt();
+ return apply_state(true);
}
diff --git a/main/net_eth.c b/main/net_eth.c
index f4dad8f..28ef782 100644
--- a/main/net_eth.c
+++ b/main/net_eth.c
@@ -150,11 +150,6 @@ esp_err_t net_eth_wait_for_ip(uint32_t timeout_ms)
return (bits & BIT_GOT_IP) ? ESP_OK : ESP_ERR_TIMEOUT;
}
-bool net_eth_is_up(void)
-{
- return (xEventGroupGetBits(s_event_group) & BIT_GOT_IP) != 0;
-}
-
const char *net_eth_get_ip_str(void)
{
return s_ip_str;
diff --git a/main/net_eth.h b/main/net_eth.h
index 23f2450..212e7f7 100644
--- a/main/net_eth.h
+++ b/main/net_eth.h
@@ -1,10 +1,8 @@
#pragma once
-#include <stdbool.h>
#include <stdint.h>
#include "esp_err.h"
esp_err_t net_eth_init(void);
esp_err_t net_eth_wait_for_ip(uint32_t timeout_ms);
-bool net_eth_is_up(void);
const char *net_eth_get_ip_str(void);
diff --git a/main/nvs_config.c b/main/nvs_config.c
index f6a9805..7f7586c 100644
--- a/main/nvs_config.c
+++ b/main/nvs_config.c
@@ -104,16 +104,3 @@ done:
return err;
}
-esp_err_t nvs_config_reset(void)
-{
- nvs_handle_t h;
- esp_err_t err = nvs_open(NS, NVS_READWRITE, &h);
- if (err == ESP_ERR_NVS_NOT_FOUND) return ESP_OK;
- if (err != ESP_OK) return err;
-
- nvs_erase_all(h);
- err = nvs_commit(h);
- nvs_close(h);
- ESP_LOGI(TAG, "NVS config cleared");
- return err;
-}
diff --git a/main/nvs_config.h b/main/nvs_config.h
index 7688d81..b90577d 100644
--- a/main/nvs_config.h
+++ b/main/nvs_config.h
@@ -11,6 +11,3 @@ esp_err_t nvs_config_load(void);
// Persist the current viewport_state to NVS atomically. The caller is expected
// to have already mutated viewport_state under viewport_state_lock().
esp_err_t nvs_config_save(void);
-
-// Clear all persisted config. Caller is responsible for rebooting.
-esp_err_t nvs_config_reset(void);
diff --git a/main/state_machine.c b/main/state_machine.c
index a4d4dab..0a6d491 100644
--- a/main/state_machine.c
+++ b/main/state_machine.c
@@ -12,21 +12,15 @@ static const char *TAG = "state";
static esp_timer_handle_t s_idle_timer;
-static void arm_idle_timer_unlocked(void)
+// ms = idle_timeout_ms snapshotted under the caller's state lock.
+// ms == 0 disables the timer (caller's idle_timeout_ms feature).
+static void arm_idle_timer(uint32_t ms)
{
- viewport_state_lock();
- uint32_t ms = viewport_state_get()->idle_timeout_ms;
- viewport_state_unlock();
- if (ms == 0) return;
esp_timer_stop(s_idle_timer);
+ if (ms == 0) return;
esp_timer_start_once(s_idle_timer, (uint64_t)ms * 1000ULL);
}
-static void disarm_idle_timer(void)
-{
- esp_timer_stop(s_idle_timer);
-}
-
static void idle_timer_fired(void *arg)
{
ESP_LOGI(TAG, "idle timer expired — sleeping");
@@ -56,6 +50,7 @@ esp_err_t state_machine_set(viewport_run_state_t target)
}
st->state = target;
bool configured = st->configured;
+ uint32_t idle_ms = st->idle_timeout_ms;
viewport_state_unlock();
if (target == VIEWPORT_STATE_AWAKE) {
@@ -67,10 +62,10 @@ esp_err_t state_machine_set(viewport_run_state_t target)
if (configured) local_screens_show_loading();
else local_screens_show_info();
}
- arm_idle_timer_unlocked();
+ arm_idle_timer(idle_ms);
ESP_LOGI(TAG, "AWAKE (%s)", configured ? "configured" : "no scrypted URL");
} else {
- disarm_idle_timer();
+ arm_idle_timer(0);
if (display_is_up()) display_sleep();
ESP_LOGI(TAG, "ASLEEP");
}
@@ -80,9 +75,11 @@ esp_err_t state_machine_set(viewport_run_state_t target)
void state_machine_frame_painted(void)
{
viewport_state_lock();
- bool awake = (viewport_state_get()->state == VIEWPORT_STATE_AWAKE);
+ viewport_state_t *st = viewport_state_get();
+ bool awake = (st->state == VIEWPORT_STATE_AWAKE);
+ uint32_t idle_ms = st->idle_timeout_ms;
viewport_state_unlock();
- if (awake) arm_idle_timer_unlocked();
+ if (awake) arm_idle_timer(idle_ms);
}
void state_machine_set_local(viewport_run_state_t target)
diff --git a/main/viewport_state.c b/main/viewport_state.c
index 3ae8f81..7ddf737 100644
--- a/main/viewport_state.c
+++ b/main/viewport_state.c
@@ -13,8 +13,6 @@ void viewport_state_init(void)
{
memset(&s_state, 0, sizeof(s_state));
s_state.configured = false;
- // State is always AWAKE or ASLEEP. UNCONFIGURED is reported via the
- // `configured` flag, not as a state value. Boot is always asleep.
s_state.state = VIEWPORT_STATE_ASLEEP;
s_state.brightness = 80;
s_state.idle_timeout_ms = 60000;
@@ -46,3 +44,12 @@ const char *viewport_state_resolution_str(void)
? "480x800"
: "800x480";
}
+
+void viewport_state_effective_dims(uint16_t *w, uint16_t *h)
+{
+ viewport_state_lock();
+ viewport_orientation_t o = s_state.orientation;
+ viewport_state_unlock();
+ if (o == VIEWPORT_ORIENTATION_PORTRAIT) { *w = 480; *h = 800; }
+ else { *w = 800; *h = 480; }
+}
diff --git a/main/viewport_state.h b/main/viewport_state.h
index 3f6147f..4e6fbd6 100644
--- a/main/viewport_state.h
+++ b/main/viewport_state.h
@@ -46,3 +46,8 @@ void viewport_state_unlock(void);
// on the current orientation. Caller-owned static storage; safe to read
// without the lock (atomic snapshot).
const char *viewport_state_resolution_str(void);
+
+// Effective width/height for the current orientation: portrait = 480x800
+// (rotated software-side from the panel's 800x480), landscape = 800x480.
+// Acquires the state lock internally.
+void viewport_state_effective_dims(uint16_t *w, uint16_t *h);