src.nth.io/

summaryrefslogtreecommitdiff
path: root/main/touch.c
AgeCommit message (Collapse)AuthorFilesLines
4 daysmain: code-review fixes — brightness units, OTA stall cap, stats + lockingLuke Hoersten1-2/+1
- display: s_last_pwm cached the raw 0-100 percentage at init but display_wake writes it straight to REG_PWM (0-255 duty) — first wake ran visibly dim until a /config brightness change. Shared pct_to_duty helper now converts in both paths. - http_api: cap consecutive OTA recv timeouts (a stalled client spun forever holding s_ota_in_progress, wedging OTA until reboot); cap viewport name at 54 chars so viewport-<name> fits the 63-byte mDNS label; log mdns_service_refresh failures; /state builds JSON from a snapshot instead of holding the state lock across ~25 cJSON allocs; respond_400 delegates to respond_status. - stream_server: bytes_in_window now counts painted frames only (frames discarded while asleep inflated the first post-wake window's MB/s, avg-jpeg and chunk/wire averages; recv_bytes folded in); so_rcvbuf carried into the stats snapshot under the mux; drop dead HEADER_BYTES; merge read_body_instrumented into read_n. - state_machine: transition mutex serializes concurrent wake/sleep (display side-effects ran after the state lock dropped, so racing callers could leave the backlight contradicting st->state); wake-path placeholder paint now takes the decoder lock like the stream path (concurrent esp_lcd_panel_draw_bitmap from two tasks isn't safe). - local_screens: overlay paint takes the decoder lock too; check the overlay timer create; panel dims from viewport_state.h. - jpeg_decoder: try_lock before init returns busy instead of passing a NULL semaphore to xSemaphoreTake. - net_eth: clear cached IP string on link down (stale /state + info). - dead code: display_present_bgr888, TOUCH_FT5426_ADDR, touch s_task, JPEG_DECODER_MAX_OUTPUT_BYTES; doc drift in nvs_config.h / jpeg_decoder.h / app_main flag legend.
2026-06-14Default name = MAC; brief wake on boot; drop dead touch defencesLuke Hoersten1-47/+9
- Seed viewport_name with the full base MAC, colons stripped (e8:f6:0a:e0:90:94 → "e8f60ae09094"). Stable across reboots, globally unique, 12 alphanumeric chars — well inside the mDNS hostname limit even with the "viewport-" prefix. - Add a mac_str field to viewport_state and expose it as the new "mac" key in GET /state and as a "mac" line on the info screen. - "Configured" no longer requires a viewport_name (it always has the MAC default); the scrypted URL alone gates outbound POSTs and the loading-vs-info screen choice. - Strip viewport_name[0] fallbacks in http_api / mdns / local_screens now that the field is never empty. - Replace the wake-on-boot-stays-on behaviour with a ~600 ms flash followed by sleep — long enough for the FT5426 touch IC to come out of its initial unresponsive state, short enough that an idle device doesn't burn the backlight. - Drop the touch defensive cruft added when we were chasing a PoE-power theory: the DEV_MODE=0x00 write at init, the touch_reset_pulse() call at init, and the runtime wedge-self-heal in the polling loop didn't actually fix anything — the wake-on-boot flash did. Also delete the display_touch_reset_pulse() helper since it now has zero callers.
2026-06-14touch: wake on boot — FT5426 only reports while LCD is streaming + litLuke Hoersten1-32/+47
Symptom: after a few cleanup cycles + power cycles, fresh boots left touch dead — the FT5426 ack'd, polling read TD_STATUS=0x00 cleanly, but taps never registered. Curl-waking the screen made touch work again instantly; tapping the dark backlight-off panel did nothing. Root cause: on this panel the FT5426 firmware only reports contact points while the DSI link is actively streaming with the backlight on. Booting straight into ASLEEP per the spec leaves taps silently unread, and there's no built-in way to wake without touch (no hardware button on this board — see prior commit). The fix is to wake on boot; the idle timer cuts back to sleep after idle_timeout_ms if nothing happens. Also defensively write DEV_MODE=0x00 (Working Mode) at touch_init, and add a runtime self-heal: if the polling loop sees stuck TD_STATUS above the 5-touch ceiling for ~3 s, pulse PC_RST_TP_N via the panel MCU and retry. Combined with display_touch_reset_pulse() the chip recovers from cold-boot wedges without manual intervention.
2026-06-14touch: retry + hard-reset when FT5426 boots into wedged 0xff stateLuke Hoersten1-2/+27
After a long bench session of taps + power cycles, the FT5426 on this unit started returning dev_mode=0xff on every read. The polling loop interpreted that as 15 simultaneous touches forever (td_status bits 0..3 all set), wedged `was_down=true` permanently, and no tap or long-press ever fired — the screen looked dead. Two layers of defence in touch_init: 1. retry the dev_mode read up to 10 × 30 ms in case the chip is just slow to come up after PC_RST_TP_N is released. 2. if still stuck, pulse PC_RST_TP_N via a new display_touch_reset_pulse() helper (drop reset for 20 ms then release + 50 ms settle), then retry the read another 10 × 30 ms. Plus a polling-loop sanity check: an FT5x06 supports max 5 simultaneous points, so a TD_STATUS lower-nibble value > 5 is bogus and the poll cycle is skipped. That keeps a wedged chip from producing phantom "15 touches" reports if it slips into 0xff during runtime. If both attempts still report 0xff, we log loudly and let the polling task run — it harmlessly drops cycles via the >5 sanity check. Wake still works via POST /state from Scrypted; this only disables touch gestures on a hardware-stuck boot.
2026-06-14Info screen: full /config + /state dump, replaces identity screenLuke Hoersten1-3/+3
Previously the 4-line "identity" screen showed only viewport name, mDNS host, IP, and state. Expanded to 15 lines covering the full GET /config + GET /state output (name, host, ip, state, configured, scrypted, orientation, brightness, idle, fw, uptime, frames, errs, free heap, free PSRAM), label/value pairs left-aligned with auto-scaled font. Renames "identity" → "info" throughout — symbol, log messages, README/TESTING references. Also: - Move the info-screen render's big locals (~1.6 KiB: lines[16][80] + scrypt[256] + vp_name[64]) to BSS. The touch task's 3 KiB stack was overflowing on every long-press, leaving whatever frame was previously on the panel — gave the appearance of a "blue screen" after the M5 test pattern. - Drop the ≥5 s touch factory-reset gesture and remove all stale references to it in docs and comments. NVS wipe is now a USB-side `idf.py erase-flash` operation only. - M5 follow-up TODO in jpeg_decoder.c: solid green renders ~black and solid blue renders green; not a byte-order issue (BGR setting turns red into blue). Tracked as a known M5 gap.
2026-06-14touch: drop factory-reset gestureLuke Hoersten1-22/+5
Holding the touch panel for 5 s to wipe NVS is dangerous (easy to trigger by accident — phone resting on the panel, kids, etc.) and useless as a recovery path (factory reset alone doesn't undo a bricked config; a USB reflash does). Factory reset should be an explicit API or USB-side action. Touch gestures now: tap = toggle wake/sleep, ≥1.5 s hold = identity overlay.
2026-06-14M3 done: drop boot test, fold BOOT button into touch long-pressLuke Hoersten1-43/+60
The Waveshare ESP32-P4-ETH board exposes BOOT on GPIO 35, but at runtime that pin is owned by the EMAC TXD1 signal. No usable GPIO is wired to a separate user button, so the BOOT-button task could never fire. Move both BOOT-button behaviours onto the touch panel: - ≥1.5s hold → 15s identity overlay (was BOOT short-press) - ≥5s hold → factory reset (was BOOT long-hold) Short tap (<500ms) still toggles wake/sleep. Long-press fires while the finger is still down so the user gets immediate feedback at each threshold. Also strip the R/G/B 6 s boot test sequence — the panel now renders correctly, so it's no longer useful diagnostically. Boot subsystem flags drop the trailing B column: [EMHDJT].
2026-06-14M3 WIP: DSI bring-up + state machine + identity overlayLuke Hoersten1-3/+7
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.
2026-06-13M7: touch + outbound /state POST to ScryptedLuke Hoersten1-0/+123
state_client.{h,c}: - Worker task drains a depth-1 queue (xQueueOverwrite gives the replace-on-full semantics from the spec — in-flight POST is never cancelled; the next queued entry is overwritten by newer state). - esp_http_client POST to <scrypted>/state with Content-Type application/ json, User-Agent ScryptedViewport/<version>, Connection: close, 1s timeout. Body: {"viewport":"<name>","state":"wake"|"sleep"}. - Any non-2xx or transport error increments state_post_failures and is otherwise ignored. Silently drops if no Scrypted URL is configured. touch.{h,c}: - FT5426 capacitive touch on the shared I2C bus at 0x38. - 30ms polling task; tracks down/up transitions, detects taps as down-then-up within 500ms with a 150ms debounce. - On tap, toggles wake/sleep via state_machine_set_local(), which drives the local transition AND fires state_client_post() at Scrypted. state_machine adds state_machine_set_local(): runs the same transition as state_machine_set() then enqueues an outbound POST. Idle-timer expiry now uses this path so Scrypted sees idle-driven sleeps too (the spec's "tighten the race with /frame 409" path stays in place as the fallback). display.h exposes display_i2c_bus(); touch.c uses it instead of re-initializing the same I2C port. app_main starts state_client right after the state machine and starts touch after display init (touch is skipped if display isn't up since they share the bus). CMakeLists.txt: add esp_http_client to REQUIRES. Build clean against ESP-IDF 5.4 (binary ~860 KB; jumped ~210 KB from M6 because esp_http_client + cJSON path pulls in tcp_transport, mbedtls, http_parser). TESTING.md M7: flask-based test receiver, tap dispatch verification, failure-path check (kill receiver, confirm counter increments), queue-coalescing behavior, no-POST-on-Scrypted-initiated, no-POST- when-unconfigured.