Commit Graph

8 Commits

Author SHA1 Message Date
Adolfo Reyna 6f095081d2 fix(rlcd): freeze after flash - disable auto-screensaver on monochrome + reduce video stream hog
Frozen screen caused by 2 runtime issues after init fixes 3770ac89:
- BouncingBalls screensaver full_refresh SPI at 10MHz for 300x400 takes ~100ms per frame, hogs LVGL lock -> UI appears frozen stuck on weird image
- MCP video stream task vTaskDelay 5ms streaming holds LVGL lock too often -> starves UI and screenshot (could not acquire LVGL lock)

Fix:
- DisplayIdle tick: for !supportsBacklight (RLCD) don't auto-activate screensaver, only handle wake. Prevents heavy animation entering automatically after timeout (SD may have 60s setting).
- McpSystem video stream: 50ms->100ms idle, 5ms->30ms streaming to release LVGL lock
- Screenshot API: 100ms->500ms lock timeout, task 50->300ms for slow SPI

Build 0x2b79e0 RLCD, flashed.

Co-Authored-By: internal-model
2026-07-11 22:00:00 -04:00
Adolfo Reyna 2dc216fb7b fix: MCP settings persistence + WebServer/DevServer coexistence + screensaver charging toggle
- McpSettings was hardcoded to /data/service/mcp/settings.properties,
  but ES3C28P uses storage.userDataLocation=SD so user data lives on
  /sdcard/tactility/. Settings appeared to save but on reload returned
  default false -> "enable and when I go back shows disabled".
  Fixed to use getUserDataPath()+"/settings/mcp.properties" pattern
  consistent with DisplaySettings/WebServerSettings, with
  findOrCreateParentDirectory() and isFile() guard.

- HttpServer ctrl_port collision: ESP-IDF default 32768 used by both
  WebServer (80) and DevelopmentService (6666). Second httpd_start()
  failed silently -> dashboard up but /api/mcp 404 and :6666 refused.
  Fixed with unique ctrl_port = 32768 + (port % 1000).
  Added CONFIG_HTTPD_MAX_URI_HANDLERS=20 (default 8 < 9 needed for
  7 handlers + 2 internal).

- DevService stack 5120 -> 8192 for /app/install handling.
- McpSystem video stream task stack 4096 -> 8192 and idle yield 50ms
  (was 5ms always) to avoid CPU starvation blocking httpd tasks.
  On RLCD, timer must always run: DisplayIdle early return on
  !supportsBacklightDuty() broke MCP manual activation (cachedSettings
  not loaded, backlight duty 0). Fixed to always load settings +
  start timer, log RLCD detection, guard setBacklightDuty with
  supportsBacklightDuty() and fallback duty 255.

- DisplaySettings: add disableScreensaverWhenCharging bool, persisted,
  with UI toggle in Display app (Settings->Display) using
  PowerDevice::IsCharging check via findDevices callback.
  When charging and flag enabled, screensaver activation skipped,
  and if already dimmed, wake on charging.

- ES3C28P Power driver: GPIO9 ADC1_CH8 2x divider 2500-4200mV spec from
  ~/Downloads official docs, TP4054 CHRG not connected to GPIO, so
  IsCharging inferred via voltage thresholds (<500mV no battery USB
  or >5000mV wall powered, >=4150mV high) + rising trend.

Verified: flashed es3c28p to /dev/cu.usbmodem101 (192.168.68.113),
WiFi FamReynaMesh RSSI -59, dashboard 200, :6666/info now works,
/api/mcp returns disabled correctly until enabled, persists to SD.
2026-07-11 20:26:01 -04:00
Adolfo Reyna 300ddb3a7f feat: integrate MCP and ES3C28P audio support with upstream compatibility updates 2026-07-04 15:41:37 -04:00
Adolfo Reyna e0a92ea50e feat: migrate all large MCP server allocations and MP3 buffers to PSRAM (SPIRAM) 2026-06-27 10:04:30 -04:00
Adolfo Reyna 0ae9b43f87 fix: increase HTTP server stack size to 16KB to prevent MP3 decode stack overflow and reset I2S controller on stop to eliminate static noise 2026-06-27 10:00:36 -04:00
Adolfo Reyna 598af546fd fix: ensure backlight turns back on during startMcpScreensaver and invalidate canvas on drawText 2026-06-27 09:41:40 -04:00
Adolfo Reyna cd921e1aa9 feat: implement MCP drawing as screensaver instead of standalone app
- Add ScreensaverType::McpScreen to DisplaySettings enum, toString/fromString
- Add 'MCP Screen' option to the Display settings screensaver dropdown
- New McpScreensaver (Screensaver subclass): creates full-screen lv_canvas on
  the overlay, allocates framebuffer in SPIRAM, registers canvas pointer in
  McpSystemState, shows 'Waiting for LLM...' until first draw command arrives
- Wire McpScreensaver into DisplayIdle::activateScreensaver() switch
- McpSystem::ensureOverrideScreen() now calls displayidle::findService()->
  startScreensaver() instead of launching McpOverrideApp — canvas appears
  automatically on any LLM draw command
- Remove McpOverrideApp (replaced by screensaver), deregister from Tactility.cpp
- Remove mcpOverrideEnabled from McpSettings — no longer needed
- Simplify McpSettingsApp: remove Screen Override toggle, update info text to
  direct users to Settings -> Display -> Screensaver -> MCP Screen
2026-06-27 09:17:50 -04:00
Adolfo Reyna 41004a3c6f feat: integrate MCP server and screen override into system firmware
- Add McpSettings (load/save mcpEnabled, mcpOverrideEnabled to /data/service/mcp/settings.properties)
- Add McpSystem: global state, canvas drawing (RGB565, BMP, PBM, text), I2S audio (WAV, MP3 via minimp3, tone, record)
- Add McpHandler: unauthenticated POST /api/mcp (JSON-RPC 2.0, 13 tools) and POST /api/screen/raw endpoints
- Route MCP endpoints before Basic Auth check in WebServerService::handleApiPost
- Start HTTP server at boot if either webServerEnabled OR mcpEnabled is set
- Fix setEnabled: start unconditionally when called with true; only stop if both WS and MCP are disabled
- Add McpSettingsApp (Settings category): toggle MCP service + screen override, show live endpoint URL
- Add McpOverrideApp (appId one.tactility.mcpscreen): full-screen LVGL canvas for LLM-driven display override
- Register both new apps in Tactility.cpp
2026-06-26 23:02:09 -04:00