mirror of
https://github.com/ALLFATHER-BV/wadamesh.git
synced 2026-10-15 01:57:35 +00:00
p4: blank the framebuffer before display-on; widen LVGL bands (#167)
Two changes against the whole-screen colour flash. 1. Real fix for the flash testers see BEFORE the boot splash. The panel was switched on and only then was the framebuffer cleared, so the DSI streamed a freshly-allocated (garbage) PSRAM buffer to the screen until the clear caught up. Blank it with a memset + cache flush while the panel is still dark. That also removes 39 back-to-back draw_bitmap transfers into a buffer the panel is scanning out. 2. Diagnostic, P4 only: LVGL bands 24 -> 64 lines. This panel is DSI video mode with a SINGLE framebuffer, so every band is copied into the buffer being actively scanned. At 24 lines a full-screen repaint is ~26 back-to-back transfers into that live buffer. The reported triggers (message arrives, opening a chat with unread, adding/deleting a contact) all rebuild the whole screen; panning the map repaints only its own region and never flashes, which is the shape this predicts. Wider bands cut the same repaint to ~10 transfers. Sized so the 2x upscale scratch still fits internal SRAM, so burst count is the only variable that moves. Supersedes the write-path theory: the flash still occurs with contacts, history and prefs all on SD, and the pre-splash case involves no write at all. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1bc0c7ab39
commit
1e6e121c85
@@ -1950,7 +1950,19 @@ static bool g_cap_touch_hw_started = false;
|
||||
// build). 24 × 240 × 2 B = 11.5 KB. Flush time is bound by SPI clock
|
||||
// (80 MHz), not memcpy speed, so the throughput delta is small —
|
||||
// LVGL just calls flush_cb more often.
|
||||
#if defined(HAS_TDISPLAY_P4)
|
||||
// DIAGNOSTIC (#167): the T-Display P4 is a DSI video-mode panel with a SINGLE framebuffer, so every
|
||||
// LVGL band is copied into the buffer the panel is actively scanning out. At 24 lines a full-screen
|
||||
// repaint is ~26 back-to-back DMA transfers into that live buffer -- and the events testers report
|
||||
// (a message arriving, opening a chat with unread, adding/deleting a contact) are exactly the ones
|
||||
// that rebuild the whole screen, while panning the map only repaints its own region and never
|
||||
// flashes. Wider bands make the same repaint ~10 transfers instead of ~26. Kept just small enough
|
||||
// that the 2x upscale scratch still fits internal SRAM (568*128*2 = ~145 KB), so this changes ONLY
|
||||
// the burst count and not where the scratch lives.
|
||||
static constexpr int LV_DRAW_BUF_LINES = 64;
|
||||
#else
|
||||
static constexpr int LV_DRAW_BUF_LINES = 24;
|
||||
#endif
|
||||
static lv_color_t* g_draw_buffer = nullptr;
|
||||
static uint32_t g_draw_buf_px = 240 * LV_DRAW_BUF_LINES; // actual buffer size in px; shrinks if the full alloc fails at boot
|
||||
#if CAP_LARGE_SCREEN
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "RM69A10Display.h"
|
||||
#include <Arduino.h>
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_cache.h" // esp_cache_msync — flush the memset framebuffer out to the DSI DMA
|
||||
#include "esp_ldo_regulator.h"
|
||||
#include "Xl9535.h" // SCREEN_RST lives on the expander (reset_gpio_num = -1)
|
||||
#include "esp_lcd_mipi_dsi.h"
|
||||
@@ -109,6 +110,19 @@ bool RM69A10Display::begin() {
|
||||
|
||||
esp_lcd_panel_reset(_panel);
|
||||
if (esp_lcd_panel_init(_panel) != ESP_OK) { Serial.println("[RM69A10] panel_init fail"); return false; }
|
||||
|
||||
// Blank the framebuffer BEFORE switching the panel on. It is freshly allocated PSRAM, so it holds
|
||||
// garbage; turning the panel on first meant the DSI streamed that garbage to the screen until the
|
||||
// clear below finished -- the colour flash testers see before the boot splash (#167). Write the
|
||||
// buffer directly (memset + a cache flush to make it visible to the DSI's DMA) instead of pushing
|
||||
// strips through draw_bitmap: it is one pass with the panel still dark, and it avoids a burst of
|
||||
// 39 back-to-back DMA transfers into a buffer the panel is scanning out.
|
||||
void* fb = nullptr;
|
||||
if (esp_lcd_dpi_panel_get_frame_buffer(_panel, 1, &fb) == ESP_OK && fb) {
|
||||
const size_t fb_bytes = (size_t)RM_W * RM_H * 2;
|
||||
memset(fb, 0, fb_bytes);
|
||||
esp_cache_msync(fb, fb_bytes, ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||
}
|
||||
esp_lcd_panel_disp_on_off(_panel, true);
|
||||
|
||||
// Brightness: the init array ships 0x51=0 (placeholder), and RM69A10 brightness is driven at
|
||||
@@ -125,20 +139,6 @@ bool RM69A10Display::begin() {
|
||||
cbs.on_color_trans_done = rm69a10TransDone;
|
||||
esp_lcd_dpi_panel_register_event_callbacks(_panel, &cbs, nullptr);
|
||||
|
||||
// Clear the panel framebuffer to black once, so nothing stale shows before LVGL's first flush.
|
||||
{
|
||||
const int SH = 32;
|
||||
uint16_t* strip = (uint16_t*)heap_caps_calloc((size_t)RM_W * SH, 2, MALLOC_CAP_SPIRAM);
|
||||
if (strip) {
|
||||
for (int y0 = 0; y0 < RM_H; y0 += SH) {
|
||||
int hh = (y0 + SH <= RM_H) ? SH : (RM_H - y0);
|
||||
esp_lcd_panel_draw_bitmap(_panel, 0, y0, RM_W, y0 + hh, strip);
|
||||
if (s_flush_sem) xSemaphoreTake(s_flush_sem, pdMS_TO_TICKS(100)); // let the copy finish before reusing/freeing strip
|
||||
}
|
||||
free(strip);
|
||||
}
|
||||
}
|
||||
|
||||
Serial.printf("[RM69A10] up %dx%d\n", RM_W, RM_H);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user