Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5988668026 | ||
|
|
4f2700d59a | ||
|
|
0ec3d89973 | ||
|
|
06d9710b16 |
@@ -1,3 +1,28 @@
|
||||
Version 1.9.8:
|
||||
- Der Stillstand beim Wechsel in den Standby ist gefunden und behoben. LVGL legt für JEDE
|
||||
Textglyphe einen eigenen Zwischenpuffer an - bei der großen Uhr rund 48 KB pro Ziffer, mit
|
||||
zwei parallel arbeitenden Zeicheneinheiten fast 100 KB gleichzeitig. Der interne
|
||||
LVGL-Speicher hatte nur rund 98 KB am Stück frei; es reichte knapp nicht. Schlägt die
|
||||
Anforderung fehl, hält LVGL per Zusicherung in einer Endlosschleife an - kein Absturz,
|
||||
keine Meldung, das Display steht einfach. Deshalb brach der Mitschnitt ohne Fehler ab.
|
||||
- Große Glyphenpuffer liegen jetzt im externen Speicher (PSRAM, 32 MB frei). Kleine bleiben
|
||||
im internen, der ist schneller - sonst würde jeder Text langsamer.
|
||||
- Hält LVGL künftig wegen einer verletzten Zusicherung an, sagt es das jetzt, statt stumm
|
||||
stehen zu bleiben.
|
||||
|
||||
Version 1.9.7:
|
||||
- Messpunkte für den Stillstand beim Wechsel in den Standby: Beide Abläufe - der Haupt- und
|
||||
der Zeichenablauf - melden jetzt alle zwei Sekunden einen Herzschlag mit Speicherstand.
|
||||
Bleibt nur einer von beiden aus, ist klar, welcher stehen bleibt.
|
||||
- Das Einblenden der Standby-Uhr meldet Anfang und Ende mit Dauer. Bleibt die zweite Meldung
|
||||
aus, hängt es genau dort.
|
||||
- Jeder Helligkeitswechsel, der länger als 50 ms braucht, wird mit seiner Dauer gemeldet. Der
|
||||
Schreibzugriff geht über denselben Bus wie der Touch - ein Verdacht für die bekannte
|
||||
Verzögerung von ein bis zwei Sekunden.
|
||||
- Die Rückmeldung aus 1.9.5, die einen komplett ungültigen Inhaltsbereich melden sollte, ist
|
||||
wieder entfernt. Sie konnte nie auslösen: LVGL schickt diese Meldung an das Display, nicht
|
||||
an einzelne Elemente. Ihr Ausbleiben war also kein Beweis.
|
||||
|
||||
Version 1.9.6:
|
||||
- Die Darstellungseinstellungen haben einen eigenen Menüpunkt „Darstellung" bekommen. Sie
|
||||
standen bisher oben auf der Info-Seite, zwischen Sachen, mit denen sie nichts zu tun
|
||||
|
||||
@@ -67,11 +67,25 @@ static void onState(const MachineState& st) {
|
||||
}
|
||||
if (bl < 0) bl = 0; if (bl > 100) bl = 100;
|
||||
if (bl != s_lastBacklight) {
|
||||
// Vermessen: Rund um jeden Helligkeitswechsel hing die Bedienung bisher ein bis
|
||||
// zwei Sekunden. Der Schreibzugriff geht ueber denselben I2C-Bus wie der Touch.
|
||||
uint32_t t0 = millis();
|
||||
hal_backlight(bl);
|
||||
uint32_t dt = millis() - t0;
|
||||
if (dt > 50) Serial.printf("[HAL] Helligkeit %d %% gesetzt, %u ms\n", bl, (unsigned)dt);
|
||||
s_lastBacklight = bl;
|
||||
}
|
||||
}
|
||||
|
||||
// Herzschlag aus dem Haupt-Ablauf. Zusammen mit dem Herzschlag aus dem Zeichen-Ablauf
|
||||
// laesst sich unterscheiden, welcher der beiden stehen bleibt, wenn nichts mehr geht.
|
||||
static void main_heartbeat() {
|
||||
static uint32_t s_last = 0;
|
||||
if (millis() - s_last < 2000) return;
|
||||
s_last = millis();
|
||||
Serial.printf("[Haupt] Herzschlag, freier Speicher %u Byte\n", (unsigned)ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
static void onAck(uint32_t id, bool ok, const String& message) {
|
||||
// Automatische/Heartbeat-Acks nicht als Toast zeigen (pong, Handshake, Listen-Refresh).
|
||||
bool routine = ok && (message == "pong" || message == "hello" ||
|
||||
@@ -332,6 +346,7 @@ static unsigned long s_lastDbgMs = 0;
|
||||
#endif
|
||||
|
||||
void loop() {
|
||||
main_heartbeat();
|
||||
g_client.loop(); // UART lesen, hello/heartbeat, state -> UI
|
||||
hal_loop(); // realer Modus: leer; Stub-Modus: lv_timer_handler()
|
||||
|
||||
|
||||
@@ -374,8 +374,10 @@
|
||||
#define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/
|
||||
|
||||
/*Add a custom handler when assert happens e.g. to restart the MCU*/
|
||||
#define LV_ASSERT_HANDLER_INCLUDE <stdint.h>
|
||||
#define LV_ASSERT_HANDLER while(1); /*Halt by default*/
|
||||
#define LV_ASSERT_HANDLER_INCLUDE <esp_rom_sys.h>
|
||||
// Frueher hielt LVGL hier stumm in einer Endlosschleife an - das Display stand, ohne dass
|
||||
// irgendwo etwas davon zu sehen war. Jetzt sagt es wenigstens, dass es angehalten hat.
|
||||
#define LV_ASSERT_HANDLER esp_rom_printf("[LVGL] Zusicherung verletzt - Zeichenablauf haelt an\n"); while(1);
|
||||
|
||||
/*-------------
|
||||
* Debug
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <Preferences.h> // Dashboard-Design P4-lokal merken (NVS)
|
||||
#include <esp_memory_utils.h> // esp_ptr_external_ram(): welcher Speicher einen Puffer traegt
|
||||
#include <esp_heap_caps.h> // Verlaufs-Historie im PSRAM allozieren (interner RAM ist knapp)
|
||||
#include "ui.h"
|
||||
#include <Preferences.h>
|
||||
@@ -3565,12 +3566,40 @@ static void refr_ready_cb(lv_event_t*) {
|
||||
(int)g_refrArea[i].y1, (int)g_refrArea[i].y2);
|
||||
}
|
||||
|
||||
// Meldet, wenn ein ganzer Container ungueltig gemacht wird. Damit laesst sich unterscheiden,
|
||||
// ob eine einzelne Beschriftung den Bildaufbau ausloest oder ob gleich der komplette
|
||||
// Inhaltsbereich neu gezeichnet werden soll - zwei verschiedene Ursachen.
|
||||
static void inval_watch_cb(lv_event_t* e) {
|
||||
const char* name = (const char*)lv_event_get_user_data(e);
|
||||
esp_rom_printf("[UI] %s wird komplett ungueltig\n", name);
|
||||
static void ui_heartbeat_cb(lv_timer_t*) {
|
||||
lv_mem_monitor_t m; lv_mem_monitor(&m);
|
||||
esp_rom_printf("[UI] Herzschlag, LVGL-Speicher frei %u von %u Byte, groesster Block %u\n",
|
||||
(unsigned)m.free_size, (unsigned)m.total_size, (unsigned)m.free_biggest_size);
|
||||
}
|
||||
|
||||
// LVGL legt fuer JEDE Textglyphe einen eigenen Zwischenpuffer an - Breite mal Hoehe, ein
|
||||
// Byte je Bildpunkt. Bei der grossen Standby-Uhr sind das 190 x 256 = rund 48 KB pro Ziffer,
|
||||
// und mit zwei parallel arbeitenden Zeicheneinheiten fast 100 KB gleichzeitig. Der interne
|
||||
// LVGL-Speicher fasst nur 245 KB, wovon rund 98 KB am Stueck frei sind - es reichte knapp
|
||||
// nicht. Schlaegt die Anforderung fehl, haelt LVGL per Zusicherung in einer Endlosschleife
|
||||
// an: kein Absturz, keine Meldung, das Display steht einfach. Genau das war der Stillstand
|
||||
// beim Wechsel in den Standby.
|
||||
//
|
||||
// Diese Puffer wandern daher in den externen Speicher (PSRAM, 32 MB frei). Kleine Glyphen
|
||||
// bleiben im internen Speicher, weil der schneller ist und Text sonst ueberall langsamer
|
||||
// wuerde; nur die grossen gehen nach aussen.
|
||||
#define FONT_BUF_EXTERN_AB 16384 // ab dieser Groesse in den externen Speicher
|
||||
|
||||
static void* font_buf_malloc(size_t size, lv_color_format_t cf) {
|
||||
LV_UNUSED(cf);
|
||||
size += LV_DRAW_BUF_ALIGN - 1;
|
||||
if (size >= FONT_BUF_EXTERN_AB) {
|
||||
void* p = heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if (p) return p;
|
||||
}
|
||||
return lv_malloc(size);
|
||||
}
|
||||
|
||||
static void font_buf_free(void* buf) {
|
||||
// Der externe Speicher liegt ausserhalb des LVGL-Bereichs; daran ist zu erkennen,
|
||||
// welcher der beiden Wege den Puffer vergeben hat.
|
||||
if (esp_ptr_external_ram(buf)) heap_caps_free(buf);
|
||||
else lv_free(buf);
|
||||
}
|
||||
|
||||
static void refr_monitor_install() {
|
||||
@@ -3983,9 +4012,12 @@ void ui_init(ProtocolClient* client) {
|
||||
show_page(PG_DASH);
|
||||
if (g_client) g_client->sendListProfiles();
|
||||
|
||||
// Glyphenpuffer umlenken, bevor der erste Text gezeichnet wird.
|
||||
lv_draw_buf_handlers_t* fh = lv_draw_buf_get_font_handlers();
|
||||
fh->buf_malloc_cb = font_buf_malloc;
|
||||
fh->buf_free_cb = font_buf_free;
|
||||
refr_monitor_install();
|
||||
if (g_content) lv_obj_add_event_cb(g_content, inval_watch_cb, LV_EVENT_INVALIDATE_AREA, (void*)"Inhaltsbereich");
|
||||
if (g_pages[PG_DASH]) lv_obj_add_event_cb(g_pages[PG_DASH], inval_watch_cb, LV_EVENT_INVALIDATE_AREA, (void*)"Dashboard-Seite");
|
||||
lv_timer_create(ui_heartbeat_cb, 2000, nullptr);
|
||||
g_uiReady = true;
|
||||
}
|
||||
|
||||
@@ -4175,8 +4207,14 @@ void ui_update(const MachineState& st) {
|
||||
if (shouldShow) {
|
||||
label_set_if_changed(g_standbyClock, zeit.length() ? zeit.c_str() : "--:--");
|
||||
if (!g_standbyShown) {
|
||||
// Vermessen: Das Einblenden der Uhr ist der Moment, in dem das Display
|
||||
// zuletzt stehen geblieben ist. Bleibt die zweite Zeile aus, haengt es hier.
|
||||
esp_rom_printf("[UI] Standby-Uhr wird eingeblendet\n");
|
||||
uint32_t t0 = lv_tick_get();
|
||||
ui_fade_in(g_standbyScreen, UI_FADE_MS); // Einschlaf-Animation
|
||||
g_standbyShown = true;
|
||||
esp_rom_printf("[UI] Standby-Uhr eingeblendet, %u ms\n",
|
||||
(unsigned)(lv_tick_get() - t0));
|
||||
}
|
||||
// Frueher wurde die Uhr hier bei JEDER Zustandsmeldung nach vorn geholt. Das
|
||||
// ordnet die Ebenen neu und laesst LVGL den gesamten Bildschirm neu zeichnen -
|
||||
|
||||
Reference in New Issue
Block a user