1280x720 sind 2,4-mal so viele Pixel wie beim 4,3-Zöller, und bis 1.6.3 wurde bei jeder Änderung das komplette Bild in 24 Bit neu gezeichnet. Drei Schalter in pins_config.h, einzeln zurückstellbar: - WS7_COLOR_BITS = 16: RGB565 statt RGB888, halbe Datenmenge je Bild. lv_conf.h liest den Wert aus pins_config.h, damit Sketch und LVGL-Bibliothek dieselbe Farbtiefe benutzen; display_hal.cpp sichert das per static_assert. - WS7_PARTIAL_REFRESH = 1: Avoid-Tear-Mode 3 (Direct-Mode, zwei Puffer) statt Vollbild-Neuzeichnen. - WS7_PARALLEL_RENDER = 1: LV_USE_OS = FREERTOS und zwei Zeichen-Threads. Framebuffer-Bedarf sinkt dadurch von rund 8,3 MB auf 3,7 MB PSRAM. Die JC-Panels sind von allen drei Schaltern nicht betroffen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
94 lines
4.1 KiB
C++
94 lines
4.1 KiB
C++
// =====================================================================================
|
|
// display_hal.cpp - LVGL-Glue fuer JC4880P443C-I-W / JC1060P470C-I-W / Waveshare 7" (H)
|
|
// =====================================================================================
|
|
// Realer Modus: nutzt die Hersteller-Portierung. Der eigentliche esp_lcd-Bringup liegt
|
|
// bewusst in board_bringup.c (C). Hier nur die LVGL-/UI-Verdrahtung.
|
|
// =====================================================================================
|
|
|
|
#include <Arduino.h>
|
|
#include <lvgl.h>
|
|
#include "display_hal.h"
|
|
#include "ui.h"
|
|
#include "config.h"
|
|
#include "pins_config.h"
|
|
|
|
// LVGL muss mit derselben Farbtiefe uebersetzt sein wie das Panel erwartet. Zieht der
|
|
// Build versehentlich eine fremde lv_conf.h (z.B. eine alte Datei neben dem lvgl-Ordner),
|
|
// faellt das hier auf - sonst erst am schwarzen oder farbverfaelschten Bild.
|
|
#if JC_PANEL_TYPE == WS_PANEL_7H
|
|
static_assert(LV_COLOR_DEPTH == WS7_COLOR_BITS,
|
|
"Farbtiefe passt nicht zu WS7_COLOR_BITS - falsche lv_conf.h?");
|
|
#else
|
|
static_assert(LV_COLOR_DEPTH == 16, "JC-Panels brauchen RGB565 - falsche lv_conf.h?");
|
|
#endif
|
|
|
|
static ProtocolClient* g_client = nullptr;
|
|
|
|
// =====================================================================================
|
|
#if JC_USE_REAL_PANEL
|
|
// =====================================================================================
|
|
// ECHTE HARDWARE - Bringup in board_bringup.c, LVGL-Mutex im Hersteller-Port.
|
|
// =====================================================================================
|
|
extern "C" {
|
|
bool jc_board_bringup(void); // board_bringup.c
|
|
void jc_backlight_set(int percent); // board_bringup.c
|
|
bool lvgl_port_lock(int timeout_ms); // lvgl_port_v9.c (Vendor-BSP)
|
|
void lvgl_port_unlock(void); // lvgl_port_v9.c (Vendor-BSP)
|
|
}
|
|
|
|
// Kam das Panel nicht hoch, laeuft die Firmware ohne Anzeige weiter: UART-Client und
|
|
// OTA bleiben erreichbar, damit die S3 neu flashen kann. Jeder LVGL-Zugriff wuerde sonst
|
|
// einen Folgeabsturz ausloesen, der die eigentliche Ursache im Log ueberdeckt.
|
|
static bool s_panel_ready = false;
|
|
|
|
void hal_init(ProtocolClient* client) {
|
|
g_client = client;
|
|
s_panel_ready = jc_board_bringup(); // Panel + Touch + LVGL-Port (eigener Task)
|
|
jc_backlight_set(100);
|
|
if (!s_panel_ready) return;
|
|
if (lvgl_port_lock(-1)) { // UI im LVGL-Kontext aufbauen
|
|
ui_init(g_client);
|
|
lvgl_port_unlock();
|
|
}
|
|
}
|
|
|
|
void hal_loop() { /* LVGL laeuft im Port-Task - hier nichts zu tun. */ }
|
|
void hal_lock() { if (s_panel_ready) lvgl_port_lock(-1); }
|
|
void hal_unlock(){ if (s_panel_ready) lvgl_port_unlock(); }
|
|
void hal_backlight(int percent) { jc_backlight_set(percent); }
|
|
|
|
// =====================================================================================
|
|
#else // JC_USE_REAL_PANEL == 0
|
|
// =====================================================================================
|
|
// STUB-MODUS - minimales LVGL ohne Panel/Touch (zum Testen von Protokoll/Logik).
|
|
// =====================================================================================
|
|
#define HAL_BUF_LINES 40
|
|
#define HAL_BYTES_PER_PX (LV_COLOR_DEPTH / 8)
|
|
static uint8_t s_buf1[DISP_HOR_RES * HAL_BUF_LINES * HAL_BYTES_PER_PX];
|
|
static lv_display_t* s_disp = nullptr;
|
|
|
|
static uint32_t hal_tick_cb(void) { return (uint32_t)millis(); }
|
|
|
|
static void stub_flush_cb(lv_display_t* disp, const lv_area_t* area, uint8_t* px_map) {
|
|
(void)area; (void)px_map;
|
|
lv_display_flush_ready(disp); // Pixel werden verworfen (kein Panel)
|
|
}
|
|
|
|
void hal_init(ProtocolClient* client) {
|
|
g_client = client;
|
|
lv_init();
|
|
lv_tick_set_cb(hal_tick_cb);
|
|
s_disp = lv_display_create(DISP_HOR_RES, DISP_VER_RES);
|
|
lv_display_set_flush_cb(s_disp, stub_flush_cb);
|
|
lv_display_set_buffers(s_disp, s_buf1, nullptr, sizeof(s_buf1),
|
|
LV_DISPLAY_RENDER_MODE_PARTIAL);
|
|
ui_init(g_client);
|
|
}
|
|
|
|
void hal_loop() { lv_timer_handler(); }
|
|
void hal_lock() { /* kein Port-Task -> kein Lock noetig */ }
|
|
void hal_unlock(){ }
|
|
void hal_backlight(int percent) { (void)percent; /* kein Panel im Stub-Modus */ }
|
|
|
|
#endif // JC_USE_REAL_PANEL
|