Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
326af4288a | ||
|
|
2e8651bc00 | ||
|
|
b13e5fdaf1 | ||
|
|
671a6696ce | ||
|
|
288f61447d | ||
|
|
a91c792491 | ||
|
|
e32c654b8d | ||
|
|
484812cb4c | ||
|
|
ff23e0e614 | ||
|
|
09b5231357 | ||
|
|
16d8465b0c | ||
|
|
407d938031 | ||
|
|
33ce2b3ab9 | ||
|
|
d4d4f2b9d2 | ||
|
|
9fef4f8a6e | ||
|
|
0f5b681421 |
@@ -1,3 +1,114 @@
|
||||
Version 1.9.5:
|
||||
- Die festen Breiten aus 1.9.4 haben nicht gereicht: Auch die HÖHE muss festliegen. LVGL
|
||||
prüft beim Setzen eines Textes, ob sich die Eigengröße der Beschriftung geändert haben
|
||||
könnte - ist eines der beiden Maße frei, gilt das Layout des Elternteils als neu zu
|
||||
berechnen, und das macht die ganze Seite ungültig. Temperaturwerte, Sollwerte, die Werte
|
||||
der unteren Zeile und die Uhrzeit in der Kopfleiste haben jetzt feste Maße in beide
|
||||
Richtungen.
|
||||
- Die Uhrzeit hatte denselben Effekt in der Kopfleiste: Beim Wechsel der Minute wurde die
|
||||
Leiste samt Menü-Knopf neu berechnet. Das erklärt den Bereich „x 6..57, y 2..41", der in
|
||||
fast jedem Durchgang auftauchte.
|
||||
- Zusätzlich meldet die Firmware jetzt, wenn der Inhaltsbereich oder die Dashboard-Seite als
|
||||
Ganzes ungültig gemacht wird. Damit ist zu unterscheiden, ob eine einzelne Beschriftung
|
||||
den Bildaufbau auslöst oder gleich der komplette Bereich - zwei verschiedene Ursachen mit
|
||||
verschiedenen Gegenmitteln.
|
||||
|
||||
Version 1.9.4:
|
||||
- Die Messung mit Koordinaten hat den Verursacher benannt: Der ungültige Bereich war
|
||||
„x 0..1279, y 44..719" - also der gesamte Inhalt unterhalb der Kopfleiste, bei jeder
|
||||
Zustandsmeldung.
|
||||
- Grund: Die Anzeigewerte hatten keine feste Breite. Wächst oder schrumpft eine Beschriftung
|
||||
mit ihrem Inhalt - etwa von „92,4 °C" auf „100,1 °C" -, rechnet LVGL das Layout der
|
||||
gesamten Seite neu und macht sie dabei komplett ungültig. Es genügt also nicht, den Text
|
||||
nur bei echter Änderung zu setzen; er darf beim Ändern auch die Breite nicht verändern.
|
||||
- Temperaturwerte, Sollwerte und die Werte der unteren Zeile haben jetzt eine feste Breite
|
||||
mit zentriertem Text. Sichtbar ändert sich dadurch nichts - die Werte standen ohnehin
|
||||
mittig.
|
||||
|
||||
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
|
||||
erzeugt, weil in denselben Speicher gezeichnet wird, aus dem gerade angezeigt wird.
|
||||
Damit ist auch klar, dass der Flaschenhals nicht im Kopieren liegt, sondern im Zeichnen
|
||||
selbst. Der Schalter WS7_DIRECT_FB bleibt samt Begründung erhalten.
|
||||
- Die Messung sagt jetzt zusätzlich, WIE VIEL neu gezeichnet wurde: Anzahl der Bereiche und
|
||||
ihr Anteil an der Gesamtfläche. Erst damit lässt sich unterscheiden, ob LVGL nur kleine
|
||||
Bereiche anfasst - dann ist das Zeichnen an sich zu langsam - oder ob jedes Mal der ganze
|
||||
Bildschirm neu entsteht, weil ihn etwas unnötig ungültig macht. Das sind zwei völlig
|
||||
verschiedene Ursachen mit verschiedenen Gegenmitteln.
|
||||
|
||||
Version 1.9.0:
|
||||
- Die Messung aus 1.8.8 hat die Ursache der Trägheit gefunden: Jeder Bildaufbau kostete
|
||||
240 bis 300 Millisekunden - dauerhaft, auch im Leerlauf. Fünf Sekunden für den
|
||||
Aufweckdialog waren also rund zwanzig solcher Durchgänge.
|
||||
- Grund war, dass zweimal durch den Bildspeicher gearbeitet wurde: LVGL zeichnete in einen
|
||||
eigenen Puffer, und dessen Inhalt wurde anschließend vollständig in den Bildspeicher
|
||||
kopiert. Bei 1280x720 in 24 Bit sind das zwei Durchgänge durch je 2,7 MB.
|
||||
- LVGL zeichnet jetzt direkt in den Bildspeicher. Der Treiber lässt das Kopieren dann weg,
|
||||
und LVGL zeichnet nur noch die geänderten Bereiche statt jedes Mal die ganze Fläche.
|
||||
Schalter WS7_DIRECT_FB in pins_config.h.
|
||||
- Die Anzeigen von Shot-Timer und Waage bleiben während eines Bezugs in der normalen
|
||||
Schrift; der fette Wechsel ist entfernt. Der Bereich bekommt weiterhin mehr Platz.
|
||||
- Neu: Die Größe der Standby-Uhr lässt sich einstellen (Klein, Mittel, Groß - 120, 180 oder
|
||||
240 Pixel), zu finden auf der Info-Seite unter Darstellung. Anders als die allgemeine
|
||||
Schriftgröße wirkt sie sofort, weil sie an einem einzigen Textfeld hängt.
|
||||
- Die Knöpfe des Aufweckdialogs berücksichtigen jetzt ebenfalls die eingestellte
|
||||
Schriftgröße und wachsen mit.
|
||||
|
||||
Version 1.8.8:
|
||||
- Der Aufweckdialog berücksichtigt jetzt die eingestellte Schriftgröße vollständig: Die
|
||||
Knöpfe bekommen dieselbe Schrift wie der Text und wachsen mit (150 / 210 / 280 Pixel).
|
||||
Bisher erbten sie die kleine Grundschrift und behielten eine feste Breite - neben dem
|
||||
größeren Text wirkten sie dadurch verloren.
|
||||
- Die große Standby-Uhr bleibt bewusst bei ihrer festen Größe: Sie ist bereits auf die
|
||||
Bildschirmhöhe abgestimmt, eine Umschaltung würde sie nur schlechter passend machen.
|
||||
- Neu: eine Zeitmessung für langsame Bildaufbauten. Überschreitet ein Zeichenzyklus
|
||||
200 Millisekunden, meldet die serielle Konsole seine Dauer. Damit lässt sich feststellen,
|
||||
welcher Vorgang tatsächlich Zeit kostet - die bisherigen Erklärungen für die Verzögerung
|
||||
beim Aufweckdialog haben sich als falsch erwiesen, und weiteres Raten hilft nicht.
|
||||
Im Normalbetrieb bleibt die Ausgabe still.
|
||||
|
||||
Version 1.8.7:
|
||||
- Vom Fingertipp auf die Standby-Uhr bis zum Aufweckdialog vergingen rund fünf Sekunden mit
|
||||
schwarzem Bildschirm. Ursache war der halbdurchsichtige Vorhang, den der Dialog über den
|
||||
ganzen Bildschirm legt: Dafür muss LVGL einen Vollbild-Zwischenpuffer anlegen und die
|
||||
gesamte Fläche mischen - bei 1280x720 in 24 Bit die teuerste Operation überhaupt.
|
||||
- Der Vorhang ist auf dem Waveshare-Panel jetzt deckend. Verloren geht dabei nichts: Im
|
||||
Standby liegt dahinter ohnehin nur Schwarz.
|
||||
- Aus demselben Grund ist auch der Vorhang des Menüs deckend, in einem dunklen Ton. Auf
|
||||
dunklem Grund sieht das praktisch genauso aus wie halbdurchsichtig, spart aber dieselbe
|
||||
Mischarbeit. Die JC-Panels behalten in beiden Fällen die Transparenz.
|
||||
- Der Aufweckdialog wird mit größerer Schrift auch breiter (420 / 640 / 900 Pixel), damit
|
||||
der Text nicht an unglücklichen Stellen umbricht.
|
||||
|
||||
Version 1.8.6:
|
||||
- Die Uhrzeit verschwindet nicht mehr, wenn die Hauptplatine ihre Zeit gerade neu abgleicht.
|
||||
Der P4 merkt sich die zuletzt empfangene Uhrzeit und zählt zwischen den Meldungen selbst
|
||||
|
||||
@@ -569,6 +569,8 @@
|
||||
LV_FONT_DECLARE(lv_font_maven_pro_48) \
|
||||
LV_FONT_DECLARE(lv_font_maven_pro_bold_96) \
|
||||
LV_FONT_DECLARE(lv_font_maven_pro_bold_140) \
|
||||
LV_FONT_DECLARE(lv_font_clock_120) \
|
||||
LV_FONT_DECLARE(lv_font_clock_180) \
|
||||
LV_FONT_DECLARE(lv_font_clock_240)
|
||||
|
||||
/*Always set a default font*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -496,6 +496,32 @@ static lv_display_t *display_init(esp_lcd_panel_handle_t panel_handle)
|
||||
// buf1 = heap_caps_malloc(buffer_size * sizeof(lv_color_t), MALLOC_CAP_DMA);
|
||||
assert(buf1);
|
||||
ESP_LOGI(TAG, "LVGL buffer size: %dKB", buffer_size * sizeof(lv_color_t) / 1024);
|
||||
|
||||
#if WS7_DIRECT_FB
|
||||
// PROJEKTAENDERUNG: LVGL zeichnet direkt in den Bildspeicher.
|
||||
//
|
||||
// Der Hersteller-Port legt einen eigenen Zeichenpuffer an; der fertige Inhalt wird
|
||||
// danach in den Bildspeicher kopiert. Bei 1280x720 in 24 Bit sind das zwei Durchgaenge
|
||||
// durch je 2,7 MB PSRAM - gemessen rund 250 bis 300 ms pro Bild, und das dauerhaft.
|
||||
// Genau deshalb hing die Oberflaeche eine gute Viertelsekunde hinterher, und Vorgaenge
|
||||
// mit mehreren Bildern brauchten Sekunden.
|
||||
//
|
||||
// Ist der Zeichenpuffer derselbe Speicher wie der Bildspeicher, laesst der
|
||||
// esp_lcd-Treiber das Kopieren weg und schreibt nur den Prozessor-Cache zurueck. Dazu
|
||||
// kommt LV_DISPLAY_RENDER_MODE_DIRECT: LVGL zeichnet dann nur die geaenderten Bereiche
|
||||
// neu, statt jedes Mal die ganze Flaeche.
|
||||
//
|
||||
// Preis: Gezeichnet wird in den Speicher, der gerade angezeigt wird - bei schnellen
|
||||
// Wechseln kann kurz eine Kante durchs Bild laufen. Mit nur einem Bildspeicher (den das
|
||||
// Panel verlangt, siehe WS7_SINGLE_FB) ist das ohnehin nicht zu vermeiden.
|
||||
void* fb0 = NULL;
|
||||
if (esp_lcd_dpi_panel_get_frame_buffer(panel_handle, 1, &fb0) == ESP_OK && fb0) {
|
||||
buf1 = fb0;
|
||||
buffer_size = LVGL_PORT_H_RES * LVGL_PORT_V_RES;
|
||||
ESP_LOGI(TAG, "LVGL zeichnet direkt in den Bildspeicher (%dKB)",
|
||||
(int)(buffer_size * sizeof(lv_color_t) / 1024));
|
||||
}
|
||||
#endif
|
||||
#endif /* LVGL_PORT_AVOID_TEAR_ENABLE */
|
||||
|
||||
ESP_LOGD(TAG, "Register display driver to LVGL");
|
||||
@@ -511,7 +537,7 @@ static lv_display_t *display_init(esp_lcd_panel_handle_t panel_handle)
|
||||
display, buf1, buf2, buffer_size * sizeof(lv_color_t),
|
||||
#if LVGL_PORT_FULL_REFRESH
|
||||
LV_DISPLAY_RENDER_MODE_FULL
|
||||
#elif LVGL_PORT_DIRECT_MODE
|
||||
#elif LVGL_PORT_DIRECT_MODE || WS7_DIRECT_FB
|
||||
LV_DISPLAY_RENDER_MODE_DIRECT
|
||||
#else
|
||||
LV_DISPLAY_RENDER_MODE_PARTIAL
|
||||
|
||||
@@ -39,6 +39,12 @@
|
||||
// nicht - siehe die ausfuehrliche Begruendung weiter unten beim Avoid-Tear-Schalter.
|
||||
// Auf 0 nur, wenn das Startverhalten erneut untersucht wird.
|
||||
#define WS7_SINGLE_FB 1
|
||||
// LVGL zeichnet direkt in den Bildspeicher statt in einen eigenen Puffer, dessen Inhalt
|
||||
// danach kopiert wird. GEPRUEFT: bringt an diesem Panel nichts (die Bildaufbauzeit blieb bei
|
||||
// 240-300 ms) und erzeugt Bildfehler, weil in denselben Speicher gezeichnet wird, aus dem
|
||||
// gerade angezeigt wird. Der Flaschenhals liegt also nicht im Kopieren, sondern im Zeichnen
|
||||
// selbst. Bleibt als Schalter erhalten, damit der Versuch nicht erneut gemacht wird.
|
||||
#define WS7_DIRECT_FB 0
|
||||
#define WS7_PARALLEL_RENDER 1
|
||||
|
||||
#define EXAMPLE_LVGL_PORT_TASK_MAX_DELAY_MS 500 //range 2 to 2000
|
||||
|
||||
+235
-44
@@ -23,6 +23,9 @@
|
||||
#include <Preferences.h>
|
||||
#include "esp_system.h"
|
||||
#include "display_hal.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "lvgl_private.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Schriftgroesse
|
||||
@@ -197,8 +200,6 @@ static lv_obj_t* g_profPickerList = nullptr; // Button-Liste im Overlay
|
||||
static lv_obj_t* g_profPickerInfo = nullptr; // "Lade Profile..."-Hinweis im Overlay
|
||||
static lv_obj_t* g_infoRow = nullptr; // untere Zeile; waechst waehrend eines Bezugs
|
||||
static bool g_dashBrewMode = false;
|
||||
static const lv_font_t* g_shotFontNormal = nullptr;
|
||||
static const lv_font_t* g_bezugFontNormal = nullptr;
|
||||
static lv_obj_t* cellShot; static lv_obj_t* lblShotTimer; static lv_obj_t* g_bbtBar = nullptr;
|
||||
static lv_obj_t* cellSteam; static lv_obj_t* lblSteamTimer; static lv_obj_t* g_sbtBar = nullptr;
|
||||
static lv_obj_t* cellBezug; static lv_obj_t* lblBezug; static lv_obj_t* g_bbwBar = nullptr;
|
||||
@@ -691,6 +692,24 @@ static void stat_list_finish(int used) {
|
||||
}
|
||||
}
|
||||
|
||||
// Groesse der Standby-Uhr. Anders als die allgemeine Schriftgroesse braucht diese keinen
|
||||
// Neustart: Es haengt an genau EINEM Textfeld, das sich sofort umstellen laesst.
|
||||
enum { UHR_KLEIN = 0, UHR_MITTEL = 1, UHR_GROSS = 2 };
|
||||
static uint8_t g_clockSize = UHR_GROSS;
|
||||
static lv_obj_t* g_clockSizeBtn[3] = {};
|
||||
|
||||
static const lv_font_t* clock_font() {
|
||||
switch (g_clockSize) {
|
||||
case UHR_KLEIN: return &lv_font_clock_120;
|
||||
case UHR_MITTEL: return &lv_font_clock_180;
|
||||
default: return &lv_font_clock_240;
|
||||
}
|
||||
}
|
||||
|
||||
static void clock_size_apply() {
|
||||
if (g_standbyClock) lv_obj_set_style_text_font(g_standbyClock, clock_font(), 0);
|
||||
}
|
||||
|
||||
static void scroll_ohne_nachlauf(lv_obj_t* o) {
|
||||
#if JC_PANEL_TYPE == WS_PANEL_7H
|
||||
lv_obj_clear_flag(o, LV_OBJ_FLAG_SCROLL_MOMENTUM);
|
||||
@@ -967,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);
|
||||
@@ -1034,6 +1056,18 @@ static lv_obj_t* tempField(lv_obj_t* parent, const char* title, lv_color_t accen
|
||||
lv_label_set_text(*big, "--.-");
|
||||
lv_obj_set_style_text_color(*big, COL_TEXT, 0);
|
||||
lv_obj_set_style_text_font(*big, valueFont, 0);
|
||||
// Feste Breite, Text zentriert. Waechst oder schrumpft eine Beschriftung mit ihrem
|
||||
// Inhalt - etwa von "92,4 °C" auf "100,1 °C" -, rechnet LVGL das Flex-Layout der
|
||||
// gesamten Seite neu und macht sie damit komplett ungueltig. Genau das war im
|
||||
// Messprotokoll als "x 0..1279, y 44..719" zu sehen: der ganze Inhaltsbereich, bei
|
||||
// jeder Zustandsmeldung. Mit fester Breite bleibt nur die Beschriftung selbst ungueltig.
|
||||
lv_obj_set_width(*big, LV_PCT(100));
|
||||
lv_obj_set_style_text_align(*big, LV_TEXT_ALIGN_CENTER, 0);
|
||||
// Auch die HOEHE muss fest sein. LVGL prueft beim Setzen eines Textes, ob sich die
|
||||
// Eigengroesse der Beschriftung geaendert haben koennte - ist eines der beiden Masse
|
||||
// frei, gilt das Layout des Elternteils als neu zu berechnen, und das macht die ganze
|
||||
// Seite ungueltig. Erst mit festen Massen bleibt nur die Beschriftung selbst ungueltig.
|
||||
lv_obj_set_height(*big, lv_font_get_line_height(valueFont) + 6);
|
||||
// Grosse Zahlen etwas enger setzen. Bei dieser Groesse wirken die Werksabstaende
|
||||
// auseinandergezogen; ein paar Pixel weniger binden die Ziffern zu einer Zahl zusammen.
|
||||
if (valueFont == &lv_font_maven_pro_bold_140) lv_obj_set_style_text_letter_space(*big, -3, 0);
|
||||
@@ -1043,6 +1077,9 @@ static lv_obj_t* tempField(lv_obj_t* parent, const char* title, lv_color_t accen
|
||||
lv_label_set_text(*setp, "Soll --.-");
|
||||
lv_obj_set_style_text_color(*setp, COL_TEXT_DIM, 0);
|
||||
lv_obj_set_style_text_font(*setp, font_text(), 0);
|
||||
lv_obj_set_width(*setp, LV_PCT(100));
|
||||
lv_obj_set_style_text_align(*setp, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_set_height(*setp, lv_font_get_line_height(font_text()) + 6);
|
||||
|
||||
*bar = lv_bar_create(c);
|
||||
lv_obj_set_size(*bar, LV_PCT(92), 8);
|
||||
@@ -1188,6 +1225,10 @@ static lv_obj_t* infoCell(lv_obj_t* parent, const char* title, lv_obj_t** val, l
|
||||
lv_obj_set_style_text_color(*val, COL_TEXT, 0);
|
||||
lv_obj_set_style_text_font(*val, font_title(), 0);
|
||||
lv_obj_set_style_text_align(*val, LV_TEXT_ALIGN_CENTER, 0); // fuer mehrzeilige Werte
|
||||
// Feste Masse in BEIDE Richtungen - siehe die ausfuehrliche Begruendung in tempField.
|
||||
// Zwei Zeilen Platz, weil manche Werte zweizeilig sind ("32,4 g / 36,0 g").
|
||||
lv_obj_set_width(*val, LV_PCT(100));
|
||||
lv_obj_set_height(*val, lv_font_get_line_height(font_title()) * 2 + 6);
|
||||
return card;
|
||||
}
|
||||
// Tipp auf die Statuszeile: Wartung -> Serviceseite, Reinigung -> Sub-Screen,
|
||||
@@ -1300,10 +1341,6 @@ static void build_dashboard(lv_obj_t* p) {
|
||||
lv_bar_set_range(g_bbwBar, 0, 100);
|
||||
lv_bar_set_value(g_bbwBar, 0, LV_ANIM_OFF);
|
||||
lv_obj_add_flag(g_bbwBar, LV_OBJ_FLAG_HIDDEN);
|
||||
// Normalschriften merken, damit der Bezugsmodus sie wieder herstellen kann
|
||||
g_shotFontNormal = lv_obj_get_style_text_font(lblShotTimer, LV_PART_MAIN);
|
||||
g_bezugFontNormal = lv_obj_get_style_text_font(lblBezug, LV_PART_MAIN);
|
||||
|
||||
cellFlow = infoCell(ir, "FLOW", &lblFlow, lv_color_hex(0x64b5f6));
|
||||
lv_obj_add_flag(cellFlow, LV_OBJ_FLAG_CLICKABLE); // antippbar -> Brew-Control
|
||||
lv_obj_add_event_cb(cellFlow, brew_cell_cb, LV_EVENT_CLICKED, nullptr);
|
||||
@@ -1363,7 +1400,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();
|
||||
@@ -1371,7 +1408,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();
|
||||
@@ -3041,6 +3078,18 @@ static void design_btn_cb(lv_event_t* e) {
|
||||
// Live-Bezugsschirm ein-/ausschalten (P4-lokal in NVS gespeichert)
|
||||
// Temperaturzahl einfaerben oder weiss lassen. Wirkt sofort - die Farbe wird bei jeder
|
||||
// Zustandsmeldung neu gesetzt, es muss nichts neu aufgebaut werden.
|
||||
// Groesse der Standby-Uhr waehlen. Wirkt sofort - es haengt an einem einzigen Textfeld.
|
||||
static void clock_size_cb(lv_event_t* e) {
|
||||
g_clockSize = (uint8_t)(intptr_t)lv_event_get_user_data(e);
|
||||
{ Preferences prefs; prefs.begin("ui", false); prefs.putUChar("uhrgr", g_clockSize); prefs.end(); }
|
||||
clock_size_apply();
|
||||
for (int i = 0; i < 3; i++) if (g_clockSizeBtn[i]) {
|
||||
bool an = (i == g_clockSize);
|
||||
lv_obj_set_style_bg_color(g_clockSizeBtn[i], an ? COL_ACCENT : COL_CARD2, 0);
|
||||
lv_obj_set_style_text_color(g_clockSizeBtn[i], an ? lv_color_hex(0x000000) : COL_TEXT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void temp_color_sw_cb(lv_event_t* e) {
|
||||
g_tempColored = sw_get((lv_obj_t*)lv_event_get_target(e));
|
||||
{ Preferences prefs; prefs.begin("ui", false); prefs.putBool("tempcol", g_tempColored); prefs.end(); }
|
||||
@@ -3083,6 +3132,20 @@ static void build_info(lv_obj_t* p) {
|
||||
lv_obj_add_event_cb(fb, font_pick_cb, LV_EVENT_CLICKED, (void*)(intptr_t)i);
|
||||
}
|
||||
|
||||
lv_obj_t* cl = lv_label_create(dcard);
|
||||
lv_label_set_text(cl, "Uhrgröße im Standby");
|
||||
lv_obj_set_style_text_color(cl, COL_TEXT_DIM, 0);
|
||||
lv_obj_t* crow = row(dcard, nullptr);
|
||||
lv_obj_set_style_pad_column(crow, 8, 0);
|
||||
static const char* UHR_NAMEN[3] = { "Klein", "Mittel", "Groß" };
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
lv_obj_t* b = (i == g_clockSize) ? th_accent_button(crow, UHR_NAMEN[i])
|
||||
: th_button(crow, UHR_NAMEN[i], COL_CARD2, COL_TEXT);
|
||||
lv_obj_set_flex_grow(b, 1);
|
||||
lv_obj_add_event_cb(b, clock_size_cb, LV_EVENT_CLICKED, (void*)(intptr_t)i);
|
||||
g_clockSizeBtn[i] = b;
|
||||
}
|
||||
|
||||
lv_obj_t* swTempCol = add_switch(dcard, "Temperaturzahl in der Zustandsfarbe");
|
||||
sw_set(swTempCol, g_tempColored);
|
||||
lv_obj_add_event_cb(swTempCol, temp_color_sw_cb, LV_EVENT_VALUE_CHANGED, nullptr);
|
||||
@@ -3200,10 +3263,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
|
||||
@@ -3412,6 +3500,73 @@ static void dash_timers_cb(lv_timer_t*) {
|
||||
// sonst greifen sie auf nicht angelegte LVGL-Objekte zu.
|
||||
static bool g_uiReady = false;
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Zeitmessung fuer langsame Bildaufbauten
|
||||
//
|
||||
// Beim 7-Zoll-Panel dauern manche Vorgaenge spuerbar lange, und aus dem Quelltext allein
|
||||
// ist nicht zu sehen, welcher Teil die Zeit frisst. LVGL meldet Anfang und Ende jedes
|
||||
// Zeichenzyklus - hier wird die Dauer gemessen und nur dann ausgegeben, wenn sie eine
|
||||
// Schwelle ueberschreitet. Im Normalbetrieb bleibt die Konsole still.
|
||||
// ------------------------------------------------------------------------------------
|
||||
#define REFR_WARN_MS 200
|
||||
|
||||
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
|
||||
// langsam - oder ob jedes Mal der ganze Bildschirm neu entsteht, weil ihn etwas unnoetig
|
||||
// ungueltig macht.
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
static void refr_ready_cb(lv_event_t*) {
|
||||
uint32_t d = lv_tick_get() - g_refrStart;
|
||||
if (d < REFR_WARN_MS) return;
|
||||
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);
|
||||
}
|
||||
|
||||
// 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 refr_monitor_install() {
|
||||
lv_display_t* d = lv_display_get_default();
|
||||
if (!d) return;
|
||||
lv_display_add_event_cb(d, refr_start_cb, LV_EVENT_REFR_START, nullptr);
|
||||
lv_display_add_event_cb(d, refr_ready_cb, LV_EVENT_REFR_READY, nullptr);
|
||||
}
|
||||
|
||||
void ui_init(ProtocolClient* client) {
|
||||
g_client = client;
|
||||
|
||||
@@ -3430,6 +3585,8 @@ void ui_init(ProtocolClient* client) {
|
||||
if (g_tempDesign >= TD_DESIGN_COUNT) g_tempDesign = TD_BAND;
|
||||
g_brewLiveEnabled = prefs.getBool("brewlive", true);
|
||||
g_tempColored = prefs.getBool("tempcol", false);
|
||||
g_clockSize = prefs.getUChar("uhrgr", UHR_GROSS);
|
||||
if (g_clockSize > UHR_GROSS) g_clockSize = UHR_GROSS;
|
||||
g_chartWin = prefs.getUChar("chartwin", 0);
|
||||
if (g_chartWin > 3) g_chartWin = 0;
|
||||
g_chartDuty = prefs.getBool("chartduty", false);
|
||||
@@ -3520,6 +3677,11 @@ void ui_init(ProtocolClient* client) {
|
||||
lv_obj_set_style_text_color(g_clock, COL_TEXT, 0);
|
||||
lv_obj_set_style_pad_right(g_clock, 10, 0);
|
||||
lv_obj_set_style_text_font(g_clock, font_text(), 0);
|
||||
// Feste Masse, sonst rechnet LVGL beim Wechsel der Minute das Layout der Kopfleiste neu
|
||||
// und macht sie samt Menue-Knopf ungueltig (siehe tempField).
|
||||
lv_obj_set_width(g_clock, 130);
|
||||
lv_obj_set_height(g_clock, lv_font_get_line_height(font_text()) + 4);
|
||||
lv_obj_set_style_text_align(g_clock, LV_TEXT_ALIGN_RIGHT, 0);
|
||||
|
||||
g_wifiIcon = lv_label_create(header);
|
||||
lv_label_set_text(g_wifiIcon, LV_SYMBOL_WIFI);
|
||||
@@ -3553,6 +3715,9 @@ 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);
|
||||
// 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);
|
||||
lv_obj_set_style_border_width(g_drawer, 0, 0);
|
||||
@@ -3621,7 +3786,7 @@ void ui_init(ProtocolClient* client) {
|
||||
g_standbyClock = lv_label_create(g_standbyScreen);
|
||||
lv_label_set_text(g_standbyClock, "--:--");
|
||||
lv_obj_set_style_text_color(g_standbyClock, COL_TEXT, 0);
|
||||
lv_obj_set_style_text_font(g_standbyClock, &lv_font_clock_240, 0); // grosse Uhr im Standby
|
||||
lv_obj_set_style_text_font(g_standbyClock, clock_font(), 0); // Groesse einstellbar
|
||||
lv_obj_center(g_standbyClock);
|
||||
lv_obj_add_event_cb(g_standbyScreen, standby_screen_cb, LV_EVENT_CLICKED, nullptr); // Tippen -> Aufweck-Abfrage
|
||||
lv_obj_t* standbyHint = lv_label_create(g_standbyScreen); // dezenter Hinweis am unteren Rand
|
||||
@@ -3634,13 +3799,25 @@ void ui_init(ProtocolClient* client) {
|
||||
g_wakeConfirm = lv_obj_create(lv_layer_top());
|
||||
lv_obj_set_size(g_wakeConfirm, LV_PCT(100), LV_PCT(100));
|
||||
lv_obj_set_style_bg_color(g_wakeConfirm, lv_color_hex(0x000000), 0);
|
||||
#if JC_PANEL_TYPE == WS_PANEL_7H
|
||||
// Deckend statt halbtransparent. Ein durchscheinender Vorhang ueber den ganzen
|
||||
// Bildschirm zwingt LVGL, einen Vollbild-Zwischenpuffer anzulegen und die gesamte
|
||||
// Flaeche zu mischen - bei 1280x720 in 24 Bit dauerte das rund fuenf Sekunden, in
|
||||
// denen nach dem Fingertipp nur der schwarze Standby-Bildschirm zu sehen war.
|
||||
// Verloren geht dabei nichts: Dahinter liegt im Standby ohnehin nur Schwarz.
|
||||
lv_obj_set_style_bg_opa(g_wakeConfirm, LV_OPA_COVER, 0);
|
||||
#else
|
||||
lv_obj_set_style_bg_opa(g_wakeConfirm, LV_OPA_70, 0);
|
||||
#endif
|
||||
lv_obj_set_style_border_width(g_wakeConfirm, 0, 0);
|
||||
lv_obj_set_style_radius(g_wakeConfirm, 0, 0);
|
||||
lv_obj_clear_flag(g_wakeConfirm, LV_OBJ_FLAG_SCROLLABLE);
|
||||
lv_obj_add_flag(g_wakeConfirm, LV_OBJ_FLAG_CLICKABLE); // Scrim faengt Tipps ab
|
||||
lv_obj_t* wakeCard = th_card(g_wakeConfirm);
|
||||
lv_obj_set_width(wakeCard, 420);
|
||||
// Breite waechst mit der gewaehlten Schriftgroesse mit. Bei fester Breite brach der
|
||||
// Text in der Stufe Gross an unguenstigen Stellen um.
|
||||
lv_obj_set_width(wakeCard, (g_fontStep == FONT_GROSS) ? 900
|
||||
: (g_fontStep == FONT_MITTEL) ? 640 : 420);
|
||||
lv_obj_set_height(wakeCard, LV_SIZE_CONTENT);
|
||||
lv_obj_center(wakeCard);
|
||||
lv_obj_set_flex_flow(wakeCard, LV_FLEX_FLOW_COLUMN);
|
||||
@@ -3663,12 +3840,17 @@ void ui_init(ProtocolClient* client) {
|
||||
lv_obj_set_flex_flow(wakeBtns, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_flex_align(wakeBtns, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_clear_flag(wakeBtns, LV_OBJ_FLAG_SCROLLABLE);
|
||||
// Knopfbreite und -schrift wachsen mit der Schriftgroesse mit; mit fester Breite und
|
||||
// geerbter Grundschrift wirkten die Knoepfe neben dem groesseren Text verloren.
|
||||
const int32_t wakeBtnW = (g_fontStep == FONT_GROSS) ? 280 : (g_fontStep == FONT_MITTEL) ? 210 : 150;
|
||||
lv_obj_t* wakeNo = th_button(wakeBtns, "Abbrechen", COL_CARD2, COL_TEXT);
|
||||
lv_obj_set_width(wakeNo, 150);
|
||||
lv_obj_set_width(wakeNo, wakeBtnW);
|
||||
lv_obj_set_style_text_font(wakeNo, font_text(), 0);
|
||||
lv_obj_add_event_cb(wakeNo, wake_no_cb, LV_EVENT_CLICKED, nullptr);
|
||||
g_wakeNoBtn = wakeNo;
|
||||
lv_obj_t* wakeYes = th_accent_button(wakeBtns, "Aufwecken");
|
||||
lv_obj_set_width(wakeYes, 150);
|
||||
lv_obj_set_width(wakeYes, wakeBtnW);
|
||||
lv_obj_set_style_text_font(wakeYes, font_text(), 0);
|
||||
lv_obj_add_event_cb(wakeYes, wake_yes_cb, LV_EVENT_CLICKED, nullptr);
|
||||
g_wakeYesLbl = lv_obj_get_child(wakeYes, 0); // Label des Knopfs (fuer "Espresso" im Abfrage-Modus)
|
||||
// Zweite Zeile: direkt in die kalte Extraktion aufwecken. Ohne diesen Weg muesste man
|
||||
@@ -3676,6 +3858,7 @@ void ui_init(ProtocolClient* client) {
|
||||
// Nur sichtbar, wenn die S3 die Funktion freigeschaltet meldet (siehe ui_update).
|
||||
g_wakeColdBtn = th_button(wakeCard, "Cold Extraction (Wasser bleibt kalt)", COL_CARD2, COL_ACCENT);
|
||||
lv_obj_set_width(g_wakeColdBtn, LV_PCT(100));
|
||||
lv_obj_set_style_text_font(g_wakeColdBtn, font_text(), 0);
|
||||
lv_obj_add_event_cb(g_wakeColdBtn, wake_cold_cb, LV_EVENT_CLICKED, nullptr);
|
||||
lv_obj_add_flag(g_wakeColdBtn, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(g_wakeConfirm, LV_OBJ_FLAG_HIDDEN);
|
||||
@@ -3786,6 +3969,9 @@ void ui_init(ProtocolClient* client) {
|
||||
show_page(PG_DASH);
|
||||
if (g_client) g_client->sendListProfiles();
|
||||
|
||||
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");
|
||||
g_uiReady = true;
|
||||
}
|
||||
|
||||
@@ -3852,10 +4038,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3880,10 +4070,10 @@ static void dash_brew_mode(bool on) {
|
||||
if (!g_tempRow || !g_infoRow) return;
|
||||
lv_obj_set_flex_grow(g_tempRow, on ? 1 : 3);
|
||||
lv_obj_set_flex_grow(g_infoRow, on ? 3 : 2);
|
||||
if (lblShotTimer && g_shotFontNormal)
|
||||
lv_obj_set_style_text_font(lblShotTimer, on ? &lv_font_maven_pro_bold_96 : g_shotFontNormal, 0);
|
||||
if (lblBezug && g_bezugFontNormal)
|
||||
lv_obj_set_style_text_font(lblBezug, on ? &lv_font_maven_pro_bold_96 : g_bezugFontNormal, 0);
|
||||
// Die Schrift von Shot-Timer und Waage bleibt unveraendert. Frueher wechselte sie
|
||||
// waehrend des Bezugs auf den grossen fetten Schnitt - das wirkte gegenueber dem
|
||||
// restlichen Dashboard zu laut. Der Bereich bekommt weiterhin mehr Platz, die Zahlen
|
||||
// stehen dadurch freier, aber in derselben Schrift wie sonst auch.
|
||||
}
|
||||
|
||||
static void dash_brew_mode_tick(const MachineState& st) {
|
||||
@@ -3896,6 +4086,7 @@ static void dash_brew_mode_tick(const MachineState& st) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Uhr läuft lokal weiter
|
||||
//
|
||||
@@ -3947,7 +4138,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).
|
||||
@@ -4238,43 +4429,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);
|
||||
}
|
||||
@@ -4423,12 +4614,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