diff --git a/P4_Display_Firmware/Changelog.txt b/P4_Display_Firmware/Changelog.txt index aea0aff..b0836d9 100644 --- a/P4_Display_Firmware/Changelog.txt +++ b/P4_Display_Firmware/Changelog.txt @@ -1,3 +1,20 @@ +Version 1.8.4: +- Standby-Uhr und Aufweckdialog erscheinen jetzt sofort statt mit spürbarer Verzögerung. + Ursache waren die weichen Ein- und Ausblendungen: Eine Deckkraft-Animation ist bei einem + Bildspeicher in RGB888 das Teuerste, was die Oberfläche tun kann, weil für jedes Einzelbild + die gesamte Fläche unter der Ebene neu gezeichnet und mit ihr gemischt werden muss. Auf + 1280x720 dauerte eine solche Blende deutlich länger als die 450 ms, die vorgesehen waren. + Auf dem Waveshare-Panel laufen die Übergänge deshalb ohne Animation; die JC-Panels + behalten sie. +- Beim Wechsel der Schriftgröße blitzte kurz ein blaues Bild auf. Das kommt nicht von der + Firmware: Das Panel zeigt von sich aus Blau, sobald kein Videosignal anliegt - und beim + nötigen Neustart reißt das Signal kurz ab. Die Beleuchtung wird jetzt vorher abgeschaltet; + dunkel ist unauffälliger als blau. +- Neue Einstellung unter Darstellung: „Temperaturzahl in der Zustandsfarbe". Aus bleibt die + Zahl weiß, die Zustandsfarbe steckt dann allein im Balken darunter - ruhiger, und die Zahl + bleibt eine Zahl. Ein bedeutet, sie färbt sich mit, wie bisher. Vorgabe ist aus. + Warnungen bleiben in jedem Fall rot; das ist keine Gestaltung, sondern eine Meldung. + Version 1.8.3: - Fehlerbehebung: Bei allen Darstellungen stand hinter der Temperatur ein leeres Rechteck statt des C. Die beiden großen Schriften waren auf Ziffern, Komma, Punkt, Minus und diff --git a/P4_Display_Firmware/ui.cpp b/P4_Display_Firmware/ui.cpp index 0c7dee6..ace69fd 100644 --- a/P4_Display_Firmware/ui.cpp +++ b/P4_Display_Firmware/ui.cpp @@ -22,6 +22,7 @@ #include "ui.h" #include #include "esp_system.h" +#include "display_hal.h" // ------------------------------------------------------------------------------------ // Schriftgroesse @@ -82,6 +83,10 @@ static void font_step_save_and_restart(uint8_t step) { } // Der Zaehler der Absturzsicherung darf diesen gewollten Neustart nicht mitzaehlen. { Preferences b; if (b.begin("bootguard", false)) { b.putUShort("early", 0); b.end(); } } + // Beleuchtung aus, bevor der Neustart die Bildausgabe abreissen laesst. Ohne Signal + // zeigt das Panel von sich aus ein blaues Bild - das blitzte beim Wechsel der + // Schriftgroesse kurz auf. Dunkel ist unauffaelliger als blau. + hal_backlight(0); delay(120); esp_restart(); } @@ -168,6 +173,7 @@ static void label_set_if_changed(lv_obj_t* lbl, const char* txt); // Definitio // TD_THERMO - vertikale Thermometer-Saeulen mit Kolben und Glanzstreifen enum TempDesign { TD_GEWICHTET = 0, TD_VERLAUF, TD_FLAECHEN, TD_BAND, TD_DESIGN_COUNT }; static uint8_t g_tempDesign = TD_BAND; +static bool g_tempColored = false; // Temperaturzahl in der Zustandsfarbe statt weiss #define DASH_SPARK_POINTS 60 // eine Minute Verlauf, ein Punkt je Sekunde static lv_obj_t* g_sparkW = nullptr; // Verlaufskurven der Darstellung TD_VERLAUF static lv_obj_t* g_sparkD = nullptr; @@ -772,7 +778,19 @@ static void err_icon_cb(lv_event_t*) { show_page(PG_DASH); } // Tipp auf Fehl // Bewusst ueber das 'opa'-Style (faellt via opa_recursive auf die Kinder durch) und NICHT // ueber 'opa_layered' - Letzteres wuerde einen Vollbild-Zwischenpuffer allozieren // und koennte den LVGL-Speicherpool sprengen. So bleibt das Fade speicher-neutral. +// Dauer der weichen Uebergaenge (Standby-Uhr, Aufweckdialog, Bezugsuebersicht). +// +// Auf dem Waveshare-Panel: 0, also ohne Animation. Eine Deckkraft-Animation ist bei einem +// Bildspeicher in RGB888 das Teuerste, was die Oberflaeche tun kann - fuer jedes Einzelbild +// muss die gesamte Flaeche unter der Ebene neu gezeichnet und mit ihr gemischt werden. Auf +// 1280x720 dauert eine solche Blende deutlich laenger als die 450 ms, die sie dauern soll; +// spuerbar war das als Verzoegerung, bis die Standby-Uhr erschien und bis nach dem +// Fingertipp der Aufweckdialog kam. Ohne Animation erscheinen beide sofort. +#if JC_PANEL_TYPE == WS_PANEL_7H +static const uint32_t UI_FADE_MS = 0; +#else static const uint32_t UI_FADE_MS = 450; // ruhige, unaufdringliche Dauer +#endif static void ui_fade_exec_cb(void* obj, int32_t v) { lv_obj_set_style_opa((lv_obj_t*)obj, (lv_opa_t)v, 0); @@ -787,6 +805,12 @@ static void ui_fade_hide_done_cb(lv_anim_t* a) { // Blendet 'obj' weich ein (sichtbar schalten, Opazitaet 0 -> voll). static void ui_fade_in(lv_obj_t* obj, uint32_t ms) { if (!obj) return; + if (ms == 0) { // ohne Animation: sofort sichtbar + lv_anim_delete(obj, ui_fade_exec_cb); + lv_obj_set_style_opa(obj, LV_OPA_COVER, 0); + lv_obj_remove_flag(obj, LV_OBJ_FLAG_HIDDEN); + return; + } lv_anim_delete(obj, ui_fade_exec_cb); // evtl. laufende Ausblendung abbrechen lv_obj_set_style_opa(obj, LV_OPA_TRANSP, 0); lv_obj_remove_flag(obj, LV_OBJ_FLAG_HIDDEN); @@ -802,6 +826,11 @@ static void ui_fade_in(lv_obj_t* obj, uint32_t ms) { static void ui_fade_out_hide(lv_obj_t* obj, uint32_t ms) { if (!obj || lv_obj_has_flag(obj, LV_OBJ_FLAG_HIDDEN)) return; lv_anim_delete(obj, ui_fade_exec_cb); + if (ms == 0) { // ohne Animation: sofort weg + lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); + lv_obj_set_style_opa(obj, LV_OPA_COVER, 0); + return; + } lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, obj); lv_anim_set_exec_cb(&a, ui_fade_exec_cb); @@ -922,6 +951,18 @@ static void temp_progress_set(lv_obj_t* bar, lv_obj_t* arc, lv_obj_t* bulb, int } if (bulb) lv_obj_set_style_bg_color(bulb, col, 0); } + +// Farbe der grossen Temperaturzahl. +// +// Die Zustandsfarbe steckt ohnehin schon im Balken darunter. Ob die Zahl selbst mitgefaerbt +// wird, ist deshalb Geschmackssache: Eingefaerbt ist der Zustand auch aus dem Augenwinkel +// erkennbar, weiss wirkt ruhiger und laesst die Zahl als Zahl stehen. +// +// Warnungen bleiben immer rot - das ist keine Gestaltung, sondern eine Meldung. +static lv_color_t temp_value_color(lv_color_t zustand) { + return g_tempColored ? zustand : COL_TEXT; +} + // ------------------------------------------------------------------------------------ // Temperaturbereich des Dashboards - vier Darstellungen // @@ -2975,6 +3016,13 @@ static void design_btn_cb(lv_event_t* e) { ui_update(g_state); // neu aufgebaute Anzeige sofort mit den aktuellen Werten fuellen } // 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. +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(); } +} + static void brew_live_sw_cb(lv_event_t* e) { g_brewLiveEnabled = sw_get((lv_obj_t*)lv_event_get_target(e)); { Preferences prefs; prefs.begin("ui", false); prefs.putBool("brewlive", g_brewLiveEnabled); prefs.end(); } @@ -3012,6 +3060,10 @@ 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* 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); + swBrewLive = add_switch(dcard, "Live-Bezugsschirm (Vollbild während des Bezugs)"); sw_set(swBrewLive, g_brewLiveEnabled); lv_obj_add_event_cb(swBrewLive, brew_live_sw_cb, LV_EVENT_VALUE_CHANGED, nullptr); @@ -3354,6 +3406,7 @@ void ui_init(ProtocolClient* client) { g_tempDesign = prefs.getUChar("tempdsgn", TD_BAND); if (g_tempDesign >= TD_DESIGN_COUNT) g_tempDesign = TD_BAND; g_brewLiveEnabled = prefs.getBool("brewlive", true); + g_tempColored = prefs.getBool("tempcol", false); g_chartWin = prefs.getUChar("chartwin", 0); if (g_chartWin > 3) g_chartWin = 0; g_chartDuty = prefs.getBool("chartduty", false); @@ -4128,14 +4181,14 @@ void ui_update(const MachineState& st) { 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, lv_color_hex(0x1976d2), 0); + lv_obj_set_style_text_color(lblTempW, temp_value_color(lv_color_hex(0x1976d2)), 0); label_set_if_changed(lblSetW, "Cold Extraction - Heizen aus"); lv_obj_set_style_text_color(lblSetW, lv_color_hex(0x1976d2), 0); 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, colW, 0); + 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); // Fortschritt = Ist/Soll in %, gedeckelt auf 100 (Ist >= Soll -> voll) @@ -4152,7 +4205,7 @@ void ui_update(const MachineState& st) { } else { lv_label_set_text(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, colD, 0); + 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); int pctD = (st.setD > 0.0f) ? (int)(st.tempD / st.setD * 100.0f + 0.5f) : 0;