Three bugs and two UX defects found on review, plus hardening: - The control loop fed the task watchdog then slept exactly the watchdog period (both 10s), tripping the TWDT fractionally late on every single iteration. Sleep is now sliced 1s with a reset per slice. Also set CONFIG_ESP_TASK_WDT_PANIC=y - the sdkconfig comment claimed a hung task panics the chip, but nothing actually made that true. - The LVGL flush called draw_bitmap (which only queues the framebuffer switch) and released LVGL immediately, letting it render the next frame into the buffer still being scanned out - the exact PRD 8.2 race the double-buffer design exists to prevent. display_present_frame() now blocks on a vsync handshake until the swap has latched. - WiFi reconnect slept up to 30s inside the system event handler, stalling all queued WiFi/IP events. Moved to an esp_timer. - The setpoint label, arc, and mode/room lines rendered the control loop's copy of state, which refreshes every 10s - every knob detent looked dead for up to 10 seconds. The UI now reads settings live; when the fallback ladder clamps the setpoint it shows both values. Room-select focus now shows which room is being selected. - z2m ISO_8601_local timestamps carry a UTC offset the parser ignored, which would shift apparent reading age by the local offset (5-6h in the US) and permanently trip the fallback ladder. Offset is now honoured. - Suppressed the cosmetic "control loop stopped" fault in the window between relay_init and the control task's first call-in at boot. - Explicit pullups on the encoder A/B lines. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
2.4 KiB
C
68 lines
2.4 KiB
C
/*
|
|
* ST7701S + RGB panel, 480x480 round.
|
|
*
|
|
* Two things about the configuration here are deliberate and load-bearing:
|
|
*
|
|
* No bounce buffers. The bounce-buffer refill ISR reads PSRAM, which shares
|
|
* the cache with flash on the S3, so any NVS write while the panel runs faults
|
|
* with "Cache disabled but cached memory region accessed" (PRD 8.2). This
|
|
* project writes settings to NVS at runtime, so instead of pausing the panel
|
|
* around every write we simply do not use bounce buffers: the LCD DMA reads
|
|
* the framebuffer out of PSRAM directly and never touches the cache.
|
|
*
|
|
* Two framebuffers. Writing into the framebuffer currently being scanned
|
|
* races the LCD's reads, and the corruption persists because LVGL does not
|
|
* know those pixels are wrong and never reinvalidates them (PRD 8.2). With
|
|
* num_fbs=2 the panel driver swaps whole buffers instead.
|
|
*
|
|
* 480x480x2 bytes x 2 buffers is ~920KB of the 8MB PSRAM.
|
|
*/
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#include "esp_err.h"
|
|
#include "esp_lcd_panel_ops.h"
|
|
|
|
#define DISPLAY_H_RES 480
|
|
#define DISPLAY_V_RES 480
|
|
|
|
/*
|
|
* Bring up the panel: expander power/reset sequencing, 3-wire SPI init,
|
|
* RGB bus, backlight.
|
|
*
|
|
* Requires i2c_bus_init() and pcf8574_init() to have run. PRD 8.2 also wants
|
|
* WiFi up before this point.
|
|
*/
|
|
esp_err_t display_init(void);
|
|
|
|
/* The esp_lcd panel handle, for the LVGL port. */
|
|
esp_lcd_panel_handle_t display_panel(void);
|
|
|
|
/*
|
|
* Hand a completed frame (one of the two framebuffers) to the panel and block
|
|
* until the swap has latched at vsync.
|
|
*
|
|
* esp_lcd_panel_draw_bitmap() only *queues* the framebuffer switch — the RGB
|
|
* driver latches it at the next frame boundary. Returning before that point
|
|
* lets the caller start rendering into the other buffer while it is still
|
|
* being scanned out, which is exactly the persistent-corruption race PRD 8.2
|
|
* warns about. All frame presentation goes through here so that cannot happen.
|
|
*/
|
|
esp_err_t display_present_frame(void *fb);
|
|
|
|
/* Both framebuffers, for LVGL to render into directly. */
|
|
esp_err_t display_get_framebuffers(void **fb0, void **fb1);
|
|
|
|
/* Backlight, 0-100. */
|
|
void display_set_backlight(uint8_t percent);
|
|
|
|
/*
|
|
* Fill the screen with vertical colour bars, bypassing LVGL.
|
|
*
|
|
* This is the PRD phase-2 check: it proves the init sequence, the RGB bus and
|
|
* the timings independently of anything LVGL does.
|
|
*/
|
|
void display_test_pattern(void);
|