Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
288f61447d | ||
|
|
a91c792491 | ||
|
|
e32c654b8d | ||
|
|
484812cb4c |
@@ -1,3 +1,31 @@
|
||||
Version 1.9.3:
|
||||
- Fehlerbehebung: Bei geöffnetem Menü war der Seiteninhalt dahinter verschwunden. Der
|
||||
Vorhang des Menüs war in 1.8.7 deckend gemacht worden, um Zeichenlast zu sparen - dabei
|
||||
verdeckt er aber genau das, was sichtbar bleiben soll. Er ist wieder durchscheinend.
|
||||
- Weitere Stellen umgestellt, die bei jeder Zustandsmeldung neu zeichnen ließen, obwohl sich
|
||||
nichts geändert hatte: das Zustandsband der Darstellung „Band" (es spannt sich über die
|
||||
volle Breite und machte damit allein schon einen Streifen über den ganzen Bildschirm
|
||||
ungültig), die Heizleistungsbalken und das WLAN-Symbol.
|
||||
- Die Messung nennt jetzt zusätzlich die Lage der neu gezeichneten Bereiche. Die Größe
|
||||
allein sagt nicht, welcher Teil der Oberfläche das Neuzeichnen auslöst - die Koordinaten
|
||||
schon.
|
||||
|
||||
Version 1.9.2:
|
||||
- Ursache der Trägheit endlich gefunden. Die erweiterte Messung zeigte: „1 Bereich, 100 %
|
||||
der Fläche" - LVGL zeichnete bei jeder Zustandsmeldung den kompletten Bildschirm neu, also
|
||||
einmal pro Sekunde 240 bis 300 Millisekunden lang. Es war also kein Tempoproblem beim
|
||||
Zeichnen, sondern es wurde viel zu viel als „muss neu gezeichnet werden" gemeldet.
|
||||
- Grund: LVGL macht den Bereich einer Beschriftung ungültig, sobald ihr Text gesetzt wird -
|
||||
auch dann, wenn er sich gar nicht geändert hat. Dasselbe gilt für Farbwechsel. Auf dem
|
||||
Dashboard wurden im Sekundentakt Werte quer über den ganzen Bildschirm gesetzt: Uhrzeit
|
||||
oben, Temperaturen in der Mitte, Bezugswerte unten. LVGL fasst benachbarte ungültige
|
||||
Bereiche zu einem zusammen - und der umfasste dann die gesamte Fläche.
|
||||
- Alle regelmäßig gesetzten Werte werden jetzt vorher verglichen und nur bei echter Änderung
|
||||
neu geschrieben; für Farben gilt dasselbe. Da sich Temperaturen selten um ein Zehntelgrad
|
||||
ändern und der Sollwert praktisch nie, entfallen die meisten dieser Neuzeichnungen.
|
||||
- Das betrifft alle Bildschirmgrößen; auf den JC-Panels war es nur nie störend, weil dort ein
|
||||
Bildaufbau ein Bruchteil davon kostet.
|
||||
|
||||
Version 1.9.1:
|
||||
- Das direkte Zeichnen in den Bildspeicher aus 1.9.0 ist zurückgenommen: Es hat die
|
||||
Bildaufbauzeit nicht verkürzt (weiterhin 240 bis 300 ms) und stattdessen Bildfehler
|
||||
|
||||
+76
-38
@@ -25,6 +25,7 @@
|
||||
#include "display_hal.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "lvgl_private.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Schriftgroesse
|
||||
@@ -985,8 +986,11 @@ static lv_color_t temp_state_color(float temp, float set) {
|
||||
static void temp_progress_set(lv_obj_t* bar, lv_obj_t* arc, lv_obj_t* bulb, int pct, lv_color_t col) {
|
||||
if (pct > 100) pct = 100; else if (pct < 0) pct = 0;
|
||||
if (bar) {
|
||||
lv_bar_set_value(bar, pct, LV_ANIM_OFF);
|
||||
lv_obj_set_style_bg_color(bar, col, LV_PART_INDICATOR);
|
||||
// Wert und Farbe nur bei echter Aenderung setzen - beides macht den Balken sonst
|
||||
// bei jeder Zustandsmeldung ungueltig, obwohl sich meist nichts bewegt hat.
|
||||
if (lv_bar_get_value(bar) != pct) lv_bar_set_value(bar, pct, LV_ANIM_OFF);
|
||||
if (lv_color_to_u32(lv_obj_get_style_bg_color(bar, LV_PART_INDICATOR)) != lv_color_to_u32(col))
|
||||
lv_obj_set_style_bg_color(bar, col, LV_PART_INDICATOR);
|
||||
}
|
||||
if (arc) {
|
||||
lv_arc_set_value(arc, pct);
|
||||
@@ -1377,7 +1381,7 @@ static void flush_targ() {
|
||||
static void targ_w_set(float v) {
|
||||
if (v < 0) v = 0; if (v > 135) v = 135;
|
||||
g_targW = v;
|
||||
if (lblTargW) lv_label_set_text(lblTargW, tempStr(g_targW, 0).c_str());
|
||||
if (lblTargW) label_set_if_changed(lblTargW, tempStr(g_targW, 0).c_str());
|
||||
if (g_arcW) lv_arc_set_value(g_arcW, (int32_t)(g_targW + 0.5f));
|
||||
g_targWDirty = true;
|
||||
schedule_targ_send();
|
||||
@@ -1385,7 +1389,7 @@ static void targ_w_set(float v) {
|
||||
static void targ_d_set(float v) {
|
||||
if (v < 0) v = 0; if (v > 200) v = 200;
|
||||
g_targD = v;
|
||||
if (lblTargD) lv_label_set_text(lblTargD, tempStr(g_targD, 0).c_str());
|
||||
if (lblTargD) label_set_if_changed(lblTargD, tempStr(g_targD, 0).c_str());
|
||||
if (g_arcD) lv_arc_set_value(g_arcD, (int32_t)(g_targD + 0.5f));
|
||||
g_targDDirty = true;
|
||||
schedule_targ_send();
|
||||
@@ -3240,10 +3244,35 @@ static void eco_case_timer_cb(lv_timer_t*) {
|
||||
// =====================================================================================
|
||||
// Setzt den Labeltext nur, wenn er sich aendert -> verhindert unnoetige Invalidierung
|
||||
// (im Full-Refresh-Modus loest jede Aenderung ein komplettes Neuzeichnen aus).
|
||||
// LVGL macht bei jedem Setzen den Bereich der Beschriftung ungueltig - auch dann, wenn sich
|
||||
// der Text gar nicht geaendert hat. Auf dem Dashboard werden im Sekundentakt Werte quer ueber
|
||||
// den ganzen Bildschirm gesetzt; LVGL fasst die ungueltigen Bereiche zu einem zusammen, und
|
||||
// das ist dann die gesamte Flaeche. Gemessen waren das 240 bis 300 ms pro Sekunde, in denen
|
||||
// die Oberflaeche mit nichts anderem beschaeftigt war. Deshalb wird ueberall dort, wo sich
|
||||
// Werte nur selten aendern, vorher verglichen.
|
||||
static void label_set_if_changed(lv_obj_t* lbl, const char* txt) {
|
||||
if (!lbl || !txt) return;
|
||||
const char* cur = lv_label_get_text(lbl);
|
||||
if (!cur || strcmp(cur, txt) != 0) lv_label_set_text(lbl, txt);
|
||||
}
|
||||
|
||||
// Wie oben, aber mit Formatangabe.
|
||||
static void label_fmt_if_changed(lv_obj_t* lbl, const char* fmt, ...) {
|
||||
if (!lbl) return;
|
||||
char buf[96];
|
||||
va_list ap; va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
label_set_if_changed(lbl, buf);
|
||||
}
|
||||
|
||||
// Auch ein Farbwechsel macht den Bereich ungueltig. Gleiche Farbe -> nichts tun.
|
||||
static void label_color_if_changed(lv_obj_t* lbl, lv_color_t col) {
|
||||
if (!lbl) return;
|
||||
lv_color_t cur = lv_obj_get_style_text_color(lbl, LV_PART_MAIN);
|
||||
if (lv_color_to_u32(cur) != lv_color_to_u32(col))
|
||||
lv_obj_set_style_text_color(lbl, col, 0);
|
||||
}
|
||||
// Pre-Infusion-Phasenleiste aktualisieren (100-ms-Takt aus dash_timers_cb).
|
||||
// Die aktive Phase kommt bevorzugt von der S3 (piState = echte Statemachine, Quelle der
|
||||
// Wahrheit; Push-Latenz max. 250 ms). Sendet eine aeltere S3-Firmware das Feld noch nicht
|
||||
@@ -3467,6 +3496,8 @@ static uint32_t g_refrStart = 0;
|
||||
|
||||
static uint32_t g_refrPixels = 0;
|
||||
static uint32_t g_refrAreas = 0;
|
||||
static lv_area_t g_refrArea[6];
|
||||
static uint8_t g_refrAreaCnt = 0;
|
||||
|
||||
// Beim Start eines Zeichenzyklus festhalten, WIE VIEL neu gezeichnet wird. Erst damit laesst
|
||||
// sich unterscheiden, ob LVGL nur kleine Bereiche anfasst - dann ist das Zeichnen an sich zu
|
||||
@@ -3476,12 +3507,14 @@ static void refr_start_cb(lv_event_t*) {
|
||||
g_refrStart = lv_tick_get();
|
||||
g_refrPixels = 0;
|
||||
g_refrAreas = 0;
|
||||
g_refrAreaCnt = 0;
|
||||
lv_display_t* d = lv_display_get_default();
|
||||
if (!d) return;
|
||||
for (uint16_t i = 0; i < d->inv_p; i++) {
|
||||
if (d->inv_area_joined[i]) continue;
|
||||
const lv_area_t* a = &d->inv_areas[i];
|
||||
g_refrPixels += (uint32_t)(a->x2 - a->x1 + 1) * (uint32_t)(a->y2 - a->y1 + 1);
|
||||
if (g_refrAreaCnt < 6) g_refrArea[g_refrAreaCnt++] = *a;
|
||||
g_refrAreas++;
|
||||
}
|
||||
}
|
||||
@@ -3492,6 +3525,12 @@ static void refr_ready_cb(lv_event_t*) {
|
||||
unsigned pct = (unsigned)((uint64_t)g_refrPixels * 100ULL / ((uint64_t)LCD_H_RES * LCD_V_RES));
|
||||
esp_rom_printf("[UI] Bildaufbau %u ms, %u Bereiche, %u %% der Flaeche\n",
|
||||
(unsigned)d, (unsigned)g_refrAreas, pct);
|
||||
// Lage der Bereiche mit ausgeben. Erst daran ist zu erkennen, WELCHER Teil der
|
||||
// Oberflaeche das Neuzeichnen ausloest - die Groesse allein sagt das nicht.
|
||||
for (uint8_t i = 0; i < g_refrAreaCnt; i++)
|
||||
esp_rom_printf(" Bereich %u: x %d..%d, y %d..%d\n", (unsigned)i,
|
||||
(int)g_refrArea[i].x1, (int)g_refrArea[i].x2,
|
||||
(int)g_refrArea[i].y1, (int)g_refrArea[i].y2);
|
||||
}
|
||||
|
||||
static void refr_monitor_install() {
|
||||
@@ -3644,16 +3683,11 @@ void ui_init(ProtocolClient* client) {
|
||||
g_drawer = lv_obj_create(scr);
|
||||
lv_obj_set_size(g_drawer, LV_PCT(100), DISP_VER_RES - 44);
|
||||
lv_obj_set_pos(g_drawer, 0, 44);
|
||||
#if JC_PANEL_TYPE == WS_PANEL_7H
|
||||
// Deckend statt halbdurchsichtig - aus demselben Grund wie beim Aufweckdialog: Ein
|
||||
// durchscheinender Vorhang laesst LVGL die ganze Flaeche darunter mitzeichnen und
|
||||
// mischen. Auf dunklem Grund sieht ein dunkles Deckend praktisch genauso aus.
|
||||
lv_obj_set_style_bg_color(g_drawer, lv_color_hex(0x0d0d0d), 0);
|
||||
lv_obj_set_style_bg_opa(g_drawer, LV_OPA_COVER, 0);
|
||||
#else
|
||||
// Bewusst durchscheinend: Der Vorhang legt sich ueber die ganze Seite, und der Inhalt
|
||||
// dahinter soll sichtbar bleiben. Ein Versuch mit deckendem Vorhang (gegen die
|
||||
// Zeichenlast) hat den Seiteninhalt verschwinden lassen und ist zurueckgenommen.
|
||||
lv_obj_set_style_bg_color(g_drawer, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_bg_opa(g_drawer, LV_OPA_50, 0);
|
||||
#endif
|
||||
lv_obj_set_style_border_width(g_drawer, 0, 0);
|
||||
lv_obj_set_style_pad_all(g_drawer, 0, 0);
|
||||
lv_obj_set_style_radius(g_drawer, 0, 0);
|
||||
@@ -3970,10 +4004,14 @@ static void ready_band_update(const MachineState& st) {
|
||||
else if (wOk) { txt = "Wasser bereit — Dampf heizt"; bg = 0x3a2a05; fg = COL_ACCENT; }
|
||||
else { txt = "Heizt auf"; bg = 0x3a2a05; fg = COL_ACCENT; }
|
||||
}
|
||||
lv_label_set_text(g_readyBandLbl, txt);
|
||||
lv_obj_set_style_text_color(g_readyBandLbl, fg, 0);
|
||||
lv_obj_set_style_bg_color(g_readyBand, lv_color_hex(bg), 0);
|
||||
lv_obj_set_style_bg_opa(g_readyBand, LV_OPA_COVER, 0);
|
||||
// Das Band spannt sich ueber die volle Breite. Wuerde es bei jeder Zustandsmeldung neu
|
||||
// gesetzt, machte es allein schon einen Streifen ueber den ganzen Bildschirm ungueltig.
|
||||
label_set_if_changed(g_readyBandLbl, txt);
|
||||
label_color_if_changed(g_readyBandLbl, fg);
|
||||
if (lv_color_to_u32(lv_obj_get_style_bg_color(g_readyBand, LV_PART_MAIN)) != bg) {
|
||||
lv_obj_set_style_bg_color(g_readyBand, lv_color_hex(bg), 0);
|
||||
lv_obj_set_style_bg_opa(g_readyBand, LV_OPA_COVER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4066,7 +4104,7 @@ void ui_update(const MachineState& st) {
|
||||
|
||||
// WLAN-Symbol
|
||||
bool wifiOk = st.wifiConnected && !st.apMode;
|
||||
if (g_wifiIcon) lv_obj_set_style_text_color(g_wifiIcon, wifiOk ? COL_OK : (st.apMode ? COL_WARN : COL_TEXT_MUT), 0);
|
||||
label_color_if_changed(g_wifiIcon, wifiOk ? COL_OK : (st.apMode ? COL_WARN : COL_TEXT_MUT));
|
||||
|
||||
// Uhrzeit. Angezeigt wird die der Hauptplatine; faellt sie voruebergehend aus, zaehlt
|
||||
// der P4 die zuletzt bekannte Zeit selbst weiter (siehe clock_text).
|
||||
@@ -4357,43 +4395,43 @@ void ui_update(const MachineState& st) {
|
||||
// Dashboard - Temperaturkarten (im Fehlerfall Warnsymbol + Klartext statt Zahl, wie OLED)
|
||||
if (lblTempW) {
|
||||
if (st.wasserSafetyShutdown || st.wasserSensorError) {
|
||||
lv_label_set_text(lblTempW, LV_SYMBOL_WARNING);
|
||||
lv_obj_set_style_text_color(lblTempW, COL_DANGER, 0);
|
||||
lv_label_set_text(lblSetW, st.wasserSafetyShutdown ? "Sicherheitsabsch." : "Sensorfehler!");
|
||||
lv_obj_set_style_text_color(lblSetW, COL_DANGER, 0);
|
||||
label_set_if_changed(lblTempW, LV_SYMBOL_WARNING);
|
||||
label_color_if_changed(lblTempW, COL_DANGER);
|
||||
label_set_if_changed(lblSetW, st.wasserSafetyShutdown ? "Sicherheitsabsch." : "Sensorfehler!");
|
||||
label_color_if_changed(lblSetW, COL_DANGER);
|
||||
temp_progress_set(barDutyW, arcTempW, bulbTempW, 0, COL_DANGER);
|
||||
} else {
|
||||
lv_label_set_text(lblTempW, tempStr(st.tempW, 1).c_str());
|
||||
label_set_if_changed(lblTempW, tempStr(st.tempW, 1).c_str());
|
||||
if (st.cxActive) {
|
||||
// Cold Extraction: der Sollwert ist bedeutungslos, es wird nicht geheizt.
|
||||
// Statt eines Zielbands, das nie erreicht wird, den Grund anzeigen.
|
||||
lv_obj_set_style_text_color(lblTempW, temp_value_color(lv_color_hex(0x1976d2)), 0);
|
||||
label_color_if_changed(lblTempW, temp_value_color(lv_color_hex(0x1976d2)));
|
||||
label_set_if_changed(lblSetW, "Cold Extraction - Heizen aus");
|
||||
lv_obj_set_style_text_color(lblSetW, lv_color_hex(0x1976d2), 0);
|
||||
label_color_if_changed(lblSetW, lv_color_hex(0x1976d2));
|
||||
temp_progress_set(barDutyW, arcTempW, bulbTempW, 0, lv_color_hex(0x1976d2));
|
||||
} else {
|
||||
// Ist-Wert faerbt sich weich Richtung Soll (Blau -> Gold -> Gruen im Zielband)
|
||||
lv_color_t colW = temp_state_color(st.tempW, st.setW);
|
||||
lv_obj_set_style_text_color(lblTempW, temp_value_color(colW), 0);
|
||||
lv_label_set_text(lblSetW, ("Soll " + tempStr(st.setW, 1)).c_str());
|
||||
lv_obj_set_style_text_color(lblSetW, COL_TEXT_DIM, 0);
|
||||
label_color_if_changed(lblTempW, temp_value_color(colW));
|
||||
label_set_if_changed(lblSetW, ("Soll " + tempStr(st.setW, 1)).c_str());
|
||||
label_color_if_changed(lblSetW, COL_TEXT_DIM);
|
||||
// Fortschritt = Ist/Soll in %, gedeckelt auf 100 (Ist >= Soll -> voll)
|
||||
int pctW = (st.setW > 0.0f) ? (int)(st.tempW / st.setW * 100.0f + 0.5f) : 0;
|
||||
temp_progress_set(barDutyW, arcTempW, bulbTempW, pctW, colW);
|
||||
}
|
||||
}
|
||||
if (st.dampfSafetyShutdown || st.dampfSensorError) {
|
||||
lv_label_set_text(lblTempD, LV_SYMBOL_WARNING);
|
||||
lv_obj_set_style_text_color(lblTempD, COL_DANGER, 0);
|
||||
lv_label_set_text(lblSetD, st.dampfSafetyShutdown ? "Sicherheitsabsch." : "Sensorfehler!");
|
||||
lv_obj_set_style_text_color(lblSetD, COL_DANGER, 0);
|
||||
label_set_if_changed(lblTempD, LV_SYMBOL_WARNING);
|
||||
label_color_if_changed(lblTempD, COL_DANGER);
|
||||
label_set_if_changed(lblSetD, st.dampfSafetyShutdown ? "Sicherheitsabsch." : "Sensorfehler!");
|
||||
label_color_if_changed(lblSetD, COL_DANGER);
|
||||
temp_progress_set(barDutyD, arcTempD, bulbTempD, 0, COL_DANGER);
|
||||
} else {
|
||||
lv_label_set_text(lblTempD, tempStr(st.tempD, 0).c_str());
|
||||
label_set_if_changed(lblTempD, tempStr(st.tempD, 0).c_str());
|
||||
lv_color_t colD = temp_state_color(st.tempD, st.setD);
|
||||
lv_obj_set_style_text_color(lblTempD, temp_value_color(colD), 0);
|
||||
lv_label_set_text(lblSetD, ("Soll " + tempStr(st.setD, 0)).c_str());
|
||||
lv_obj_set_style_text_color(lblSetD, COL_TEXT_DIM, 0);
|
||||
label_color_if_changed(lblTempD, temp_value_color(colD));
|
||||
label_set_if_changed(lblSetD, ("Soll " + tempStr(st.setD, 0)).c_str());
|
||||
label_color_if_changed(lblSetD, COL_TEXT_DIM);
|
||||
int pctD = (st.setD > 0.0f) ? (int)(st.tempD / st.setD * 100.0f + 0.5f) : 0;
|
||||
temp_progress_set(barDutyD, arcTempD, bulbTempD, pctD, colD);
|
||||
}
|
||||
@@ -4542,12 +4580,12 @@ void ui_update(const MachineState& st) {
|
||||
float wDisp = st.weight;
|
||||
if (wDisp > -0.05f && wDisp <= 0.0f) wDisp = 0.0f;
|
||||
if (!st.scaleEnabled) {
|
||||
lv_label_set_text(lblBezug, "--");
|
||||
label_set_if_changed(lblBezug, "--");
|
||||
} else if (bbwShot) {
|
||||
// Waehrend des Bezugs mit Brew-by-Weight: Ist oben, Ziel darunter (zweizeilig)
|
||||
lv_label_set_text_fmt(lblBezug, "%.1f g\n/ %.1f g", wDisp, shotTarget);
|
||||
label_fmt_if_changed(lblBezug, "%.1f g\n/ %.1f g", wDisp, shotTarget);
|
||||
} else {
|
||||
lv_label_set_text_fmt(lblBezug, "%.1f g", wDisp);
|
||||
label_fmt_if_changed(lblBezug, "%.1f g", wDisp);
|
||||
}
|
||||
// Fortschrittsbalken Gewicht/Ziel (nur waehrend BBW-Bezug)
|
||||
if (g_bbwBar) {
|
||||
|
||||
Reference in New Issue
Block a user