Compare commits

..
Author SHA1 Message Date
thomas 7296a0d2f6 Merge pull request 'feat(P4): Verlaufskurven mit festem Ausgangspunkt und pulsierendem Punkt (1.11.0)' (#87) from feat/verlaufskurven-anker-und-pulspunkt into main 2026-09-04 11:39:50 +02:00
raw-designsandClaude Opus 5 c5ea697f24 feat(P4): Verlaufskurven mit festem Ausgangspunkt und pulsierendem Punkt (1.11.0)
Der aelteste Wert einer Kurve liegt jetzt links genau auf halber Hoehe,
die Kurve waechst von dort nach oben oder unten. Der Verlauf sieht damit
bei jeder Kesseltemperatur gleich aus.

Beide Kurven behalten denselben Massstab. Die absolute Hoehe laesst sich
dadurch nicht mehr zwischen Wasser und Dampf vergleichen, der Ausschlag
aber schon.

Am juengsten Messwert sitzt ein kleiner weisser Punkt mit weichem Schein,
der langsam pulsiert. Beide Linien sind weiss.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wx7wu7uXXgRzp1zHUhtUa6
2026-09-04 11:39:29 +02:00
thomas 5c64892c01 Merge pull request 'fix(P4): Delle nach dem Standby per Median statt Sperrfrist (1.10.4)' (#86) from fix/temperaturdelle-median into main 2026-09-04 10:22:05 +02:00
raw-designsandClaude Opus 5 1febc0b092 fix(P4): Delle nach dem Standby per Median statt Sperrfrist (1.10.4)
Die Massnahme aus 1.10.3 verlaengerte die Delle, statt sie zu entfernen.
Sie hielt beim Umschalten des Standby-Merkers den zuletzt gemeldeten Wert
fest - zu diesem Zeitpunkt lag die gestoerte Probe aber bereits an.
Festgehalten wurde also ausgerechnet die Delle, und das sekundenlang.

Die Verlaufskurven tragen jetzt den mittleren Wert der letzten fuenf
Proben ein (Median). Ein bis zwei verirrte Proben verschwinden damit
vollstaendig, unabhaengig vom Zeitpunkt. Echte Aenderungen kommen
unverfaelscht durch, nur zwei Sekunden spaeter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gwqJf2DcqHFQpoY3XkDHX
2026-09-04 10:21:44 +02:00
thomas a84f902f75 Merge pull request 'fix(P4): Temperaturdelle in den Verlaufskurven nach dem Standby (1.10.3)' (#85) from fix/temperaturdelle-nach-standby into main 2026-09-04 09:16:50 +02:00
raw-designsandClaude Opus 5 bcbeea2a17 fix(P4): Temperaturdelle in den Verlaufskurven nach dem Standby (1.10.3)
Direkt nach dem Aufwachen aus dem Standby zog die Wasserkurve eine kurze
Delle nach unten. Ursache ist die Messung, nicht der Kessel: In genau
diesem Moment schalten die Heizungen, und der Wassersensor haengt als NTC
am ADC. Ein Kessel kann binnen einer Sekunde nicht um Grade einbrechen.

Die Verlaufskurven halten deshalb rund um jeden Standby-Wechsel sechs
Sekunden lang ihren letzten Wert, statt die gestoerte Probe einzutragen.
Das gilt fuer die kleinen Kurven im Dashboard und fuer die grosse
Verlaufsseite. Die angezeigten Temperaturzahlen bleiben unveraendert.

Ausserdem: DISPLAY_FW_VERSION stand seit dem Ruecknehmen von 1.6.11 auf
1.6.10 fest und wurde bei keinem der folgenden Staende mitgezogen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fe8KxS47iPmuByJPs5RvEw
2026-09-04 09:16:18 +02:00
thomas 1fe96b70aa Merge pull request 'fix(P4): Dashboard-Sparklines wurden nie fortgeschrieben (1.10.2)' (#84) from fix/verlaufskurven-werden-nie-fortgeschrieben into main 2026-09-04 01:42:57 +02:00
raw-designsandClaude Opus 5 43517a2c48 fix(P4): Dashboard-Sparklines wurden nie fortgeschrieben (1.10.2)
Die Linien blieben identisch und unbewegt - kein Skalierungsproblem, wie
1.10.0 und 1.10.1 angenommen hatten.

lv_chart_set_next_value() für g_sparkW/g_sparkD stand am Ende von
chart_duty_btn_cb(), dem Callback des Heizleistungs-Umschalters auf der
Verlauf-SEITE. Die Sparklines wuchsen also nur, wenn jemand genau diesen
Knopf drückte. Ansonsten zeigten sie unverändert, was lv_chart_set_all_value()
beim Aufbau der Darstellung eingetragen hatte.

Der Block sitzt jetzt in chart_sample_cb() (1-s-Timer), und zwar vor dessen
"if (!g_chart || !g_hist) return" - die Dashboard-Kurven sollen nicht davon
abhängen, ob die Verlauf-Seite samt großem Diagramm aufgebaut ist.

Die gemeinsame Skala aus 1.10.1 bleibt richtig, konnte bisher aber nichts
ausrichten, weil nie neue Werte ankamen.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012gBXGt5M22ns5YfNJRaiMu
2026-09-04 01:42:35 +02:00
thomas 6a867e54fd Merge pull request 'fix(P4): Verlaufskurven mit gemeinsamer Skala - Höhen wieder vergleichbar (1.10.1)' (#83) from fix/verlauf-gemeinsame-skala into main 2026-09-03 17:23:29 +02:00
raw-designsandClaude Opus 5 edfa2d4711 fix(P4): Verlaufskurven mit gemeinsamer Skala - Höhen wieder vergleichbar (1.10.1)
Nachbesserung zu 1.10.0. Dort bekam jede Kurve ihren eigenen Ausschnitt aus
ihren eigenen min/max. Bei zwei flachen Kurven (Wasser 70 °C, Dampf 0 °C)
greift beidesmal die Mindestspanne, jede Linie sitzt mittig in ihrem Fenster -
und beide liegen auf identischer Höhe. Die Skalierung war zu clever: Bewegung
wurde sichtbar, aber die Höhe verlor jede Bedeutung.

- spark_range_fit(ch, ser) ersetzt durch spark_ranges_fit(): scannt beide
  Serien, bildet einen gemeinsamen Bereich und setzt ihn auf beide Charts.
- Der gemerkte Bereich liegt jetzt in zwei Datei-Statics statt in user_data
  der Charts; das nimmt auch das nicht freigegebene lv_malloc bei jedem
  Neuaufbau der Temperaturzeile weg.
- build_temp_row_content() setzt den Merker beim Aufbau zurück und ruft
  spark_ranges_fit() erst, wenn beide Kurven stehen.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018ZJ2iUTbm7Zz5DTPkwgJyC
2026-09-03 17:22:28 +02:00
thomas fc0a756127 Merge pull request 'fix(P4): Verlaufskurven skalieren nach Daten, Diagnose ausgebaut (1.10.0)' (#82) from fix/verlaufskurven-und-aufraeumen into main 2026-09-03 17:01:50 +02:00
raw-designsandClaude Opus 5 cc9ae945b1 fix(P4): Verlaufskurven skalieren nach Daten, Diagnose ausgebaut (1.10.0)
Die Sparklines im Dashboard lagen flach auf gleicher Höhe und bewegten sich
nicht, obwohl ein Kessel bei 80 °C stand und der andere bei 0.

Ursache: lv_chart_set_range() war an den Sollwert gebunden (soll-60 bis
soll+30 in Zehntelgrad). Liegt die Temperatur unter diesem Fenster - beim
Aufheizen oder bei abgeschaltetem Kessel -, klemmt LVGL jeden Punkt auf den
unteren Rand. Beide Kurven landeten dadurch auf derselben Linie.

- Neues spark_range_fit(): Ausschnitt aus min/max der vorhandenen Punkte
  (lv_chart_get_y_array), Mindestspanne DASH_SPARK_MIN_SPAN (40 = 4,0 °C),
  sonst ein Achtel Luft nach oben und unten.
- Der zuletzt gesetzte Bereich wird in user_data gemerkt, weil LVGL keinen
  Getter dafür hat; ohne den Vergleich würde set_range das Diagramm bei jeder
  Zustandsmeldung invalidieren.
- Die Charts füllen jetzt den Platz unterhalb der Zahlen (flex_grow 1,
  min_height 90) statt als 64-px-Streifen mittig zu hängen.

Aufräumen nach der abgeschlossenen Fehlersuche:
- Herzschlag, [Zustand]- und [Touch]-Messzeilen entfernt.
- refr_monitor_install() hinter WS7_PERF_MONITOR (aus).
- scroll_ohne_nachlauf() gibt LV_OBJ_FLAG_SCROLL_MOMENTUM wieder frei.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019G95njDFkedFqXiz5sEaJ2
2026-09-03 17:01:19 +02:00
thomas 696707a9a4 Merge pull request 'fix(P4): Hintergrundbeleuchtung kommt sofort - Bridge braucht zwei Latches (1.9.12)' (#81) from fix/helligkeit-doppelte-uebernahme into main 2026-09-03 15:46:17 +02:00
raw-designsandClaude Opus 5 6bf046801c fix(P4): Hintergrundbeleuchtung kommt sofort - Bridge braucht zwei Latches (1.9.12)
Der Nutzer hat es im Gegenlicht gesehen: Das Bild steht nach 446 ms fertig
da, nur die Beleuchtung kommt Sekunden später. Die gesamte Suche im
Zeichenablauf lief damit am falschen Ort - die Messungen dort waren alle
unauffällig, weil dort auch nichts war.

Der Referenz-Sketch (dsi-test.ino, enableBacklight) setzt 0xAB/0xAA zweimal
mit delay(100) dazwischen, ausdrücklich "sicherheitshalber Helligkeit noch
einmal übernehmen". jc_backlight_set() schrieb die Sequenz nur einmal.

- 0xAB/0xAA werden jetzt wiederholt, Pause über WS7_BACKLIGHT_LATCH_MS (20).
- 0xAD (Freigabe) nur noch beim ersten Aufruf statt bei jeder Änderung; der
  Referenzcode setzt sie ebenfalls nur einmal, und sie erneut zu schreiben
  stößt die Helligkeitsstufe der Bridge neu an.
- jc_backlight_set() meldet seine Dauer selbst; die doppelte Messung im .ino
  entfällt.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 15:45:50 +02:00
thomas cd1617fdce Merge pull request 'fix(P4): Endlose Neustartschleife nach Kaltstart (1.9.11)' (#80) from fix/kaltstart-neustartschleife into main 2026-09-03 15:09:03 +02:00
raw-designsandClaude Opus 5 5df6c20171 fix(P4): Endlose Neustartschleife nach Kaltstart (1.9.11)
Log zeigt zweimal hintereinander "rst:0x1 (POWERON)" und
"[Panel] Startgrund: 1", danach nichts mehr - Beleuchtung an, kein Bild.

Ursache: Der gewollte einmalige Neustart nach Kaltstart (WS7_COLD_BOOT_RESTART)
prüfte nur esp_reset_reason() == ESP_RST_POWERON. Der Kommentar nahm an, der
zweite Durchlauf melde einen Software-Reset. Tatsächlich meldet der Chip auch
nach esp_restart() wieder POWERON, die Bedingung greift erneut - Endlosschleife.
Der bootguard konnte nicht eingreifen, weil derselbe Zweig "early" jedes Mal
auf 0 zurücksetzt.

- Zusätzliches NVS-Flag "kaltneu" in bootguard: wird vor esp_restart() gesetzt
  und beim zweiten Durchlauf erkannt und gelöscht. Unabhängig vom gemeldeten
  Startgrund, damit die Schleife strukturell ausgeschlossen ist.
- Die Meldung lief über DBG_SERIAL (USB-CDC) und war im Monitor an der UART
  nicht zu sehen - jetzt esp_rom_printf wie die übrigen Panel-Meldungen.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NeFMr439WcLMdebE3kU7fS
2026-09-03 15:08:40 +02:00
thomas 7d7893cf08 Merge pull request 'diag(P4): Touch-Rohwerte vermessen, einheitliche Zeitbasis (1.9.10)' (#79) from diag/touch-rohwerte-und-zeitbasis into main 2026-09-03 13:52:10 +02:00
raw-designsandClaude Opus 5 db707ffd8c diag(P4): Touch-Rohwerte vermessen, einheitliche Zeitbasis (1.9.10)
Auswertung des letzten Logs (lv_tick lief 2728 ms hinter millis):
Tipp erkannt 49428, Rückfrage aufgebaut 49430, Bildaufbau fertig 49746.
Also 318 ms vom erkannten Tipp bis zum fertigen Bild - die gemessene Kette
ist schnell. Der Knopfdruck im Dialog liegt bei 55638 (Bereich 645..856,
374..426), die Antwort des S3 bei 59303, also 937 ms Rundlauf.

Die Verzögerung liegt damit VOR der Erkennung. Deshalb:
- ws7_touch_get_xy() meldet den ersten verworfenen Rohwert nach Ruhe mit
  Koordinaten und zählt, wie viele bis zur akzeptierten Berührung anfallen.
- Alle Messzeilen auf millis() statt lv_tick_get(); die beiden Uhren
  auseinanderzurechnen hat das Lesen unnötig erschwert.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NeFMr439WcLMdebE3kU7fS
2026-09-03 13:51:48 +02:00
thomas 9eb386095d Merge pull request 'fix(P4): Kachelhöhe beim Bezug halten, Messzeilen mit Zeitmarke (1.9.9)' (#78) from fix/kachelhoehe-und-zeitmarken into main 2026-09-03 13:38:36 +02:00
raw-designsandClaude Opus 5 7fec5d9fb5 fix(P4): Kachelhöhe beim Bezug halten, Messzeilen mit Zeitmarke (1.9.9)
- dash_brew_mode() verteilt die flex_grow-Werte nicht mehr um. Die untere
  Zeile bekam während des Bezugs 3 statt 2 und die Temperaturzeile 1 statt 3;
  die kleinen Kacheln wurden dadurch enorm hoch und das Layout sprang.
- Die Messzeilen aus dem .ino liefen über Serial und damit über USB-CDC,
  während der Monitor an der UART hängt - sie waren nie zu sehen. Jetzt
  durchgängig esp_rom_printf wie die Panel-Meldungen.
- Alle Messzeilen tragen eine Zeitmarke in ms; ohne die sind die Lücken
  nicht zu erkennen.
- onState() misst Ankunft der Zustandsmeldung, Wartezeit auf hal_lock() und
  Dauer von ui_update(). standby_screen_cb() klammert wake_confirm_show()
  ein. Das deckt beide Richtungen der gemeldeten Fünf-Sekunden-Verzögerung ab.

Das Einblenden der Standby-Uhr scheidet als Ursache aus: laut Messung 2 ms.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NeFMr439WcLMdebE3kU7fS
2026-09-03 13:38:14 +02:00
thomas 32280a7ea3 Merge pull request 'fix(P4): Glyphenpuffer ins PSRAM - behebt Stillstand bei großer Standby-Uhr (1.9.8)' (#77) from fix/glyphenpuffer-ins-psram into main 2026-09-03 13:17:30 +02:00
raw-designsandClaude Opus 5 5988668026 fix(P4): Glyphenpuffer ins PSRAM - behebt Stillstand bei großer Standby-Uhr (1.9.8)
Ursache gefunden. lv_draw_label.c legt pro Glyphe einen A8-Draw-Buf an:
box_w * LV_ROUND_UP(box_h, 32) Byte. Größte Ziffer des 360er-Fonts ist
190x247 -> 190*256 = 48 KB. Mit LV_DRAW_SW_DRAW_UNIT_CNT 2 sind zwei davon
gleichzeitig offen, also ~97 KB. Der LVGL-Pool (LV_MEM_SIZE 256 KB) hatte
laut Herzschlag nur 98068 Byte am Stück frei - es reichte knapp nicht.

LV_USE_ASSERT_MALLOC ist 1 und LV_ASSERT_HANDLER war "while(1);". Bei
fehlgeschlagener Allokation hält der LVGL-Task also stumm an: kein Panic,
kein Backtrace, Log bricht einfach ab. Genau das beobachtete Bild.

- font_buf_malloc/-free über lv_draw_buf_get_font_handlers(): Puffer ab
  16 KB kommen per heap_caps_malloc aus dem PSRAM, kleinere weiter aus dem
  LVGL-Pool (schneller; sonst würde jeder Text langsamer). Freigabe
  unterscheidet über esp_ptr_external_ram().
- LV_ASSERT_HANDLER gibt jetzt eine Meldung aus, bevor er anhält.

Der interne RAM bleibt unangetastet - LV_MEM_SIZE zu erhöhen war keine
Option, der statische Speicher liegt bereits bei ~98 %.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NeFMr439WcLMdebE3kU7fS
2026-09-03 13:17:06 +02:00
thomas 4f2700d59a Merge pull request 'diag(P4): Messpunkte für den Stillstand beim Standby-Wechsel (1.9.7)' (#76) from diag/standby-stillstand-vermessen into main 2026-09-03 13:02:57 +02:00
raw-designsandClaude Opus 5 0ec3d89973 diag(P4): Messpunkte für den Stillstand beim Standby-Wechsel (1.9.7)
Beim Wechsel in den Standby bleibt das Display stehen: Bild bleibt auf der
alten Seite, keine Bedienung, auch der S3 weckt nicht mehr auf. Der Log
bricht nach dem letzten Bildaufbau ab, ohne Panic.

Statt zu raten, Messpunkte:
- Herzschlag alle 2 s aus dem Arduino-loop (freier Heap) und aus einem
  lv_timer im LVGL-Task (lv_mem_monitor). Bleibt nur einer aus, ist klar,
  welcher Task steht.
- ui_fade_in() der Standby-Uhr wird eingeklammert: "wird eingeblendet" /
  "eingeblendet, N ms".
- hal_backlight() wird gemessen; über 50 ms wird die Dauer gemeldet.
  Der Bridge-Schreibzugriff läuft über denselben I2C-Bus wie der Touch.

Außerdem entfernt: die LV_EVENT_INVALIDATE_AREA-Callbacks aus 1.9.5. Das
Event geht per lv_display_send_event an das Display, nicht an Objekte - die
Callbacks konnten nie feuern, ihr Ausbleiben war kein Beweis.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NeFMr439WcLMdebE3kU7fS
2026-09-03 13:02:35 +02:00
thomas 06d9710b16 Merge pull request 'feat(P4): Eigener Menüpunkt „Darstellung“, größere Uhr im Standby (1.9.6)' (#75) from feat/darstellung-eigene-seite-groessere-uhr into main 2026-09-03 09:24:31 +02:00
raw-designsandClaude Opus 5 b3b96362c3 feat(P4): Eigener Menüpunkt "Darstellung", größere Uhr im Standby (1.9.6)
- Der Darstellungsblock wandert aus build_info() in ein eigenes build_display()
  mit neuer Seite PG_DISPLAY. Die Info-Seite zeigt nur noch Firmware-Stände und
  Verbindungsdaten.
- clock_font() liefert für WS_PANEL_7H jetzt 180/270/360 statt 120/180/240. Für
  JC_PANEL_43 bleiben die alten Stufen - 360 px passen nicht auf 480x480.
- Neue Fonts lv_font_clock_270/_360 (Maven Pro Regular, bpp 4, Range
  32,45,0x30-0x3A). bpp 3 scheidet aus: lv_font_conv erlaubt das nur mit
  Kompression, und die kostet beim Zeichnen genau das, was gerade eingespart wird.
- Alle fünf Uhr-Fonts sind deklariert; der Linker verwirft die je nach Panel
  ungenutzten. Netto wächst die WS-Firmware um 196 KB.

Beide Panel-Varianten mit arduino-cli gegengebaut (PartitionScheme=custom,
passend zur partitions.csv mit zwei 6,5-MB-Slots).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NeFMr439WcLMdebE3kU7fS
2026-09-03 09:23:50 +02:00
thomas 14f1a4789d Merge pull request 'perf(P4): Auch feste Höhen - LVGL markiert sonst das Layout als dirty (1.9.5)' (#74) from perf/feste-hoehen-und-nachweis into main 2026-09-03 07:25:04 +02:00
raw-designsandClaude Opus 5 326af4288a perf(P4): Auch feste Höhen - LVGL markiert sonst das Layout als dirty (1.9.5)
Die festen Breiten aus 1.9.4 haben nicht gereicht. lv_label_set_text ruft
lv_obj_refresh_self_size(); ist eines der beiden Maße LV_SIZE_CONTENT, gilt
das Parent-Layout als dirty und der Container wird komplett invalidiert.

- tempField(): big und setp bekommen zusätzlich eine feste Höhe aus
  lv_font_get_line_height().
- infoCell(): val ebenso, mit Platz für zwei Zeilen.
- g_clock: feste Breite/Höhe, rechtsbündig. Erklärt den Bereich
  "x 6..57, y 2..41" (Menü-Knopf), der bei jedem Minutenwechsel durch das
  Header-Relayout mit invalidiert wurde.

Zusätzlich eine gezielte Diagnose: LV_EVENT_INVALIDATE_AREA auf g_content
und der Dashboard-Seite meldet, wenn ein ganzer Container invalidiert wird -
damit ist "einzelnes Label" von "kompletter Bereich" zu unterscheiden.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 03:10:40 +02:00
thomas 2e8651bc00 Merge pull request 'perf(P4): Feste Breiten für Anzeigewerte - kein Neulayout mehr (1.9.4)' (#73) from perf/feste-breiten-kein-neulayout into main 2026-09-03 02:56:24 +02:00
raw-designsandClaude Opus 5 b13e5fdaf1 perf(P4): Feste Breiten für Anzeigewerte - kein Neulayout mehr (1.9.4)
Die Koordinaten haben den Verursacher benannt: Der invalidierte Bereich war
"x 0..1279, y 44..719" - der komplette Content-Container, bei jeder
Zustandsmeldung.

Grund: Die Wert-Labels hatten LV_SIZE_CONTENT. Ändert sich ihre Breite mit
dem Inhalt (92,4 °C -> 100,1 °C), löst LVGL ein Flex-Relayout der ganzen
Seite aus und invalidiert sie komplett. Change-checked Text allein reicht
also nicht - der Text darf beim Ändern auch die Breite nicht ändern.

tempField() und infoCell() setzen die Wert-Labels jetzt auf LV_PCT(100) mit
zentriertem Text. Optisch identisch, da die Werte ohnehin mittig standen.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 02:56:05 +02:00
thomas 671a6696ce Merge pull request 'fix(P4): Menüvorhang wieder durchscheinend, weitere Invalidierung entfernt (1.9.3)' (#72) from fix/menuevorhang-und-weitere-invalidierung into main 2026-09-03 02:36:48 +02:00
raw-designsandClaude Opus 5 288f61447d fix(P4): Menüvorhang wieder durchscheinend, weitere Invalidierung entfernt (1.9.3)
- Regression aus 1.8.7: Der deckende Drawer-Scrim verdeckte den
  Seiteninhalt, der dahinter sichtbar bleiben soll. Zurück auf LV_OPA_50.
- ready_band_update() setzte Text, Textfarbe und Hintergrundfarbe des
  Zustandsbands bei jeder Zustandsmeldung neu. Das Band spannt sich über die
  volle Breite - allein dadurch wurde ein Streifen über den ganzen Bildschirm
  ungültig. Jetzt über die change-checked Helfer.
- temp_progress_set() setzte Balkenwert und -farbe unbedingt; jetzt nur bei
  echter Änderung.
- Das WLAN-Symbol ebenso.
- Die Messung gibt zusätzlich die Koordinaten der invalidierten Bereiche aus.
  Die Fläche allein sagt nicht, welcher Teil der UI den Redraw auslöst.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 02:36:31 +02:00
thomas a91c792491 Merge pull request 'perf(P4): Nur bei echter Änderung neu zeichnen (1.9.2)' (#71) from perf/nur-bei-aenderung-neu-zeichnen into main 2026-09-03 02:17:20 +02:00
raw-designsandClaude Opus 5 e32c654b8d perf(P4): Nur bei echter Änderung neu zeichnen (1.9.2)
Die erweiterte Messung war eindeutig: "1 Bereich, 100 % der Fläche" - LVGL
zeichnete bei jeder Zustandsmeldung den kompletten Bildschirm neu, also
einmal pro Sekunde 240-300 ms lang. Kein Rendering-Tempoproblem, sondern
massiv zu viel Invalidierung.

lv_label_set_text invalidiert den Label-Bereich unbedingt, auch bei
identischem Text; lv_obj_set_style_text_color ebenso. Auf dem Dashboard
wurden pro Sekunde Werte quer über den Bildschirm gesetzt (Uhr oben,
Temperaturen Mitte, Bezugswerte unten) - LVGL joint die Bereiche, und die
Bounding-Box ist die ganze Fläche.

- Neue Helfer label_fmt_if_changed() und label_color_if_changed() neben dem
  vorhandenen label_set_if_changed().
- Alle 13 zyklischen Textzuweisungen und alle 10 Farbzuweisungen in
  ui_update darauf umgestellt.

Da sich Temperaturen selten um ein Zehntelgrad ändern und Sollwerte
praktisch nie, entfallen die meisten Neuzeichnungen ganz.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 02:17:03 +02:00
thomas 484812cb4c Merge pull request 'diag(P4): Gezeichnete Fläche messen, direktes Zeichnen zurücknehmen (1.9.1)' (#70) from diag/gezeichnete-flaeche-messen into main 2026-09-03 01:42:21 +02:00
raw-designsandClaude Opus 5 ff23e0e614 diag(P4): Gezeichnete Fläche messen, direktes Zeichnen zurücknehmen (1.9.1)
WS7_DIRECT_FB hat die Bildaufbauzeit nicht verkürzt (weiterhin 240-300 ms)
und Bildfehler erzeugt - in denselben Speicher zu zeichnen, aus dem gerade
angezeigt wird, geht ohne zweiten Framebuffer nicht sauber. Zurück auf 0,
Schalter mit Begründung erhalten.

Damit ist belegt: Der Flaschenhals liegt nicht im Kopieren, sondern im
Rendern selbst. Offen ist, ob LVGL kleine Bereiche langsam zeichnet oder
jedes Mal die volle Fläche - zwei verschiedene Ursachen.

refr_start_cb summiert deshalb jetzt die nicht zusammengefassten
inv_areas und meldet Anzahl und Flächenanteil zusammen mit der Dauer.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 01:42:05 +02:00
thomas 09b5231357 Merge pull request 'perf(P4): LVGL zeichnet direkt in den Bildspeicher (1.9.0)' (#69) from perf/direkt-in-bildspeicher-zeichnen into main 2026-09-03 01:27:32 +02:00
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
raw-designsandClaude Opus 5 01d960258a feat(P4): Uhr läuft lokal weiter, wenn die S3 keine Zeit liefert (1.8.6)
Die Uhrzeit kommt von der Hauptplatine und ist leer, solange dort keine
Zeitquelle synchronisiert ist. Bei einem erneuten Abgleich ist sie kurz weg,
und die Uhr verschwand für ein paar Sekunden - im Standby unruhig.

Der P4 merkt sich jetzt die zuletzt empfangene Zeit (Minuten seit
Mitternacht plus lv_tick zum Empfangszeitpunkt) und rechnet zwischen den
Meldungen selbst weiter. Sobald die S3 wieder eine Zeit schickt, gilt deren
Wert - der P4 stellt nichts richtig und ersetzt keine Zeitquelle, er
überbrückt nur die Lücke. Ohne je empfangene Zeit bleibt die Anzeige leer
wie bisher.

Gilt für die Kopfleisten-Uhr und die große Standby-Uhr; beide setzen den
Text jetzt über label_set_if_changed, sparen also unnötige Neuzeichnungen.

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:33:50 +02:00
thomas 3c333f0280 Merge pull request 'fix(P4): Standby-Verzögerung, Dialog-Timeout, Kurvenhintergrund, Bindestrich (1.8.5)' (#65) from fix/standby-verzoegerung-und-feinschliff into main 2026-09-03 00:26:30 +02:00
raw-designsandClaude Opus 5 b6c6214b41 fix(P4): Standby-Verzögerung, Dialog-Timeout, Kurvenhintergrund, Bindestrich (1.8.5)
- Die ~2 s Verzögerung rund um den Standby lag nicht an der Helligkeit:
  lv_obj_move_foreground(g_standbyScreen) lief bei JEDER Zustandsmeldung.
  Das ordnet die Ebenen neu und lässt LVGL den ganzen Bildschirm neu
  zeichnen - einmal pro Sekunde, 1280x720 in 24 Bit. Nach vorn geholt wird
  die Uhr jetzt nur beim Einblenden.
- Der Aufweckdialog schließt sich nach 30 s ohne Auswahl selbst und wird wie
  Abbrechen gewertet (lv_timer, repeat_count 1). Sonst bliebe das Display
  hell stehen, weil der Dialog auf normale Helligkeit schaltet.
- Die Verlaufskurve hat keinen eigenen Hintergrund mehr. Die abgesetzte
  Fläche war nur nötig, solange die Kurve vor dem ersten Messwert leer war -
  seit sie beim aktuellen Wert startet, ist immer eine Linie da.
- Statistik: Bei fehlendem Gewicht stand ein En-Dash, den der Zeichensatz
  nicht enthält - erschien als leeres Rechteck. Jetzt ASCII-Bindestrich.

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:26:12 +02:00
thomas 63290afa07 Merge pull request 'fix(P4): Übergänge ohne Animation, kein blaues Aufblitzen, Temperaturfarbe wählbar (1.8.4)' (#64) from fix/uebergaenge-und-temperaturfarbe into main 2026-09-03 00:04:43 +02:00
raw-designsandClaude Opus 5 cf57e11ccb fix(P4): Übergänge ohne Animation, kein blaues Aufblitzen, Temperaturfarbe wählbar (1.8.4)
- Standby-Uhr und Aufweckdialog kamen spürbar verzögert. Ursache waren die
  Fade-Animationen: Eine Deckkraft-Animation ist bei einem Bildspeicher in
  RGB888 das Teuerste überhaupt, weil pro Einzelbild die ganze Fläche unter
  der Ebene neu gezeichnet und gemischt werden muss. UI_FADE_MS ist für
  WS_PANEL_7H auf 0; ui_fade_in/ui_fade_out_hide zeigen bzw. verstecken dann
  direkt. Die JC-Panels behalten die Animation.
- Beim Wechsel der Schriftgröße blitzte Blau auf. Das ist das Panel selbst -
  ohne Videosignal zeigt es Blau, und der nötige Neustart reißt das Signal
  ab. hal_backlight(0) vor esp_restart().
- Neue Einstellung "Temperaturzahl in der Zustandsfarbe" (Info-Seite,
  Abschnitt Darstellung, NVS ui/tempcol, Vorgabe aus). Aus bleibt die Zahl
  weiß; die Zustandsfarbe steckt dann allein im Balken. Warnungen bleiben
  immer rot.

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:03:58 +02:00
thomas 6d345d2145 Merge pull request 'fix(P4): Fehlendes °C, unsichtbarer Verlauf, fette Zahlen (1.8.3)' (#63) from fix/dashboard-schrift-und-verlauf into main 2026-09-02 20:12:52 +02:00
raw-designsandClaude Opus 5 a410da6e72 fix(P4): Fehlendes °C, unsichtbarer Verlauf, fette Zahlen (1.8.3)
Drei Punkte am neuen Dashboard:

- Hinter der Temperatur stand ein leeres Rechteck statt des C. Die großen
  Schriften waren auf Ziffern, Komma, Punkt, Minus und Gradzeichen
  beschränkt; C fehlte. Jetzt enthalten, ebenso g und s für die Anzeige
  während eines Bezugs.
- Bei "Verlauf" war keine Kurve zu sehen: Ein frisches lv_chart hat lauter
  LV_CHART_POINT_NONE und zeichnet nichts, und ohne Hintergrund war der
  Bereich unsichtbar, bis nach einer Minute Messwerte zusammenkamen. Die
  Kurve startet jetzt beim aktuellen Wert (lv_chart_set_all_value), Bereich
  und Fläche sind sofort gesetzt.
- Die großen Zahlen stehen im fetten Schnitt und mit engerem Zeichenabstand,
  wie im Entwurf. Erzeugt aus MavenPro-VariableFont bei wght=700 via
  fontTools varLib.instancer; dieselbe Schriftart, nur kräftiger. Die
  Dateien heißen entsprechend lv_font_maven_pro_bold_96/_140.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 20:12:32 +02:00
thomas f0a214d712 Merge pull request 'feat(P4): Letzte Bezüge als Tabelle statt Textblock (1.8.2)' (#62) from feat/statistik-tabelle into main 2026-09-02 19:52:14 +02:00
raw-designsandClaude Opus 5 21f273aae4 feat(P4): Letzte Bezüge als Tabelle statt Textblock (1.8.2)
Die Liste war ein einziges mehrzeiliges Label: Zeitpunkt, Dauer und Gewicht
durch Leerzeichen getrennt aneinandergereiht. Weil Zahlen unterschiedlich
breit sind, stand nichts untereinander - zwei Bezüge ließen sich nicht
vergleichen, ohne jede Zeile einzeln zu lesen.

Jetzt eine Tabelle mit festen Spalten (Zeitpunkt / Dauer / Gewicht / kalt),
Ziffern gleicher Breite, Kopfzeile und leicht abgesetzten wechselnden
Zeilen statt Trennlinien. Ohne Waage bezogen bleibt die Gewichtsspalte leer
statt eine Null vorzutäuschen.

Die Zeilen werden einmal angelegt und danach nur gefüllt oder ausgeblendet -
kein Neuanlegen bei jeder Aktualisierung.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 19:51:57 +02:00
thomas e42d2b3de2 Merge pull request 'feat(P4): Bezugsanzeige für alle vier Darstellungen (1.8.1)' (#61) from feat/bezugsanzeige into main 2026-09-02 19:41:07 +02:00
raw-designsandClaude Opus 5 785f64331d feat(P4): Bezugsanzeige für alle vier Darstellungen (1.8.1)
Sobald ein Bezug oder Dampfbezug läuft, schrumpft der Temperaturbereich
(flex-grow 3 -> 1) und die untere Zeile wächst (2 -> 3); Shot-Timer und
Gewicht wechseln auf 96 px. Während eines Bezugs zählen Zeit und Gewicht,
die Kesseltemperaturen sind dann Nebensache.

Keine zweite Ansicht: Die Seite verschiebt nur das Gewicht zwischen ihren
beiden Bereichen. Nichts doppelt zu pflegen, nichts springt an eine andere
Stelle.

Der Wechsel hält nach dem Bezug noch vier Sekunden an - ohne dieses
Nachhalten würde die Seite bei jeder kurzen Unterbrechung hin- und
herspringen.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 19:40:51 +02:00
thomas 40aabe48bc Merge pull request 'feat(P4): Vier neue Dashboard-Darstellungen (1.8.0)' (#60) from feat/dashboard-vier-darstellungen into main 2026-09-02 19:30:11 +02:00
raw-designsandClaude Opus 5 ca3a9c1264 feat(P4): Vier neue Dashboard-Darstellungen (1.8.0)
Ersetzt die bisherigen fünf (Klassisch, Instrumente, Minimal, Soft-3D,
Thermometer) durch vier, die nicht nur den Temperaturbereich anders zeichnen,
sondern die Fläche unterschiedlich nutzen:

- Gewichtet: Wasser mit flex-grow 2, Dampf mit 1.
- Verlauf: lv_chart-Sparkline je Kessel, gespeist aus der bestehenden
  Sekundenabtastung; Ausschnitt am Sollwert ausgerichtet.
- Flächen: ohne Kartenkanten, zwei Felder mit leicht verschiedenem Grund.
- Band: Zustandsband über volle Breite (bereit / heizt / Bezug / Cold
  Extraction / Standby). Neue Vorgabe.

Zwei neue Schriftgrade (96 und 140 px), erzeugt mit lv_font_conv aus
MavenPro-Regular.ttf, beschränkt auf Ziffern, Komma, Punkt, Minus und
Gradzeichen - die größte Textschrift hatte 48 px und reichte für die großen
Zahlen nicht.

Ein gespeicherter Wert außerhalb des neuen Bereichs fällt auf die Vorgabe
zurück. Die fünf alten Builder sind entfernt.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 19:29:54 +02:00
thomas bcd9ecf0c8 Merge pull request 'refactor(P4): Schriftgröße auf die Info-Seite verschieben (1.7.3)' (#59) from refactor/schriftgroesse-auf-info-seite into main 2026-09-02 18:09:36 +02:00
raw-designsandClaude Opus 5 e5c61d42d4 refactor(P4): Schriftgröße auf die Info-Seite verschieben (1.7.3)
Die Info-Seite hat bereits einen Abschnitt "Darstellung" mit der Wahl der
Temperaturanzeige und dem Live-Bezugsschirm. Die Schriftgröße gehört dort
hinein - sie ist eine Einstellung dieses Displays, keine Wartungsaufgabe.

- Die eigene Karte auf der Wartungsseite entfällt; diese hat damit wieder
  vier Karten in zwei Spalten.
- Die Auswahl selbst ist unverändert: drei Stufen, Neustart danach.
- Sie gilt für alle Panels, nicht nur den 7-Zöller.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LFRMCnijNEA7obGAq5Jz9v
2026-09-02 18:09:21 +02:00
thomas d77b0795ea Merge pull request 'feat(P4): Schriftgröße einstellbar (1.7.2)' (#58) from feat/schriftgroesse-einstellbar into main 2026-09-02 18:02:40 +02:00
raw-designsandClaude Opus 5 7ebffdab8f feat(P4): Schriftgröße einstellbar (1.7.2)
Klein, Mittel oder Groß - Karte "Darstellung" auf der Seite Reinigung &
Wartung.

LVGL-Schriften sind fest einkompilierte Bilddaten und existieren nur in den
Größen, die im Projekt liegen (14/18/28/40/48). Stufenloses Skalieren gibt
es also nicht. Stattdessen drei Rollen - font_small(), font_text(),
font_title() -, die je nach Einstellung eine Stufe höher greifen; die 45
festen Schriftverweise in ui.cpp sind darauf umgestellt.

- Die großen Anzeigen (Temperatur 40/48, Uhr) bleiben fest: Sie sind auf die
  Bildschirmgröße abgestimmt.
- Die Grundschrift wird am Bildschirmobjekt gesetzt, damit alles ohne eigene
  Schrift sie erbt.
- Die Einstellung liegt lokal im P4 (NVS "anzeige"), nicht auf der S3.
- Nach der Auswahl folgt ein Neustart; der Frühstart-Zähler der
  Absturzsicherung wird vorher zurückgesetzt.

Offen: In der Stufe Groß brauchen die Karten mehr Platz - ob alle Seiten
dann noch vollständig auf den Bildschirm passen, zeigt erst das Gerät.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 18:02:23 +02:00
thomas b73fc798c3 Merge pull request 'feat(P4): Cold Extraction und Wartung mehrspaltig (1.7.1)' (#57) from feat/coldex-und-wartung-mehrspaltig into main 2026-09-02 17:52:32 +02:00
raw-designsandClaude Opus 5 5defbe362c feat(P4): Cold Extraction und Wartung mehrspaltig (1.7.1)
Zweiter Teil der Layoutumstellung für das 7-Zoll-Panel.

Cold Extraction, drei Spalten:
- Oben die Karten mit Erklärungstext (Modus, Vorbenetzung, Bezugsende),
  darunter die knappen (Grundeinstellung, Hauptbezug, Pumpenschutz).
- Drei statt zwei Spalten, weil die Erklärungstexte keine volle
  Zeilenbreite brauchen und so keine halbleere Reihe stehen bleibt.
- Der Warnhinweis stand als eigene Zeile am Seitenende, weit entfernt vom
  zugehörigen Schalter - er sitzt jetzt in der Modus-Karte.
- Speichern frei unter allen Karten.

Reinigung & Wartung, zwei Spalten, vier Karten:
- Wartungszähler, Flush-Zeiten, Display-Helligkeit, Reinigung & Entkalkung.
- Bisher lose Zeilen unter bloßen Zwischenüberschriften mit freistehenden
  Knöpfen dazwischen.
- Hier sitzt Speichern IN der Karte: Jede Karte speichert etwas anderes.

Die JC-Panels behalten ihr einspaltiges Layout; beide Varianten mit
arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:52:15 +02:00
thomas 749f50097f Merge pull request 'feat(P4): Brew-Control zweispaltig auf dem 7-Zoll-Panel (1.7.0)' (#56) from feat/brew-control-zweispaltig into main 2026-09-02 17:26:06 +02:00
raw-designsandClaude Opus 5 95373dc619 feat(P4): Brew-Control zweispaltig auf dem 7-Zoll-Panel (1.7.0)
Die Seiten sind als einspaltige Stapel für 800x480 entstanden. Auf 1280x720
bleibt daneben rund 40 % der Fläche leer, während unten Karten aus dem Bild
fallen - und Scrollen ist auf diesem Panel teuer, weil ohne Doppelpufferung
jedes Bild komplett neu entsteht.

- Neue Helfer page_grid() und grid_at() legen eine Seite als LVGL-Raster an.
- build_brew() ordnet die vier Karten in zwei Spalten: links was den Bezug
  startet (Pre-Infusion, Brew-by-Time), rechts was ihn beendet
  (Brew-by-Weight, Dampf-Timer).
- Der Speichern-Knopf steht frei unter allen Karten statt in einer davon -
  er speichert die ganze Seite.
- Nur für WS_PANEL_7H; die JC-Panels bleiben einspaltig.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:24:42 +02:00
thomas a1c047e1ef Merge pull request 'perf(P4): Scrollen ohne Nachlauf am Waveshare-Panel (1.6.27)' (#55) from perf/scrollen-ohne-nachlauf into main 2026-09-02 17:03:04 +02:00
raw-designsandClaude Opus 5 52391c46c9 perf(P4): Scrollen ohne Nachlauf am Waveshare-Panel (1.6.27)
Ohne Doppelpufferung entsteht beim Scrollen jedes Bild komplett neu
(1280x676 in 24 Bit, per Software). Am stärksten fällt das beim Ausrollen
nach dem Loslassen auf: Dort bewegt sich das Bild weiter, ohne dass ein
Finger es führt, und jedes Stocken ist unmittelbar zu sehen.

LV_OBJ_FLAG_SCROLL_MOMENTUM ist für die scrollbaren Container deshalb
abgeschaltet - die Liste folgt nur noch dem Finger. Nur für WS_PANEL_7H;
die JC-Panels haben das Tempoproblem nicht und bleiben unverändert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 17:01:40 +02:00
thomas 5d47228eed Merge pull request 'fix(P4): Blaue Zwischenbilder beim Bildlauf beseitigt (1.6.26)' (#54) from fix/blaue-zwischenbilder into main 2026-09-02 03:49:23 +02:00
raw-designsandClaude Opus 5 a3461fe960 fix(P4): Blaue Zwischenbilder beim Bildlauf beseitigt (1.6.26)
Ursache war der zweite Zeichenpuffer aus 1.6.25. esp_lcd_dpi_panel_draw_bitmap
lehnt eine Übertragung ab, solange die vorige noch läuft:

  ESP_RETURN_ON_FALSE(xSemaphoreTake(dpi_panel->draw_sem, 0) == pdTRUE,
                      ESP_ERR_INVALID_STATE, ...)

Mit zwei Puffern schickt LVGL die nächste Übertragung sofort los, statt auf
lv_disp_flush_ready zu warten. Die abgelehnte Übertragung fällt ersatzlos
aus, und der betroffene Bildbereich behält seinen alten oder noch nicht
geschriebenen Inhalt - sichtbar als blaue Zwischenbilder.

Der zweite Zeichenpuffer ist entfernt, lvgl_port_v9.c ist damit wieder
unverändert gegenüber der Hersteller-Portierung. Der eigentliche Gewinn
bleibt: Der Zwischenpuffer hat weiterhin volle Bildhöhe, ein Bildlauf
braucht einen Durchgang statt sechs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 03:47:59 +02:00
thomas 1a05f8e1b3 Merge pull request 'perf(P4): Zeichenpuffer für flüssigen Bildlauf (1.6.25)' (#53) from perf/zeichenpuffer-bildlauf into main 2026-09-02 03:38:44 +02:00
raw-designsandClaude Opus 5 dd8e641aa7 perf(P4): Zeichenpuffer für flüssigen Bildlauf (1.6.25)
Nach der Umstellung auf einen Bildspeicher war der Bildlauf sehr zäh. Grund
war der Zwischenpuffer: Mit 120 Zeilen brauchte ein Bildlauf über die ganze
Seite sechs Durchgänge, jeder mit eigener Übertragung in den Bildspeicher.

- CONFIG_EXAMPLE_LVGL_PORT_BUF_HEIGHT auf LCD_V_RES: ein Durchgang statt
  sechs.
- Zweiter Zeichenpuffer (LVGL_PORT_SECOND_DRAW_BUFFER), damit LVGL den
  nächsten Bereich zeichnen kann, während der vorige übertragen wird. Dafür
  eine kleine, markierte Änderung in lvgl_port_v9.c - der Hersteller-Port
  legt dort nur einen Puffer an.

Kosten 2 x 2,8 MB PSRAM. Das Startverhalten bleibt unberührt: Es handelt
sich um Zeichenpuffer, nicht um Bildspeicher der Anzeige - es bleibt bei
einem Bildspeicher.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-02 03:37:19 +02:00
thomas 6201c1bc36 Merge pull request 'fix(P4): Nur ein Bildspeicher - Ursache des Startfehlers behoben (1.6.24)' (#52) from fix/ein-bildspeicher into main 2026-09-02 03:20:25 +02:00
raw-designsandClaude Opus 5 6d710f0129 fix(P4): Nur ein Bildspeicher - Ursache des Startfehlers behoben (1.6.24)
Mit dem Prüfbild bei num_fbs = 1 startet das Panel zuverlässig, mit zwei
Bildspeichern nicht. Das war der letzte verbliebene Unterschied zum
funktionierenden Werks-Testsketch - und die Ursache des ganzen
Startproblems: Der Hochlauf meldete durchgehend Erfolg, das Panel blieb
dunkel, erst ein Reset half.

- WS7_SINGLE_FB schaltet die Doppelpufferung für das Waveshare-Panel ab
  (EXAMPLE_LVGL_PORT_AVOID_TEAR_ENABLE = 0). LVGL zeichnet dann in einen
  Zwischenpuffer von 120 Zeilen im PSRAM, der per DMA in den einen
  Bildspeicher übertragen wird.
- num_fbs folgt wieder LVGL_PORT_LCD_BUFFER_NUMS, das in diesem Modus 1
  ist - die Sonderbehandlung im Prüfbild-Modus entfällt.
- WS7_PARTIAL_REFRESH ist damit wirkungslos und als solches vermerkt.
- PSRAM-Bedarf sinkt von 5,4 MB auf 2,8 MB.

Preis ist mögliches Tearing bei schnellen Bildwechseln.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7JsiDJ1QbNFLDz5chf8Jt
2026-09-02 03:19:00 +02:00
thomas 5cc71ffa92 Merge pull request 'diag(P4): Prüfbild mit genau einem Bildspeicher, wie im Testsketch (1.6.23)' (#51) from diag/pruefbild-ein-bildspeicher into main 2026-09-02 03:04:57 +02:00
raw-designsandClaude Opus 5 6bef94b8e1 diag(P4): Prüfbild mit genau einem Bildspeicher, wie im Testsketch (1.6.23)
Der Selbst-Neustart aus 1.6.22 reicht nicht - ein Software-Neustart setzt
offenbar nicht dasselbe zurück wie die Reset-Taste.

Damit zurück zu dem einen Unterschied zum funktionierenden Werks-Testsketch,
der bisher nie überprüft wurde: dsi-test.ino setzt num_fbs = 1, die Firmware
nutzt LVGL_PORT_LCD_BUFFER_NUMS = 2. Der Prüfbild-Test lief bislang ebenfalls
mit zwei Speichern und war damit nie ein echter Nachbau - er wich an genau
der offenen Stelle ab.

Mit WS7_TEST_PATTERN = 1 wird num_fbs jetzt fest auf 1 gesetzt. Erscheinen
die Farbbalken damit zuverlässig, liegt es an der Anzahl der Bildspeicher.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7JsiDJ1QbNFLDz5chf8Jt
2026-09-02 03:03:33 +02:00
thomas 95e97e5937 Merge pull request 'fix(P4): Nach Kaltstart einmal selbst neu starten (1.6.22)' (#50) from fix/kaltstart-neustart into main 2026-09-02 02:45:31 +02:00
raw-designsandClaude Opus 5 8db8e166a2 fix(P4): Nach Kaltstart einmal selbst neu starten (1.6.22)
Der DSI-Ab- und Wiederaufbau aus 1.6.21 hat nicht geholfen, sondern das
Bild um einen Schritt verschlechtert: Einschalten - gar nichts, erster
Reset - nur Beleuchtung, zweiter Reset - Bild. Ein Neuaufbau im laufenden
Betrieb ist einem echten Chip-Reset also nicht gleichwertig.
WS7_DSI_RESTART steht wieder auf 0, der Schalter bleibt dokumentiert.

Stattdessen der Weg, den die Messungen stützen: Nach einem Kaltstart
startet der P4 sich genau einmal selbst neu, sobald der erste Hochlauf
durch ist. Ein Reset hat in jedem Versuch zuverlässig geholfen.

- Bedingung ist esp_reset_reason() == ESP_RST_POWERON, beim zweiten
  Durchlauf greift sie nicht mehr - keine Schleife möglich.
- Der Frühstart-Zähler der Absturzsicherung wird vorher zurückgesetzt,
  damit der gewollte Neustart nicht in den Update-Modus führt.
- Schalter WS7_COLD_BOOT_RESTART, kostet ~3 s beim Einschalten.

Das ist eine Umgehung, keine Erklärung: Warum das Panel den ersten Anlauf
nicht annimmt, bleibt offen - der Hochlauf meldet durchgehend Erfolg.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7JsiDJ1QbNFLDz5chf8Jt
2026-09-02 02:44:06 +02:00
thomas 1def9e45dc Merge pull request 'fix(P4): DSI-Strecke beim Hochlauf einmal neu aufbauen (1.6.21)' (#49) from fix/dsi-strecke-neu-aufbauen into main 2026-09-02 02:27:49 +02:00
raw-designsandClaude Opus 5 c2a8b21917 fix(P4): DSI-Strecke beim Hochlauf einmal neu aufbauen (1.6.21)
Der Hochlauf lief zuletzt vollständig fehlerfrei durch - Bridge zweimal
eingestellt, Panel zweimal geweckt, alle I2C-Bausteine erreichbar - und
trotzdem kam beim ersten Einschalten kein Bild. Erst ein Reset half, und
der zuverlässig.

Es fehlte also kein Befehl mehr, sondern der Vorgang selbst: Ein Reset
unterscheidet sich an dieser Stelle in genau einem Punkt von unserem
Ablauf - die DSI-Verbindung geht einmal weg und neu auf, während Bridge
und Panel bereits versorgt und eingestellt sind. Die Wiederholungen aus
1.6.19/1.6.20 liefen dagegen über eine durchgehend bestehende Verbindung.

- Der DSI-Aufbau (Bus, Kommandokanal, Bildausgabe, Weckbefehle) steckt
  jetzt in ws7_dsi_bringup() und ist damit wiederholbar.
- Nach dem ersten Durchlauf werden esp_lcd_panel_del(),
  esp_lcd_panel_io_del() und esp_lcd_del_dsi_bus() aufgerufen und die
  Strecke neu angelegt. Schalter WS7_DSI_RESTART, Pause
  WS7_DSI_RESTART_MS.

Beide Panel-Varianten mit arduino-cli gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7JsiDJ1QbNFLDz5chf8Jt
2026-09-02 02:26:24 +02:00
thomas 6d7d544ac7 Merge pull request 'fix(P4): Bridge-Grundeinstellung nach dem DSI-Start wiederholen (1.6.20)' (#48) from fix/bridge-grundeinstellung-wiederholen into main 2026-09-02 02:12:53 +02:00
raw-designsandClaude Opus 5 992796345c fix(P4): Bridge-Grundeinstellung nach dem DSI-Start wiederholen (1.6.20)
Beobachtung am Gerät: Beim Einschalten geht nach 2-3 s die Beleuchtung an,
dann kommt nichts. Nach einem Reset geht die Beleuchtung kurz aus, danach
erscheint Beleuchtung samt Bild - reproduzierbar in zwei von zwei Fällen.

Dass die Beleuchtung ausgeht, zeigt: Die Bridge folgt dem DSI-Signal. Und
dass der zweite Durchlauf klappt, zeigt warum - die Bridge hatte ihre
Grundeinstellung aus dem ersten Durchlauf noch und fand diesmal ein
DSI-Signal vor. Beim ersten Start bekommt sie ihre Einstellung dagegen,
bevor die DSI-Strecke überhaupt existiert.

ws7_bridge_core_init() ist aus ws7_bridge_pre_init() herausgelöst und wird
jetzt ein zweites Mal aufgerufen, sobald esp_lcd_panel_init() läuft -
dasselbe Vorgehen wie bei ws7_panel_wake() in 1.6.19. Die Register sind
wiederholbar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7JsiDJ1QbNFLDz5chf8Jt
2026-09-02 02:11:29 +02:00
thomas 5e2d0f7af8 Merge pull request 'fix(P4): Panel-Weckbefehle nach dem Start der Videoausgabe wiederholen (1.6.19)' (#47) from fix/panel-weckbefehle-wiederholen into main 2026-09-02 01:41:26 +02:00
15 changed files with 58116 additions and 470 deletions
+526
View File
@@ -1,3 +1,529 @@
Version 1.11.0:
- Die Verlaufskurven im Dashboard beginnen jetzt immer am selben Punkt: Der älteste Wert
liegt links genau auf halber Höhe, die Kurve wächst von dort nach oben oder unten. Der
Verlauf sieht dadurch bei jeder Kesseltemperatur gleich aus.
- Beide Kurven behalten denselben Maßstab. Die absolute Höhe lässt sich damit nicht mehr
zwischen Wasser und Dampf vergleichen - der Ausschlag aber schon: Wer weiter ausschlägt,
hat sich auch stärker verändert.
- Am jüngsten Messwert sitzt ein kleiner weißer Punkt mit weichem Schein, der langsam
pulsiert.
- Beide Linien sind jetzt weiß. Die Farbe der Karte steckt ohnehin in der Überschrift.
Version 1.10.4:
- Die Maßnahme aus 1.10.3 machte die Delle nach dem Standby länger statt kleiner. Sie
hielt beim Umschalten des Standby-Merkers den zuletzt gemeldeten Wert fest - zu diesem
Zeitpunkt lag die gestörte Probe aber bereits an. Festgehalten wurde also ausgerechnet
die Delle, und das sekundenlang.
- Statt einer Sperrfrist tragen die Verlaufskurven jetzt den mittleren Wert der letzten
fünf Proben ein (Median). Eine oder zwei verirrte Proben verschwinden damit vollständig,
unabhängig davon, wann sie auftreten - beim Standby-Ende ebenso wie beim Bezugsstart.
- Echte Temperaturänderungen kommen unverfälscht durch, nur zwei Sekunden später. Das ist
die Verzögerung, um die es hier ging.
- Die angezeigten Temperaturzahlen bleiben weiterhin ungefiltert.
Version 1.10.3:
- Direkt nach dem Aufwachen aus dem Standby zog die Wasserkurve eine kurze Delle nach
unten. Ursache ist die Messung, nicht der Kessel: In genau diesem Moment schalten die
Heizungen, und der Wassersensor hängt als NTC am ADC. Ein Kessel kann binnen einer
Sekunde nicht um Grade einbrechen.
- Die Verlaufskurven halten deshalb rund um jeden Standby-Wechsel sechs Sekunden lang
ihren letzten Wert, statt die gestörte Probe einzutragen. Das gilt für die kleinen
Kurven im Dashboard und für die große Verlaufsseite.
- Die angezeigten Temperaturzahlen bleiben unverändert: Dort steht weiter, was gemessen
wird.
- Die Versionsanzeige stand seit dem Zurücknehmen von 1.6.11 auf 1.6.10 fest und wurde bei
keinem der folgenden Stände mitgezogen. Sie zeigt jetzt wieder den echten Stand.
Version 1.10.2:
- Die Verlaufskurven im Dashboard wurden überhaupt nicht fortgeschrieben. Der Code dafür
stand am Ende der Umschaltung „Heizleistung anzeigen" auf der Verlauf-Seite - also im
Callback eines Knopfes. Die Kurven wuchsen nur weiter, wenn jemand genau diesen Knopf
drückte. Sonst zeigten sie unverändert den Wert, der beim Aufbau der Darstellung gerade
anlag: zwei flache, gleich hohe Linien.
- Die Fortschreibung sitzt jetzt im sekündlichen Abtaster, dort, wo auch der große Verlauf
seine Messwerte nimmt. Damit bewegen sich die Kurven, und die gemeinsame Skala aus 1.10.1
kann ihre Arbeit überhaupt erst tun.
Version 1.10.1:
- Die beiden Verlaufskurven teilen sich jetzt eine gemeinsame Skala. In 1.10.0 zoomte jede
Kurve auf ihre eigenen Werte - dadurch saß jede mittig in ihrem eigenen Fenster, und
Wasser bei 70 Grad lag genauso hoch wie Dampf bei 0. Die Höhe sagte nichts mehr aus.
- Die Skala richtet sich nach den Werten beider Kessel zusammen. Der wärmere Kessel liegt
damit sichtbar höher, und die Skala bleibt so eng, wie es die Daten zulassen: Stehen beide
dicht beieinander, greift die Mindestspanne von vier Grad und schon Zehntelgrade sind zu
erkennen.
Version 1.10.0:
- Die Verlaufskurven im Dashboard zeigen jetzt wirklich einen Verlauf. Ihr Ausschnitt hing
bisher am Sollwert - sechs Grad darunter bis drei darüber. Das funktioniert nur, solange
der Kessel schon nahe am Ziel ist. Heizte er noch auf oder war er ganz aus, lag jeder
Messwert unterhalb des Fensters und wurde auf den unteren Rand geklemmt: Beide Kurven lagen
flach auf derselben Höhe und bewegten sich nicht, obwohl der eine Kessel bei 80 Grad stand
und der andere bei 0. Der Ausschnitt richtet sich jetzt nach den tatsächlich vorhandenen
Werten, mit einer Mindestspanne von vier Grad, damit ein ruhig geregelter Kessel nicht
jedes Zehntelgrad zum vollen Ausschlag aufbläht.
- Die Kurven nehmen jetzt den Platz unterhalb der Zahlen ein statt als schmaler Streifen in
der Mitte zu hängen: Sie beginnen weiter unten auf der Karte und sind deutlich höher.
- Der Nachlauf beim Wischen ist zurück. Er war abgeschaltet, weil jedes Einzelbild während
des Schwungs den ganzen Bildschirm neu zeichnete; seit die Anzeigewerte feste Maße haben,
fällt das weg.
- Die Messzeilen der Fehlersuche sind wieder entfernt. Die Messung des Bildaufbaus bleibt
erhalten, liegt aber hinter dem Schalter WS7_PERF_MONITOR und ist aus.
Version 1.9.12:
- Die Hintergrundbeleuchtung kommt beim Wechsel in den und aus dem Standby jetzt sofort.
Bisher stand das Bild bereits fertig da - im Gegenlicht war es zu sehen -, blieb aber
mehrere Sekunden dunkel. Das war die ganze gesuchte Verzögerung.
- Ursache: Die Bridge übernimmt eine neue Helligkeit nicht zuverlässig beim ersten Mal. Der
Beispielcode von Waveshare setzt sie deshalb zweimal, mit einer Pause dazwischen,
ausdrücklich „sicherheitshalber". Genau diese Wiederholung fehlte.
- Die Panel-Freigabe wird nur noch beim ersten Mal gesetzt. Sie erneut zu setzen, während die
Beleuchtung läuft, stößt die Helligkeitsstufe der Bridge neu an; der Beispielcode setzt sie
ebenfalls nur ein einziges Mal.
- Jeder Helligkeitswechsel meldet jetzt seine Dauer. Bleibt die Beleuchtung wieder hinterher,
lässt sich die Pause zwischen den beiden Übernahmen über WS7_BACKLIGHT_LATCH_MS erhöhen.
Version 1.9.11:
- Endlose Startschleife behoben: Beleuchtung an, nie ein Bild. Der P4 startet sich nach dem
Einschalten absichtlich einmal neu, weil das Panel sonst schwarz bleibt. Die Absicherung
dagegen verließ sich darauf, dass der zweite Start kein Kaltstart mehr ist - der Chip
meldet aber auch nach dem selbst ausgelösten Neustart wieder einen Kaltstart. Damit griff
die Bedingung erneut, endlos.
- Der Neustart wird jetzt vermerkt und beim zweiten Durchlauf erkannt, unabhängig davon, was
der Chip als Startgrund meldet. Beim nächsten echten Einschalten erfolgt wieder genau ein
Neustart.
- Die Meldung über diesen Neustart lief bisher über die USB-Verbindung und war im seriellen
Monitor nicht zu sehen - deshalb war von der Schleife nichts zu erkennen. Sie läuft jetzt
denselben Weg wie die übrigen Panel-Meldungen.
Version 1.9.10:
- Alle Messzeilen laufen jetzt auf derselben Uhr. Die des Zeichenablaufs startete später als
die des Hauptablaufs; die Zeiten ließen sich nur mit Umrechnung vergleichen.
- Der Touch meldet jetzt, wenn er Rohwerte verwirft, weil sie außerhalb des gültigen
Bereichs liegen, und nennt bei jeder erkannten Berührung, wie viele vorher verworfen
wurden. Eine Berührung, deren Rohwerte lange verworfen werden, sieht von außen genauso aus
wie ein Display, das nicht reagiert - das war bisher nicht zu unterscheiden.
Version 1.9.9:
- Die kleinen Kacheln unten im Dashboard behalten beim Bezug ihre Höhe. Bisher bekam die
untere Zeile während des Bezugs deutlich mehr Platz - die Kacheln wurden enorm hoch und
das Dashboard sprang bei jedem Bezugsbeginn sichtbar um.
- Die Messzeilen gingen bisher teils über die USB-Verbindung hinaus und waren im seriellen
Monitor gar nicht zu sehen - die Messung der Helligkeit lief damit ins Leere. Alle
Messzeilen laufen jetzt über denselben Weg wie die Panel-Meldungen.
- Jede Messzeile trägt jetzt eine Zeitmarke. Nur so sind die Lücken zu sehen, in denen die
fünf Sekunden vergehen.
- Der Wechsel in den und aus dem Standby wird an jeder Station vermessen: Ankunft der
Meldung, Warten auf die Anzeigesperre, Dauer der Aktualisierung. Ebenso der Weg vom Tippen
auf die Standby-Uhr bis zur fertig aufgebauten Rückfrage.
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
haben. Die Info-Seite zeigt jetzt nur noch Firmware-Stände und Verbindungsdaten.
- Die Uhr im Standby ist auf dem 7-Zoll-Panel deutlich größer geworden: Die drei Stufen
liegen jetzt bei 180, 270 und 360 Pixeln statt bei 120, 180 und 240. Auf dem 4,3-Zoll-
Panel bleiben die bisherigen Stufen, dort passen größere schlicht nicht auf den Schirm.
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
weiter; sobald die Hauptplatine wieder eine Zeit schickt, gilt deren Wert.
- Der P4 stellt dabei nichts richtig und ersetzt keine Zeitquelle - er überbrückt nur die
Lücke. Hat er noch nie eine Uhrzeit bekommen, bleibt die Anzeige wie bisher leer.
- Gilt für die Uhr in der Kopfleiste und für die große Standby-Uhr.
Version 1.8.5:
- Die Verzögerung von rund zwei Sekunden rund um den Standby ist behoben. Sie lag nicht an
der Helligkeitsumschaltung, sondern daran, dass die Standby-Uhr bei JEDER Zustandsmeldung
der Hauptplatine nach vorn geholt wurde. Das ordnet die Ebenen neu und lässt LVGL den
gesamten Bildschirm neu zeichnen - einmal pro Sekunde, jedes Mal 1280x720 in 24 Bit.
Dadurch hing die Oberfläche dauerhaft ein bis zwei Sekunden hinterher. Nach vorn geholt
wird die Uhr jetzt beim Einblenden, danach bleibt sie dort.
- Der Aufweckdialog schließt sich nach 30 Sekunden ohne Auswahl von selbst und wird wie
„Abbrechen" gewertet. Vorher blieb das Display hell stehen - der Dialog schaltet auf
normale Helligkeit, und ein versehentlicher Tipp auf die Uhr hätte die Maschine die ganze
Nacht leuchten lassen.
- Die Verlaufskurve hat keinen eigenen Hintergrund mehr; sie liegt jetzt direkt auf der
Karte. Die abgesetzte Fläche war nur nötig, solange die Kurve vor dem ersten Messwert
leer blieb - seit sie beim aktuellen Wert startet, ist immer eine Linie da.
- Auf der Statistikseite erschien ein leeres Rechteck, wenn ohne Waage bezogen wurde. Dort
stand ein typografischer Gedankenstrich, den der Zeichensatz der Schrift nicht enthält.
Jetzt ein einfacher Bindestrich.
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
Gradzeichen beschränkt - das C fehlte darin schlicht. Es ist jetzt enthalten, ebenso g
und s für die Gewichts- und Zeitanzeige während eines Bezugs.
- Fehlerbehebung: Bei der Darstellung „Verlauf" war keine Kurve zu sehen. Ein frisch
angelegtes Diagramm enthält lauter „kein Wert"-Punkte und zeichnet deshalb nichts; ohne
Hintergrund war der Bereich vollständig unsichtbar, bis nach einer Minute genug Messwerte
zusammengekommen wären. Die Kurve startet jetzt beim aktuellen Messwert, und ihre Fläche
ist leicht abgesetzt.
- Die großen Zahlen des Dashboards stehen jetzt im fetten Schnitt und etwas enger, wie im
Entwurf. Erzeugt aus der variablen Maven-Pro-Datei mit Gewicht 700 - dieselbe Schriftart
wie bisher, nur kräftiger. Die übrige Oberfläche bleibt unverändert.
Version 1.8.2:
- Die Liste der letzten Bezüge auf der Statistikseite ist jetzt eine Tabelle mit festen
Spalten: Zeitpunkt, Dauer, Gewicht und gegebenenfalls die Kennzeichnung „kalt".
- Vorher war es ein einziges mehrzeiliges Textfeld, in dem die Werte durch Leerzeichen
getrennt aneinandergereiht standen. Weil Zahlen unterschiedlich breit sind, stand nichts
untereinander - zwei Bezüge ließen sich nicht vergleichen, ohne jede Zeile einzeln zu
lesen. Genau das sah unruhig aus.
- Ziffern haben jetzt gleiche Breite, jede zweite Zeile ist leicht abgesetzt, und eine
Kopfzeile benennt die Spalten. Wurde ohne Waage bezogen, bleibt die Gewichtsspalte leer,
statt eine Null vorzutäuschen.
- Die Zeilen werden einmal angelegt und danach nur gefüllt oder ausgeblendet, statt bei
jeder Aktualisierung neu zu entstehen.
Version 1.8.1:
- Die Bezugsanzeige ist da, und zwar für alle vier Darstellungen gemeinsam: Sobald ein
Bezug oder Dampfbezug läuft, schrumpft der Temperaturbereich und die untere Zeile wächst.
Shot-Timer und Gewicht werden dabei auf 96 Pixel vergrößert - während eines Bezugs zählen
Zeit und Gewicht, die Kesseltemperaturen sind dann Nebensache.
- Es gibt keine zweite Ansicht: Die Seite verschiebt nur das Gewicht zwischen ihren beiden
Bereichen. Damit bleibt alles an seinem Platz, und es gibt nichts doppelt zu pflegen.
- Der Wechsel hält nach dem Bezug noch vier Sekunden an. Ohne dieses Nachhalten würde die
Seite bei jeder kurzen Unterbrechung hin- und herspringen - das wäre unruhiger als gar
kein Wechsel.
Version 1.8.0:
- Das Dashboard hat vier neue Darstellungen, die die bisherigen fünf ersetzen. Sie sind
keine Varianten desselben Bildes, sondern vier Antworten auf die Frage, was die große
Fläche des 7-Zöllers leisten soll:
* Gewichtet - Wasser bekommt zwei Drittel der Fläche, Dampf ein Drittel. Beim Espresso
zählt die Wassertemperatur; die Asymmetrie ist die Aussage.
* Verlauf - unter jeder Temperatur eine flache Kurve der letzten Minute. Die eigentliche
Frage an eine PID-Regelung ist nicht „wie warm", sondern „hält sie" - und das kann eine
Zahl grundsätzlich nicht zeigen. Der Ausschnitt hängt am Sollwert, damit die Abweichung
sichtbar wird statt in der Skala unterzugehen.
* Flächen - keine Kartenkanten, zwei Felder mit einem Hauch Helligkeitsunterschied.
* Band - ein farbiges Band über die volle Breite sagt den Zustand, bevor eine Zahl
gelesen wird: bereit, heizt, Bezug, Cold Extraction oder Standby. Neue Vorgabe.
- Dafür gibt es zwei neue Schriftgrade (96 und 140 Pixel). Sie enthalten nur Ziffern,
Komma, Punkt, Minus und Gradzeichen - mit vollem Zeichensatz wären sie um ein Vielfaches
größer, ohne etwas beizutragen. Die größte Textschrift hatte bisher 48 Pixel, was für die
großen Zahlen nicht reichte.
- Ältere Stände haben in den Einstellungen noch die Nummer einer der früheren Darstellungen
gespeichert; liegt sie außerhalb, fällt sie auf die Vorgabe zurück.
- Der Aufbau der Bezugsanzeige - untere Zeile wechselt während eines Bezugs auf große
Timer- und Gewichtsanzeige - folgt als nächster Schritt.
Version 1.7.3:
- Die Schriftgröße steht jetzt auf der Info-Seite im Abschnitt „Darstellung", zusammen mit
der Wahl der Temperaturanzeige und dem Live-Bezugsschirm. Dort gehört sie hin: Es ist
eine Einstellung dieses Displays, keine Wartungsaufgabe.
- Die Seite Reinigung & Wartung hat damit wieder vier Karten in zwei Spalten.
- Die Auswahl selbst ist unverändert: drei Stufen, Neustart nach der Auswahl.
- Sie steht auf allen Panels zur Verfügung, nicht nur auf dem 7-Zöller.
Version 1.7.2:
- Die Schriftgröße lässt sich jetzt einstellen: Klein, Mittel oder Groß, zu finden auf der
Seite Reinigung & Wartung in der neuen Karte „Darstellung".
- LVGL-Schriften sind fest einkompilierte Bilddaten; es gibt sie nur in den Größen, die im
Projekt liegen (14, 18, 28, 40 und 48 Pixel). Stufenlos skalieren lässt sich also nichts.
Stattdessen gibt es drei Rollen - klein, normal, hervorgehoben -, die je nach Einstellung
eine Stufe höher greifen.
- Die großen Anzeigen für Temperatur und Uhrzeit bleiben unverändert: Sie sind bereits auf
die Bildschirmgröße abgestimmt und sollen nicht mitwachsen.
- Die Einstellung liegt lokal im Display, nicht auf der Hauptplatine - sie betrifft nur
dieses Gerät. Nach der Auswahl startet der P4 neu, weil die Schriften in bereits
angelegten Bedienelementen stecken und sich nicht nachträglich umhängen lassen.
- Zu erwarten: In der Stufe Groß brauchen die Karten mehr Platz. Ob alle Seiten dann noch
vollständig auf den Bildschirm passen, zeigt erst das Gerät.
Version 1.7.1:
- Cold Extraction ist auf dem 7-Zoll-Panel dreispaltig: oben die drei Karten mit
Erklaerungstext (Modus, Vorbenetzung, Bezugsende), darunter die knappen (Grundeinstellung,
Hauptbezug, Pumpenschutz), der Speichern-Knopf frei unter allen sechs. Drei statt zwei
Spalten, weil die Erklaerungstexte keine volle Zeilenbreite brauchen und so am Ende keine
halbleere Reihe stehen bleibt.
- Der Warnhinweis stand bisher als eigene Zeile am Seitenende, weit entfernt von dem
Schalter, auf den er sich bezieht. Er sitzt jetzt in der Modus-Karte.
- Reinigung & Wartung ist zweispaltig und besteht aus vier Karten: Wartungszaehler,
Flush-Zeiten, Display-Helligkeit sowie Reinigung & Entkalkung. Bisher standen dort lose
Zeilen unter blossen Zwischenueberschriften, dazwischen freistehende Knoepfe.
- Anders als bei Bruehen und Cold Extraction sitzt der Speichern-Knopf hier IN der Karte:
Jede Karte speichert etwas anderes, deshalb gehoert der Knopf zur Karte statt unter die
Seite.
- Alle drei umgestellten Seiten passen jetzt vollstaendig auf den Bildschirm. Die JC-Panels
behalten ihr einspaltiges Layout.
Version 1.7.0:
- Brew-Control ist auf dem 7-Zoll-Panel zweispaltig: Pre-Infusion und Brew-by-Weight oben,
Brew-by-Time und Dampf-Timer darunter, der Speichern-Knopf frei unter allen Karten.
Damit passt die Seite vollstaendig auf den Bildschirm und muss nicht mehr gescrollt
werden - der teuerste Vorgang der Oberflaeche entfaellt dort ersatzlos.
- Die Anordnung folgt der Bedeutung: links steht, was den Bezug startet, rechts, was ihn
beendet.
- Der Speichern-Knopf sitzt bewusst nicht in einer der Karten. Er speichert die ganze Seite
und wuerde in einer einzelnen Karte so wirken, als gaelte er nur fuer diese.
- Die JC-Panels bleiben einspaltig - dort ist der Platz knapp, nicht ueppig.
- Cold Extraction und Reinigung/Wartung folgen als naechstes.
Version 1.6.27:
- Beim Waveshare-Panel rollen scrollbare Listen nach dem Loslassen nicht mehr aus, sondern
folgen nur dem Finger. Ohne Doppelpufferung entsteht beim Scrollen jedes Bild komplett
neu; am staerksten faellt das beim Ausrollen auf, wo sich das Bild ohne fuehrenden Finger
weiterbewegt und jedes Stocken unmittelbar sichtbar ist.
- Die JC-Panels sind ausgenommen, ihr Bediengefuehl bleibt unveraendert.
Version 1.6.26:
- Fehlerbehebung: Beim Bildlauf blitzten blaue Zwischenbilder auf. Ursache war der zweite
Zeichenpuffer aus 1.6.25. Der Panel-Treiber lehnt eine Uebertragung ab, solange die
vorige noch laeuft; mit zwei Puffern schickt LVGL die naechste aber sofort los. Die
abgelehnte Uebertragung faellt ersatzlos aus, und der betroffene Bildbereich behaelt
seinen alten Inhalt.
- Der zweite Zeichenpuffer ist deshalb wieder entfernt, die Herstellerdatei lvgl_port_v9.c
damit wieder unveraendert. Der eigentliche Gewinn beim Bildlauf bleibt erhalten: Der
Zwischenpuffer hat weiterhin volle Bildhoehe, ein Bildlauf braucht also einen Durchgang
statt sechs.
Version 1.6.25:
- Der Bildlauf war nach der Umstellung auf einen Bildspeicher sehr zaeh. Grund war der
Zwischenpuffer, in den LVGL zeichnet: Mit 120 Zeilen brauchte ein Bildlauf ueber die
ganze Seite sechs Durchgaenge, jeder mit eigener Uebertragung in den Bildspeicher.
- Der Zwischenpuffer hat jetzt volle Bildhoehe - ein Durchgang statt sechs. Dazu kommt ein
zweiter Puffer, damit LVGL bereits den naechsten Bereich zeichnen kann, waehrend der
vorige noch uebertragen wird.
- Kosten: 2 x 2,8 MB PSRAM zusaetzlich, bei 32 MB unkritisch. Am Startverhalten aendert
sich nichts: Diese Puffer sind Zeichenpuffer, keine Bildspeicher der Anzeige - es bleibt
bei EINEM Bildspeicher, und nur der war fuer den Startfehler verantwortlich.
Version 1.6.24:
- Ursache des unzuverlaessigen Starts gefunden und behoben: die Anzahl der Bildspeicher.
Mit zwei Bildspeichern kam nach dem Einschalten kein Bild - der Hochlauf meldete
durchgehend Erfolg, das Panel blieb dunkel, und erst ein Reset half. Mit genau einem
startet es zuverlaessig. Belegt wurde das mit den Prueffarbbalken: Sie erscheinen mit
einem Speicher sofort, mit zweien nicht. Der Werks-Testsketch benutzt ebenfalls einen -
das war der letzte verbliebene Unterschied zu ihm.
- Die Oberflaeche laeuft deshalb ohne Doppelpufferung: LVGL zeichnet in einen
Zwischenpuffer von 120 Zeilen im PSRAM, der dann in den einen Bildspeicher uebertragen
wird. Bei schnellen Bildwechseln kann kurz eine Kante sichtbar werden; ein zuverlaessig
startendes Display wiegt das auf.
- Schalter WS7_SINGLE_FB in pins_config.h. WS7_PARTIAL_REFRESH ist damit wirkungslos, weil
es ohne Doppelpufferung nichts umzuschalten gibt.
- Der PSRAM-Bedarf sinkt von 5,4 MB auf 2,8 MB.
- Die Umgehungen aus den Vorversionen bleiben erhalten: Anlaufzeit, wiederholte
Bridge-Grundeinstellung, wiederholte Weckbefehle und der Neustart nach Kaltstart. Ob
jede davon noch noetig ist, laesst sich jetzt einzeln pruefen - der Startfehler selbst
ist behoben.
Version 1.6.23:
- Der Selbst-Neustart aus 1.6.22 reicht nicht: Ein Software-Neustart setzt offenbar nicht
dasselbe zurueck wie die Reset-Taste. Der Schalter bleibt eingeschaltet, er schadet nicht,
loest das Problem aber nicht allein.
- Zurueck zu dem einen Unterschied zum funktionierenden Werks-Testsketch, der bisher nie
ueberprueft wurde: Dieser legt EINEN Bildspeicher an, die Firmware zwei. Der Pruefbild-Test
lief bislang ebenfalls mit zwei und war damit nie ein echter Nachbau des Testsketches - er
wich an genau der Stelle ab, die noch offen ist.
- Mit WS7_TEST_PATTERN = 1 wird jetzt genau ein Bildspeicher angelegt, wie im Testsketch.
Erscheinen die Farbbalken damit zuverlaessig, liegt es an der Anzahl der Bildspeicher, und
die Oberflaeche laesst sich darauf umstellen.
Version 1.6.22:
- Der Ab- und Wiederaufbau der DSI-Strecke aus 1.6.21 hat nicht geholfen, sondern das Bild
um einen Schritt verschlechtert: Nach dem Einschalten kam gar nichts mehr, nach dem
ersten Reset nur die Beleuchtung, erst nach dem zweiten das Bild. Ein Ab- und Wiederaufbau
im laufenden Betrieb ist einem echten Chip-Reset also nicht gleichwertig. WS7_DSI_RESTART
steht deshalb wieder auf 0; der Schalter bleibt samt Begruendung erhalten.
- Stattdessen der Weg, den die Messungen eindeutig stuetzen: Nach einem Kaltstart startet
der P4 sich genau einmal selbst neu, sobald der erste Hochlauf durch ist. Damit passiert
genau das, was bei jedem Versuch zuverlaessig geholfen hat - ohne dass jemand die
Reset-Taste druecken muss.
- Eine Schleife ist ausgeschlossen: Beim zweiten Durchlauf ist der Startgrund kein Kaltstart
mehr, die Bedingung greift nicht erneut. Der Fruehstart-Zaehler der Absturzsicherung wird
vor dem gewollten Neustart zurueckgesetzt, damit dieser nicht als Absturz zaehlt.
- Kostet rund drei Sekunden, und nur beim Einschalten. Schalter WS7_COLD_BOOT_RESTART in
pins_config.h.
- Das ist eine Umgehung, keine Erklaerung: Warum das Panel den ersten Anlauf nach dem
Einschalten nicht annimmt, ist weiterhin offen. Der Hochlauf meldet durchgehend Erfolg.
Version 1.6.21:
- Der Hochlauf lief zuletzt vollstaendig fehlerfrei durch - Bridge zweimal eingestellt,
Panel zweimal geweckt, alle I2C-Bausteine erreichbar - und trotzdem kam beim ersten
Einschalten kein Bild. Erst ein Reset half, und der zuverlaessig. Es fehlte also kein
Befehl mehr; es fehlte der Vorgang selbst.
- Ein Reset unterscheidet sich an dieser Stelle in genau einem Punkt: Die DSI-Verbindung
geht einmal weg und neu auf, waehrend Bridge und Panel bereits versorgt und eingestellt
sind. Weder die wiederholte Grundeinstellung noch die wiederholten Weckbefehle ersetzen
das - beide laufen ueber eine Verbindung, die durchgehend bestand.
- Der Hochlauf baut die DSI-Strecke jetzt einmal komplett ab und wieder auf: Bildausgabe,
Kommandokanal und Bus werden freigegeben und neu angelegt. Damit passiert ohne Reset,
was vorher erst der zweite Start brachte. Schalter WS7_DSI_RESTART in pins_config.h,
Pause dazwischen WS7_DSI_RESTART_MS (Vorgabe 200 ms).
- Der DSI-Aufbau steckt dafuer in einer eigenen Funktion, damit der Vorgang wiederholbar
ist statt zweimal im Quelltext zu stehen.
Version 1.6.20:
- Nach 1.6.19 lief es reproduzierbar so ab: Beim Einschalten ging nach zwei bis drei
Sekunden die Hintergrundbeleuchtung an, dann kam nichts mehr; nach einem Reset ging die
Beleuchtung kurz aus und danach erschien Beleuchtung samt Bild. Daraus folgt der letzte
fehlende Schritt: Auch die Grundeinstellung der Bridge lief bisher nur einmal, und zwar
bevor die DSI-Strecke ueberhaupt existierte. Beim Reset half es nur deshalb, weil die
Bridge ihre Einstellung aus dem vorigen Durchlauf noch hatte und diesmal ein DSI-Signal
vorfand.
- Die Grundeinstellung der Bridge wird jetzt ein zweites Mal geschrieben, sobald die
Videoausgabe laeuft - dasselbe Vorgehen wie bei den Weckbefehlen des Panels in 1.6.19.
Damit wird ohne Reset erreicht, was vorher erst der zweite Durchlauf brachte.
- Im Start-Log sind beide Durchgaenge benannt ("Bridge-Grundeinstellung vor dem DSI-Start"
und "... nach dem Start der Videoausgabe").
Version 1.6.19:
- Die Wartezeit aus 1.6.18 hat den Start deutlich verbessert, aber noch nicht zuverlässig
gemacht. Aus dem verbliebenen Fehlerbild folgt der nächste Schritt: Die Beleuchtung ging
+44 -1
View File
@@ -24,6 +24,7 @@
#include "protocol_client.h"
#include "ui.h"
#include "display_hal.h"
#include "pins_config.h"
#include <ArduinoJson.h>
#include <Update.h>
#include <Preferences.h>
@@ -66,7 +67,7 @@ static void onState(const MachineState& st) {
}
if (bl < 0) bl = 0; if (bl > 100) bl = 100;
if (bl != s_lastBacklight) {
hal_backlight(bl);
hal_backlight(bl); // meldet seine Dauer selbst, siehe jc_backlight_set()
s_lastBacklight = bl;
}
}
@@ -296,6 +297,48 @@ void setup() {
g_client.onOta(onOta);
hal_init(&g_client); // LVGL + Panel/Touch + Dashboard (ruft ui_init intern auf)
// --- Waveshare-Panel: einmaliger Neustart nach dem Einschalten ---
//
// Das Panel kommt nach dem Anlegen der Versorgung im ersten Anlauf nicht zuverlaessig
// hoch: Die Beleuchtung geht an, ein Bild bleibt aus - obwohl jeder Schritt des
// Hochlaufs Erfolg meldet. Ein Reset behebt es zuverlaessig, und zwar nur ein echter
// Chip-Reset; die DSI-Strecke im laufenden Betrieb ab- und wieder aufzubauen genuegt
// nicht (siehe WS7_DSI_RESTART).
//
// Deshalb startet der P4 sich nach einem Kaltstart genau einmal selbst neu, nachdem
// der erste Hochlauf durch ist. Kostet rund drei Sekunden, aber nur beim Einschalten.
//
// Frueher stuetzte sich die Absicherung dagegen allein auf den Startgrund: Beim zweiten
// Durchlauf sei es kein Kaltstart mehr, eine Schleife also ausgeschlossen. Das stimmt
// nicht - der Chip meldet auch nach dem selbst ausgeloesten Neustart wieder einen
// Kaltstart, und dann startet er endlos neu. Genau das ist aufgetreten: Beleuchtung an,
// nie ein Bild. Deshalb wird jetzt zusaetzlich vermerkt, dass der Neustart schon
// stattgefunden hat; darauf ist Verlass, unabhaengig vom gemeldeten Startgrund.
#if (JC_PANEL_TYPE == WS_PANEL_7H) && WS7_COLD_BOOT_RESTART
if (esp_reset_reason() == ESP_RST_POWERON) {
Preferences p;
p.begin("bootguard", false);
bool schonNeugestartet = p.getUChar("kaltneu", 0) != 0;
if (schonNeugestartet) {
// Zweiter Durchlauf: Vermerk loeschen, damit beim naechsten echten Einschalten
// wieder genau ein Neustart erfolgt.
p.putUChar("kaltneu", 0);
p.end();
esp_rom_printf("[Panel] Neustart bereits erfolgt - Hochlauf wird fortgesetzt\n");
} else {
p.putUChar("kaltneu", 1);
// Der Fruehstart-Zaehler wurde oben bereits erhoeht. Diesen gewollten Neustart
// darf er nicht mitzaehlen, sonst laeuft die Absturzsicherung nach ein paar
// Einschaltvorgaengen in den Update-Modus.
p.putUShort("early", 0);
p.end();
esp_rom_printf("[Panel] Kaltstart - einmaliger Neustart fuer das Displaypanel\n");
delay(50);
esp_restart();
}
}
#endif
g_client.begin(); // UART starten, hello folgt automatisch in loop()
DBG_SERIAL.println(F("Bereit. Warte auf Verbindung zur Hauptplatine..."));
+1 -1
View File
@@ -50,7 +50,7 @@ Vendor-Pakete: 4,3" im Ordner `JC4880P443C_I_W/`, 7,0" im Repo-Ordner
| Touch-Rohkoordinaten | 480×800 (= Panelraster) | **800×480** → wird auf 1024×600 skaliert | **720×1280** (Hochformat) → X/Y werden getauscht |
| LCD-Reset | GPIO5 | **GPIO27** | kein Reset-Pin (macht die Bridge) |
| Backlight | GPIO23 (LEDC-PWM) | GPIO23 (LEDC-PWM) | **Bridge-Register** auf I²C **0x45** (`AD`/`AB`/`AA`) |
| Framebuffer | 3 × 750 KB ≈ 2,3 MB PSRAM | 3 × 1,2 MB ≈ 3,6 MB PSRAM | 3 × 2,8 MB ≈ 8,3 MB PSRAM |
| Framebuffer | 3 × 750 KB ≈ 2,3 MB PSRAM | 3 × 1,2 MB ≈ 3,6 MB PSRAM | **1 × 2,8 MB** — mehr verträgt das Panel beim Start nicht |
| Freie Expansion-IO | Stiftleiste **JP1**: GPIO 52/51/50/49/35/34/33/32/31/30/29/28 | FPC 1,0 mm 16-pol. **FPC4**: GPIO 34/33/32/31/30/29/28 · **FPC3**: 48/47/46/45/5/4/3/2 | 40-poliger Header im Raspberry-Pi-Pico-Format; belegt sind I²C (7/8), TF-Karte (9/10/11/12/13/53) und Debug-UART0 (37/38) |
| UART zur Hauptplatine | TX GPIO33 / RX GPIO31 | TX GPIO33 / RX GPIO31 | **TX GPIO20 / RX GPIO21** |
+162 -61
View File
@@ -193,8 +193,24 @@ static void ws7_bridge_write(uint8_t reg, uint8_t value)
}
}
// Bridge am I2C-Bus anmelden und Grundinitialisierung schreiben. Muss VOR dem
// DSI-Bringup laufen; die Hintergrundbeleuchtung bleibt dabei noch aus.
// Grundeinstellung der Bridge. Bewusst mehrfach aufrufbar, siehe unten.
//
// Warum zweimal: Beim ersten Aufruf existiert die DSI-Strecke noch gar nicht - die Bridge
// bekommt ihre Einstellung also, bevor ein Signal anliegt. Beim ersten Einschalten reichte
// das nicht: Die Beleuchtung ging an (die haengt an der Bridge), ein Bild kam aber nicht.
// Erst ein Reset half - und dann nur deshalb, weil die Bridge ihre Einstellung aus dem
// vorigen Durchlauf noch hatte und diesmal ein DSI-Signal vorfand. Genau das holt der
// zweite Aufruf nach, ohne dass ein Reset noetig ist. Die Register sind wiederholbar.
static void ws7_bridge_core_init(const char *wann)
{
esp_rom_printf("[Panel] Bridge-Grundeinstellung %s\n", wann);
ws7_bridge_write(0xC0, 0x01);
ws7_bridge_write(0xC2, 0x01);
ws7_bridge_write(0xAC, 0x01);
}
// Bridge am I2C-Bus anmelden und erstmalig einstellen. Laeuft VOR dem DSI-Bringup;
// die Hintergrundbeleuchtung bleibt dabei noch aus.
static void ws7_bridge_pre_init(void)
{
i2c_device_config_t dev_cfg = {
@@ -206,9 +222,7 @@ static void ws7_bridge_pre_init(void)
s_bridge_handle = NULL;
return;
}
ws7_bridge_write(0xC0, 0x01);
ws7_bridge_write(0xC2, 0x01);
ws7_bridge_write(0xAC, 0x01);
ws7_bridge_core_init("vor dem DSI-Start");
}
void jc_backlight_init(void)
@@ -221,9 +235,34 @@ void jc_backlight_set(int percent)
if (percent > 100) percent = 100;
if (percent < 0) percent = 0;
uint8_t brightness = (uint8_t)((255 * percent) / 100);
ws7_bridge_write(0xAD, 0x01); // Panel-/Backlight-Freigabe
ws7_bridge_write(0xAB, (uint8_t)(255 - brightness));
uint8_t wert = (uint8_t)(255 - brightness);
int64_t t0 = esp_timer_get_time();
// Die Bridge uebernimmt eine neue Helligkeit nicht zuverlaessig beim ersten Mal. Der
// Beispielcode von Waveshare setzt sie deshalb zweimal, mit einer Pause dazwischen,
// ausdruecklich "sicherheitshalber". Uns fehlte diese Wiederholung: Das Bild stand
// dann fertig da, blieb aber dunkel, bis die Uebernahme irgendwann doch griff - beim
// Ein- und Ausschalten des Standby waren das mehrere Sekunden.
//
// Die Freigabe (0xAD) bleibt beim ersten Aufruf, danach nicht mehr: Sie erneut zu
// setzen, waehrend die Beleuchtung laeuft, stoesst die Helligkeitsstufe der Bridge neu
// an - der Beispielcode setzt sie darum ebenfalls nur ein einziges Mal.
static bool freigegeben = false;
if (!freigegeben) {
ws7_bridge_write(0xAD, 0x01); // Panel-/Backlight-Freigabe
vTaskDelay(pdMS_TO_TICKS(20)); // wie im Beispielcode: Bridge setzen lassen
freigegeben = true;
}
ws7_bridge_write(0xAB, wert);
ws7_bridge_write(0xAA, 0x01); // Helligkeit uebernehmen
vTaskDelay(pdMS_TO_TICKS(WS7_BACKLIGHT_LATCH_MS));
ws7_bridge_write(0xAB, wert); // Wiederholung, siehe oben
ws7_bridge_write(0xAA, 0x01);
esp_rom_printf("[HAL] %u ms: Helligkeit %d %% gesetzt, brauchte %u ms\n",
(unsigned)(esp_timer_get_time() / 1000), percent,
(unsigned)((esp_timer_get_time() - t0) / 1000));
}
// =====================================================================================
@@ -296,14 +335,26 @@ static bool ws7_touch_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y
bool got = s_touch_get_xy_orig(tp, x, y, strength, point_num, max_point_num);
int64_t now = esp_timer_get_time();
// Unplausible Rohwerte gelten als Aussetzer, nicht als Beruehrung.
// Unplausible Rohwerte gelten als Aussetzer, nicht als Beruehrung. Wie viele davon
// anfallen, war bisher nirgends zu sehen - eine Beruehrung, deren Rohwerte lange
// verworfen werden, sieht von aussen wie ein Display aus, das nicht reagiert.
static uint32_t s_verworfen = 0;
if (got && *point_num > 0 &&
(x[0] > WS7_TOUCH_RAW_X_MAX || y[0] > WS7_TOUCH_RAW_Y_MAX)) {
if (s_verworfen == 0)
esp_rom_printf("[Touch] %u ms: Rohwert verworfen (x %u, y %u liegen ausserhalb)\n",
(unsigned)(now / 1000), (unsigned)x[0], (unsigned)y[0]);
s_verworfen++;
got = false;
*point_num = 0;
}
if (got && *point_num > 0) {
if (!s_touch_down)
esp_rom_printf("[Touch] %u ms: Beruehrung erkannt bei x %u, y %u; %u Rohwerte vorher verworfen\n",
(unsigned)(now / 1000), (unsigned)x[0], (unsigned)y[0],
(unsigned)s_verworfen);
s_verworfen = 0;
s_touch_last_x = x[0];
s_touch_last_y = y[0];
s_touch_last_us = now;
@@ -408,6 +459,86 @@ static void ws7_panel_wake(esp_lcd_panel_io_handle_t io, const char *wann)
}
#endif
#if JC_PANEL_TYPE == WS_PANEL_7H
// Baut die komplette DSI-Strecke auf: Bus, Kommandokanal, Bildausgabe, und weckt das
// Panel. Bewusst als eigene Funktion, damit der ganze Vorgang wiederholbar ist.
static bool ws7_dsi_bringup(esp_lcd_dsi_bus_handle_t *out_bus,
esp_lcd_panel_io_handle_t *out_io,
esp_lcd_panel_handle_t *out_panel,
esp_lcd_dpi_panel_config_t *out_dpi_config)
{
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
esp_lcd_panel_io_handle_t io = NULL;
esp_lcd_panel_handle_t disp_panel = NULL;
esp_lcd_dsi_bus_config_t bus_config = {
.bus_id = 0,
.num_data_lanes = WS7_DSI_LANES,
.phy_clk_src = MIPI_DSI_PHY_PLLREF_CLK_SRC_PLL_F20M,
.lane_bit_rate_mbps = WS7_DSI_LANE_MBPS,
};
BSP_STEP(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus), "MIPI-DSI-Bus");
esp_lcd_dbi_io_config_t dbi_config = {
.virtual_channel = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
};
BSP_STEP(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io), "DBI-Kommandokanal");
esp_lcd_dpi_panel_config_t dpi_config = {
.virtual_channel = 0,
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = WS7_DPI_CLOCK_MHZ,
#if WS7_COLOR_BITS == 24
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888,
#else
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
#endif
// Anzahl der Bildspeicher. Beim Waveshare-Panel genau einer: mit zweien kam nach
// dem Einschalten kein Bild (siehe WS7_SINGLE_FB in pins_config.h).
.num_fbs = LVGL_PORT_LCD_BUFFER_NUMS,
.video_timing = {
.h_size = BSP_LCD_H_RES,
.v_size = BSP_LCD_V_RES,
.hsync_back_porch = WS7_HSYNC_BACK,
.hsync_pulse_width = WS7_HSYNC_PULSE,
.hsync_front_porch = WS7_HSYNC_FRONT,
.vsync_back_porch = WS7_VSYNC_BACK,
.vsync_pulse_width = WS7_VSYNC_PULSE,
.vsync_front_porch = WS7_VSYNC_FRONT,
},
.flags = {
.use_dma2d = true,
},
};
BSP_STEP(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &disp_panel),
"DPI-Panel (Framebuffer im PSRAM)");
if (disp_panel == NULL) {
esp_rom_printf("[Panel] Abbruch: Panel wurde nicht angelegt. Haeufigste Ursache ist zu "
"wenig PSRAM - PSRAM in den Board-Einstellungen aktivieren oder in "
"pins_config.h weniger Framebuffer waehlen.\n");
return false;
}
ws7_panel_wake(io, "vor dem Start der Videoausgabe");
BSP_STEP(esp_lcd_panel_init(disp_panel), "DPI-Videoausgabe starten");
// Zweiter Anlauf, jetzt bei laufender Videoausgabe: faengt den Fall ab, dass das
// Panel beim ersten Mal noch nicht aufnahmebereit war.
vTaskDelay(pdMS_TO_TICKS(WS7_PANEL_SETTLE_MS));
ws7_bridge_core_init("nach dem Start der Videoausgabe");
ws7_panel_wake(io, "nach dem Start der Videoausgabe");
*out_bus = mipi_dsi_bus;
*out_io = io;
*out_panel = disp_panel;
*out_dpi_config = dpi_config;
return true;
}
#endif
// Bringt Panel + Touch + LVGL-Port hoch (LVGL laeuft danach in eigenem Task).
// Rueckgabe false: Panel kam nicht hoch - der Aufrufer darf dann KEINE LVGL-Funktion
// benutzen, sonst folgt ein zweiter Absturz, der die eigentliche Ursache ueberdeckt.
@@ -469,9 +600,12 @@ bool jc_board_bringup(void)
};
BSP_STEP(esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan), "Stromversorgung MIPI-D-PHY");
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL;
esp_lcd_panel_io_handle_t io = NULL;
esp_lcd_panel_handle_t disp_panel = NULL;
#if JC_PANEL_TYPE == WS_PANEL_7H
esp_lcd_dpi_panel_config_t dpi_config;
#endif
#if JC_PANEL_TYPE == WS_PANEL_7H
// ---------------- Waveshare 7inch DSI LCD (H) (1280x720) ----------------
@@ -481,62 +615,29 @@ bool jc_board_bringup(void)
bsp_report_psram((size_t)BSP_LCD_H_RES * BSP_LCD_V_RES * BSP_LCD_FB_BYTES_PER_PX
* LVGL_PORT_LCD_BUFFER_NUMS);
esp_lcd_dsi_bus_config_t bus_config = {
.bus_id = 0,
.num_data_lanes = WS7_DSI_LANES,
.phy_clk_src = MIPI_DSI_PHY_PLLREF_CLK_SRC_PLL_F20M,
.lane_bit_rate_mbps = WS7_DSI_LANE_MBPS,
};
BSP_STEP(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus), "MIPI-DSI-Bus");
esp_lcd_dbi_io_config_t dbi_config = {
.virtual_channel = 0,
.lcd_cmd_bits = 8,
.lcd_param_bits = 8,
};
BSP_STEP(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io), "DBI-Kommandokanal");
esp_lcd_dpi_panel_config_t dpi_config = {
.virtual_channel = 0,
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
.dpi_clock_freq_mhz = WS7_DPI_CLOCK_MHZ,
#if WS7_COLOR_BITS == 24
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888,
#else
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
#endif
.num_fbs = LVGL_PORT_LCD_BUFFER_NUMS,
.video_timing = {
.h_size = BSP_LCD_H_RES,
.v_size = BSP_LCD_V_RES,
.hsync_back_porch = WS7_HSYNC_BACK,
.hsync_pulse_width = WS7_HSYNC_PULSE,
.hsync_front_porch = WS7_HSYNC_FRONT,
.vsync_back_porch = WS7_VSYNC_BACK,
.vsync_pulse_width = WS7_VSYNC_PULSE,
.vsync_front_porch = WS7_VSYNC_FRONT,
},
.flags = {
.use_dma2d = true,
},
};
BSP_STEP(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &disp_panel),
"DPI-Panel (Framebuffer im PSRAM)");
if (disp_panel == NULL) {
esp_rom_printf("[Panel] Abbruch: Panel wurde nicht angelegt. Haeufigste Ursache ist zu "
"wenig PSRAM - PSRAM in den Board-Einstellungen aktivieren oder in "
"pins_config.h weniger Framebuffer waehlen.\n");
if (!ws7_dsi_bringup(&mipi_dsi_bus, &io, &disp_panel, &dpi_config)) {
return false;
}
ws7_panel_wake(io, "vor dem Start der Videoausgabe");
#if WS7_DSI_RESTART
// Die Strecke einmal komplett ab- und wieder aufbauen.
//
// Beim ersten Einschalten kam trotz fehlerfreiem Hochlauf kein Bild; erst ein Reset
// half, und zwar zuverlaessig. Ein Reset unterscheidet sich an dieser Stelle nur in
// einem Punkt von unserem Ablauf: Die DSI-Verbindung geht einmal weg und neu auf,
// waehrend Bridge und Panel bereits versorgt und eingestellt sind. Weder die
// wiederholte Grundeinstellung der Bridge noch die wiederholten Weckbefehle ersetzen
// das. Genau dieser Ab- und Wiederaufbau wird hier nachgeholt - ohne Reset.
esp_rom_printf("[Panel] DSI-Strecke wird neu aufgebaut\n");
esp_lcd_panel_del(disp_panel);
esp_lcd_panel_io_del(io);
esp_lcd_del_dsi_bus(mipi_dsi_bus);
vTaskDelay(pdMS_TO_TICKS(WS7_DSI_RESTART_MS));
BSP_STEP(esp_lcd_panel_init(disp_panel), "DPI-Videoausgabe starten");
// Zweiter Anlauf, jetzt bei laufender Videoausgabe: faengt den Fall ab, dass das
// Panel beim ersten Mal noch nicht aufnahmebereit war.
vTaskDelay(pdMS_TO_TICKS(WS7_PANEL_SETTLE_MS));
ws7_panel_wake(io, "nach dem Start der Videoausgabe");
if (!ws7_dsi_bringup(&mipi_dsi_bus, &io, &disp_panel, &dpi_config)) {
return false;
}
#endif
#if WS7_TEST_PATTERN
// Prueffarbbalken: Sie entstehen im DSI-Baustein selbst und benutzen weder den
// Bildspeicher noch LVGL. Erscheinen sie, arbeitet die Anzeigekette bis zum Panel und
+1 -1
View File
@@ -126,7 +126,7 @@
// -------------------------------------------------------------------------------------
// Firmware
// -------------------------------------------------------------------------------------
#define DISPLAY_FW_VERSION "1.6.10" // Firmware-Stand der P4-Display-Steuerung (Info-Seite)
#define DISPLAY_FW_VERSION "1.11.0" // Firmware-Stand der P4-Display-Steuerung (Info-Seite)
// -------------------------------------------------------------------------------------
// Protokoll
+11 -3
View File
@@ -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
@@ -567,7 +569,13 @@
LV_FONT_DECLARE(lv_font_maven_pro_28) \
LV_FONT_DECLARE(lv_font_maven_pro_40) \
LV_FONT_DECLARE(lv_font_maven_pro_48) \
LV_FONT_DECLARE(lv_font_clock_240)
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) \
LV_FONT_DECLARE(lv_font_clock_270) \
LV_FONT_DECLARE(lv_font_clock_360)
/*Always set a default font*/
#define LV_FONT_DEFAULT &lv_font_maven_pro_14
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
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
+61
View File
@@ -32,7 +32,19 @@
// startet der P4 nicht mehr, hier zuerst auf 0 stellen.
// -------------------------------------------------------------------------------------
#define WS7_COLOR_BITS 24
// Ohne Wirkung, solange WS7_SINGLE_FB = 1 ist: Mit nur einem Bildspeicher gibt es keine
// Doppelpufferung, zwischen deren Betriebsarten man waehlen koennte.
#define WS7_PARTIAL_REFRESH 1
// Nur EIN Bildspeicher. Zwei vertraegt die DSI-Ausgabe dieses Panels beim Einschalten
// 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
@@ -42,7 +54,32 @@
#define EXAMPLE_LVGL_PORT_TASK_CORE -1 //range -1 to 1
#define EXAMPLE_LVGL_PORT_TICK 2 //ragne 1 to 100
// Ruckelfreie Ausgabe braucht mindestens zwei Bildspeicher, aus denen abwechselnd
// angezeigt und in die gezeichnet wird.
//
// Das Waveshare-Panel vertraegt das nicht: Mit zwei Bildspeichern kam nach dem Einschalten
// kein Bild - der Hochlauf meldete durchgehend Erfolg, das Panel blieb dunkel, und erst ein
// Reset half. Mit genau einem Bildspeicher startet es zuverlaessig; belegt wurde das mit den
// Prueffarbbalken, die der Werks-Testsketch ebenfalls mit einem Speicher anzeigt.
// Deshalb hier ohne Doppelpufferung: LVGL zeichnet in einen kleinen Zwischenpuffer, der
// dann in den einen Bildspeicher uebertragen wird. Bei schnellen Bildwechseln kann dabei
// kurz eine Kante sichtbar werden - ein zuverlaessig startendes Display wiegt das auf.
#if (JC_PANEL_TYPE == WS_PANEL_7H) && WS7_SINGLE_FB
#define EXAMPLE_LVGL_PORT_AVOID_TEAR_ENABLE 0
// Zwischenpuffer fuer das Zeichnen. Volle Bildhoehe, damit ein Bildlauf in EINEM Durchgang
// gezeichnet und uebertragen wird. Mit 120 Zeilen waren es sechs Durchgaenge samt sechs
// Uebertragungen - das war der Grund fuer den zaehen Bildlauf. Kostet 2,8 MB PSRAM.
//
// Bewusst nur EIN Zeichenpuffer: Ein zweiter wuerde LVGL erlauben, schon den naechsten
// Bereich zu zeichnen, waehrend der vorige uebertragen wird. Der Panel-Treiber lehnt eine
// Uebertragung aber ab, solange die vorige laeuft (ESP_ERR_INVALID_STATE) - der betroffene
// Bildbereich wird dann gar nicht geschrieben und behaelt seinen alten Inhalt. Sichtbar
// war das als blaue Zwischenbilder beim Bildlauf.
#define CONFIG_EXAMPLE_LVGL_PORT_BUF_PSRAM 1
#define CONFIG_EXAMPLE_LVGL_PORT_BUF_HEIGHT LCD_V_RES
#else
#define EXAMPLE_LVGL_PORT_AVOID_TEAR_ENABLE 1
#endif
#ifdef EXAMPLE_LVGL_PORT_AVOID_TEAR_ENABLE
// 2 = Triple-Buffer + LVGL Full-Refresh: zeichnet bei jeder Aenderung das komplette
@@ -145,6 +182,14 @@
// auf I2C antwortet. Meldet sich 0x14 beim Start nicht, diesen Wert erhoehen.
#define WS7_TOUCH_POWER_MS 120
// Pause zwischen den beiden Helligkeitsuebernahmen der Bridge. Sie uebernimmt eine neue
// Helligkeit nicht zuverlaessig beim ersten Mal; der Beispielcode von Waveshare setzt sie
// darum zweimal. Ohne die Wiederholung stand das Bild fertig da, blieb aber dunkel - beim
// Wechsel in den und aus dem Standby mehrere Sekunden lang. Der Beispielcode wartet 100 ms;
// weniger genuegt hier, weil die Wiederholung ohnehin folgt. Bleibt die Beleuchtung wieder
// hinterher, diesen Wert erhoehen.
#define WS7_BACKLIGHT_LATCH_MS 20
// Prueffarbbalken statt Oberflaeche anzeigen. Sie entstehen im DSI-Baustein selbst und
// benutzen weder Bildspeicher noch LVGL. Damit laesst sich trennen, ob die Anzeigekette
// bis zum Panel arbeitet (Balken sichtbar) oder nicht (schwarz). Nur zur Fehlersuche.
@@ -159,6 +204,22 @@
// Beleuchtung brennt - sie haengt an der Bridge, nicht am Panel.
#define WS7_PANEL_SETTLE_MS 200
// Die DSI-Strecke beim Hochlauf einmal ab- und wieder aufbauen. Beim ersten Einschalten
// kam sonst trotz fehlerfreiem Ablauf kein Bild; erst ein Reset half. Der einzige
// Unterschied dabei: Die DSI-Verbindung geht einmal weg und neu auf, waehrend Bridge und
// Panel schon versorgt und eingestellt sind. Genau das holt der zweite Aufbau nach.
// Kostet WS7_DSI_RESTART_MS zusaetzliche Startzeit.
#define WS7_DSI_RESTART 0
#define WS7_DSI_RESTART_MS 200
// Nach einem Kaltstart einmal selbst neu starten, sobald der erste Hochlauf durch ist.
// Das Panel kommt beim ersten Anlauf nach dem Einschalten nicht zuverlaessig hoch;
// ein echter Chip-Reset behebt es zuverlaessig, der Ab- und Wiederaufbau der
// DSI-Strecke im Betrieb dagegen nicht. Kostet rund drei Sekunden beim Einschalten.
// Eine Schleife ist ausgeschlossen: Beim zweiten Durchlauf ist der Startgrund kein
// Kaltstart mehr.
#define WS7_COLD_BOOT_RESTART 1
#define WS7_TEST_PATTERN 0
#elif JC_PANEL_TYPE == JC_PANEL_70
+1228 -402
View File
File diff suppressed because it is too large Load Diff