Compare commits

...
Author SHA1 Message Date
raw-designsandClaude Opus 5 16d8465b0c perf(P4): LVGL zeichnet direkt in den Bildspeicher (1.9.0)
Die Messung aus 1.8.8 hat es gezeigt: Jeder Bildaufbau kostete 240-300 ms,
dauerhaft, auch im Leerlauf. Die fünf Sekunden für den Aufweckdialog waren
rund zwanzig solcher Durchgänge - meine bisherigen Erklärungen (Fades,
Scrims) waren Symptome, nicht die Ursache.

Grund: zwei Durchgänge durch je 2,7 MB PSRAM pro Bild. LVGL rendert in einen
eigenen Draw-Buffer, esp_lcd_panel_draw_bitmap kopiert ihn danach komplett
in den Framebuffer.

WS7_DIRECT_FB holt den Framebuffer über esp_lcd_dpi_panel_get_frame_buffer
und übergibt ihn als LVGL-Draw-Buffer. Der IDF-Treiber erkennt das
(draw_buffer im Framebuffer-Bereich) und macht nur noch Cache-Writeback statt
Kopie; dazu LV_DISPLAY_RENDER_MODE_DIRECT, sodass nur geänderte Bereiche neu
gezeichnet werden.

Außerdem:
- Shot-Timer und Waage behalten während eines Bezugs die normale Schrift;
  der Wechsel auf den fetten 96er ist entfernt.
- Größe der Standby-Uhr einstellbar (120/180/240 px, Info-Seite,
  NVS ui/uhrgr). Wirkt sofort - sie hängt an einem einzigen Label.
- Die Knöpfe des Aufweckdialogs skalieren mit der Schriftgröße.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 01:27:14 +02:00
thomas 407d938031 Merge pull request 'diag(P4): Bildaufbau messen, Dialogknöpfe skalieren (1.8.8)' (#68) from diag/bildaufbau-messen into main 2026-09-03 01:01:36 +02:00
raw-designsandClaude Opus 5 33ce2b3ab9 diag(P4): Bildaufbau messen, Dialogknöpfe skalieren (1.8.8)
Der Aufweckdialog braucht weiterhin ~5 s. Zwei Erklärungsversuche lagen
daneben (Fade-Animationen, transparenter Scrim), also wird ab jetzt
gemessen statt geraten.

- refr_monitor_install() hängt sich über LV_EVENT_REFR_START/READY an die
  Anzeige und meldet jeden Zeichenzyklus, der 200 ms überschreitet. Im
  Normalbetrieb bleibt die Konsole still.
- Der Aufweckdialog berücksichtigt die Schriftgröße jetzt vollständig:
  Knöpfe mit font_text() statt geerbter Grundschrift, Breite 150/210/280 je
  Stufe. Bisher wirkten sie neben dem größeren Text verloren.
- Die große Standby-Uhr bleibt bewusst fest: Sie ist auf die Bildschirmhöhe
  abgestimmt.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01STPpZoK3ToDhrcniVqE6MJ
2026-09-03 01:01:19 +02:00
thomas d4d4f2b9d2 Merge pull request 'fix(P4): Aufweckdialog sofort statt nach fünf Sekunden (1.8.7)' (#67) from fix/vorhaenge-deckend-und-dialogbreite into main 2026-09-03 00:47:35 +02:00
raw-designsandClaude Opus 5 9fef4f8a6e fix(P4): Aufweckdialog sofort statt nach fünf Sekunden (1.8.7)
Vom Fingertipp auf die Standby-Uhr bis zum Dialog vergingen ~5 s mit
schwarzem Bildschirm. Ursache war der Scrim mit LV_OPA_70 über den ganzen
Bildschirm: Ein durchscheinender Vollbild-Layer zwingt LVGL zu einem
Zwischenpuffer und zum Mischen der gesamten Fläche - bei 1280x720 in 24 Bit
die teuerste Operation überhaupt.

- Wake-Scrim auf WS_PANEL_7H jetzt LV_OPA_COVER. Verloren geht nichts: Im
  Standby liegt dahinter ohnehin nur Schwarz.
- Der Drawer-Scrim (LV_OPA_50) hat dasselbe Problem und ist ebenfalls
  deckend, in 0x0d0d0d - auf dunklem Grund optisch praktisch identisch.
- Die JC-Panels behalten in beiden Fällen die Transparenz.
- Die Dialogkarte wächst mit der Schriftgröße (420 / 640 / 900 px), damit
  der Text nicht an unglücklichen Stellen umbricht.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01STPpZoK3ToDhrcniVqE6MJ
2026-09-03 00:47:16 +02:00
thomas 0f5b681421 Merge pull request 'feat(P4): Uhr läuft lokal weiter, wenn die S3 keine Zeit liefert (1.8.6)' (#66) from feat/uhr-laeuft-lokal-weiter into main 2026-09-03 00:34:07 +02:00
7 changed files with 9431 additions and 15 deletions
+44
View File
@@ -1,3 +1,47 @@
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
+2
View File
@@ -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
+27 -1
View File
@@ -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
+4
View File
@@ -39,6 +39,10 @@
// 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 zu zeichnen und
// den danach zu kopieren. Spart pro Bild einen kompletten Durchgang durch 2,7 MB PSRAM
// und laesst LVGL nur die geaenderten Bereiche neu zeichnen. Braucht WS7_SINGLE_FB.
#define WS7_DIRECT_FB 1
#define WS7_PARALLEL_RENDER 1
#define EXAMPLE_LVGL_PORT_TASK_MAX_DELAY_MS 500 //range 2 to 2000
+110 -14
View File
@@ -23,6 +23,7 @@
#include <Preferences.h>
#include "esp_system.h"
#include "display_hal.h"
#include "esp_rom_sys.h"
// ------------------------------------------------------------------------------------
// Schriftgroesse
@@ -197,8 +198,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 +690,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);
@@ -1300,10 +1317,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);
@@ -3041,6 +3054,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 +3108,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);
@@ -3412,6 +3451,33 @@ 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 void refr_start_cb(lv_event_t*) { g_refrStart = lv_tick_get(); }
static void refr_ready_cb(lv_event_t*) {
uint32_t d = lv_tick_get() - g_refrStart;
if (d >= REFR_WARN_MS) esp_rom_printf("[UI] Bildaufbau %u ms\n", (unsigned)d);
}
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 +3496,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);
@@ -3553,8 +3621,16 @@ 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
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);
@@ -3621,7 +3697,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 +3710,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 +3751,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 +3769,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 +3880,7 @@ void ui_init(ProtocolClient* client) {
show_page(PG_DASH);
if (g_client) g_client->sendListProfiles();
refr_monitor_install();
g_uiReady = true;
}
@@ -3880,10 +3975,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 +3991,7 @@ static void dash_brew_mode_tick(const MachineState& st) {
}
// ------------------------------------------------------------------------------------
// Uhr läuft lokal weiter
//