Compare commits

..
Author SHA1 Message Date
raw-designsandClaude Opus 5 e8308a9182 fix(P4): Schwarzes Bild nach Reset am Waveshare-Panel (1.6.11)
Nach einem Reset des P4 blieb das Bild schwarz, die Hintergrundbeleuchtung
brannte; nur direkt nach dem Flashen lief es.

Die Bridge des Panels hat keine Reset-Leitung und hängt an Dauerstrom. Ein
Reset des P4 setzt sie nicht zurück - ihre Register standen noch auf den
Werten der vorigen Sitzung, während der P4 seine DSI-Strecke komplett neu
aufbaut. Beim Flashen wird die Versorgung getrennt, deshalb trat der Fehler
dort nicht auf.

ws7_bridge_pre_init() schaltet die Bridge jetzt zuerst definiert ab
(AB/AA, AD, dann AC/C2/C0), wartet WS7_BRIDGE_RESET_MS und schreibt erst
danach die Grundinitialisierung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
2026-09-01 15:22:11 +02:00
thomas edb1e333f0 Merge pull request 'perf(P4): Teil-Neuzeichnen als Vorgabe, Messeinblendung, deckende Seiten (1.6.10)' (#38) from perf/scrollen-messen-und-vorgaben into main 2026-09-01 14:46:56 +02:00
raw-designsandClaude Opus 5 528c8d5500 perf(P4): Teil-Neuzeichnen als Vorgabe, Messeinblendung, deckende Seiten (1.6.10)
- WS7_PARTIAL_REFRESH = 1 auch im Auslieferungsstand. Am Gerät geprüft: kein
  Flackern; von den drei Tempo-Maßnahmen aus 1.6.4 ist es der größte Gewinn.
- make_page() setzt einen deckenden Hintergrund in COL_BG statt LV_OPA_TRANSP.
  Optisch identisch, spart LVGL beim Scrollen aber das Zeichnen und Mischen
  der darunterliegenden Ebenen.
- Neuer Schalter WS7_PERF_MONITOR schaltet LV_USE_SYSMON/LV_USE_PERF_MONITOR
  ein und blendet Bilder je Sekunde und Prozessorlast ein. Vorgabe 0, mit 1
  gegengebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
2026-09-01 14:45:33 +02:00
thomas 117715dc3b Merge pull request 'fix(P4): Tipp auf einen Knopf löst nicht mehr mehrfach aus (1.6.9)' (#37) from fix/touch-mehrfachausloesung into main 2026-09-01 14:19:51 +02:00
raw-designsandClaude Opus 5 328dc06983 fix(P4): Tipp auf einen Knopf löst nicht mehr mehrfach aus (1.6.9)
Der GT9271 lässt gelegentlich einen Messzyklus aus oder liefert ein
unplausibles Paket. Der Hersteller-Treiber kann "gerade nichts Neues" nicht
von "Finger weg" unterscheiden und meldet beides als losgelassen. Seit die
Abtastrate mit 1.6.8 von 33 auf 16 ms gestiegen ist, wurde daraus sichtbar
Drücken-Loslassen-Drücken-Loslassen.

Vor den Treiber ist jetzt ein eigener get_xy-Aufsatz gesetzt: Er verwirft
unplausible Rohwerte und hält den letzten gültigen Punkt noch
WS7_TOUCH_HOLD_MS lang (Vorgabe 40 ms). Der Aufsatz wird zur Laufzeit in das
Touch-Handle eingehängt, die Herstellerdateien bleiben unverändert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
2026-09-01 14:18:28 +02:00
thomas 480708c992 Merge pull request 'perf(P4): Scrollen am Waveshare-Panel flüssiger (1.6.8)' (#36) from perf/scrollen-taktrate into main 2026-09-01 14:02:46 +02:00
raw-designsandClaude Opus 5 9a0761f6da perf(P4): Scrollen am Waveshare-Panel flüssiger (1.6.8)
LV_DEF_REFR_PERIOD steuert nicht nur die Bildrate, sondern auch die
Abtastrate des Touch und die Schrittweite von Animationen. Mit 33 ms waren
das 30 Schritte je Sekunde - beim Ziehen mit dem Finger sichtbar ruckelig.

Für das Waveshare-Panel jetzt 16 ms, passend zu dessen 60 Hz. Kommt das
Zeichnen nicht hinterher, wird ein Bild später fertig; kaputt geht nichts.
Die JC-Panels bleiben unverändert bei 33 ms.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
2026-09-01 14:01:23 +02:00
thomas e6c09b7a9a Merge pull request 'fix(P4): Menü-Knopf fängt Tipps auch knapp daneben ab (1.6.7)' (#35) from fix/menue-knopf-trefferflaeche into main 2026-09-01 13:49:17 +02:00
raw-designsandClaude Opus 5 4fa0c81087 fix(P4): Menü-Knopf fängt Tipps auch knapp daneben ab (1.6.7)
Eine Messung mit WS7_TOUCH_DEBUG hat gezeigt, dass die Touch-Zuordnung stimmt:
Der Tipp auf den Menü-Knopf landete bei X=66/Y=27, der Knopf liegt aber bei
X 8..56. Mit 48x36 Pixeln ist er auf dem 7-Zoll-Panel ein sehr kleines Ziel.

lv_obj_set_ext_click_area vergrößert die Trefferfläche um 20 Pixel, ohne den
Knopf optisch zu ändern. Die Vergrößerung wirkt nur innerhalb der Kopfleiste,
weil diese ihre Kinder beschneidet - dem Seiteninhalt darunter wird nichts
weggenommen, und bei offenem Menü liegt ohnehin der Vorhang darüber.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
2026-09-01 13:47:54 +02:00
thomas 04eb77fb2d Merge pull request 'feat(P4): Touch-Messausgabe zum Einmessen (1.6.6)' (#34) from diag/touch-einmessen into main 2026-09-01 13:25:39 +02:00
raw-designsandClaude Opus 5 7878f1bafd feat(P4): Touch-Messausgabe zum Einmessen (1.6.6)
Der Menü-Knopf oben links reagiert am Waveshare-Panel nicht. Ob der Touch die
48x36 Pixel grosse Flaeche in der 44 Pixel hohen Kopfleiste ueberhaupt trifft,
liess sich bisher nicht nachsehen.

WS7_TOUCH_DEBUG in pins_config.h gibt jeden Berührpunkt roh und umgerechnet
über esp_rom_printf aus, also auch bei Core-Debug-Level "none". Vorgabe 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
2026-09-01 13:24:18 +02:00
thomas 60bb859fc9 Merge pull request 'fix(P4): Menü-Vorhang wieder öffenbar, RGB888 bleibt Vorgabe (1.6.5)' (#33) from fix/waveshare-vollbild-neuzeichnen into main 2026-09-01 13:14:52 +02:00
raw-designsandClaude Opus 5 e8fdc60fea fix(P4): Menü-Vorhang wieder öffenbar, RGB888 bleibt Vorgabe (1.6.5)
Zwei der drei Tempo-Maßnahmen aus 1.6.4 haben sich am Gerät als untauglich
erwiesen und stehen wieder auf ihrem alten Wert:

- WS7_COLOR_BITS = 24: Die Bridge dieses Panels nimmt kein RGB565 an.
- WS7_PARTIAL_REFRESH = 0: Der Menü-Vorhang ist halbtransparent und wird in
  den gerade aktiven Bildpuffer eingemischt. Die nächste Zustandsmeldung der
  S3 zeichnet in den zweiten Puffer, der ihn nie bekommen hat - der Vorhang
  war damit sofort wieder weg und der Knopf schien wirkungslos. Nutzbar wäre
  der Modus erst, wenn der LVGL-Port die geänderten Bereiche zwischen beiden
  Puffern abgleicht.

Beide bleiben als Schalter erhalten, mit Notiz woran sie gescheitert sind.
WS7_PARALLEL_RENDER bleibt eingeschaltet - von den drei Maßnahmen trägt nur
diese.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QoLDQeUh1dCQz7yYZVb4Y
2026-09-01 13:13:28 +02:00
thomas 8b7978507c Merge pull request 'perf(P4): Darstellung am Waveshare-Panel beschleunigen (1.6.4)' (#32) from perf/waveshare-darstellung-beschleunigen into main 2026-09-01 12:52:55 +02:00
7 changed files with 241 additions and 20 deletions
+76
View File
@@ -1,3 +1,79 @@
Version 1.6.11:
- Fehlerbehebung: Nach einem Reset des P4 blieb das Bild schwarz, während die
Hintergrundbeleuchtung brannte; erst ein erneutes Flashen half. Die Bridge des
Waveshare-Panels hat keine Reset-Leitung und hängt an Dauerstrom - ein Reset des P4
setzt sie also nicht zurück, ihre Register standen noch auf den Werten der vorigen
Sitzung. Der P4 baut seine DSI-Strecke aber komplett neu auf, und ein frischer DSI-Start
auf einer bereits laufenden Bridge liefert kein Bild. Beim Flashen wird die Versorgung
getrennt, deshalb war der Fehler dort nicht zu sehen.
- Der Start schaltet die Bridge jetzt zuerst definiert ab (Beleuchtung, dann Ausgabe,
dann Grundregister), wartet WS7_BRIDGE_RESET_MS und fährt sie erst danach hoch. Der
Wert steht in pins_config.h (Vorgabe 120 ms) und ist die erste Stellschraube, falls
nach einem Reset doch einmal ein schwarzes Bild auftaucht.
Version 1.6.10:
- WS7_PARTIAL_REFRESH ist jetzt auch im Auslieferungsstand 1. Am Gerät geprüft: kein
Flackern, und der Gewinn ist der größte der drei Tempo-Maßnahmen - vor allem während
eines Bezugs, wo die Zeitanzeige zehnmal je Sekunde weiterläuft.
- Der Hintergrund der Seiten ist deckend statt durchsichtig. Sichtbar ändert sich nichts,
die Ebenen darunter haben dieselbe Farbe; LVGL muss sie beim Scrollen aber nicht mehr
mitzeichnen und durchmischen.
- Neuer Schalter WS7_PERF_MONITOR in pins_config.h: blendet unten rechts Bilder je Sekunde
und Prozessorlast ein. Damit lässt sich beantworten, ob weitere Mühe beim Zeichnen
überhaupt noch etwas bringt, statt ins Blaue zu optimieren.
Version 1.6.9:
- Fehlerbehebung: Ein Tipp auf einen Knopf löste oft mehrfach aus. Der GT9271 lässt
gelegentlich einen Messzyklus aus oder liefert ein unplausibles Paket; der
Hersteller-Treiber kann "gerade nichts Neues" nicht von "Finger weg" unterscheiden und
meldet beides als losgelassen. Seit die Oberfläche mit 1.6.8 doppelt so oft abtastet,
wurde daraus sichtbar Drücken-Loslassen-Drücken-Loslassen.
- Vor den Treiber ist deshalb ein Filter gesetzt: Er verwirft unplausible Rohwerte und hält
den letzten gültigen Berührpunkt noch WS7_TOUCH_HOLD_MS lang (Vorgabe 40 ms). Losgelassen
wird erst gemeldet, wenn wirklich nichts mehr kommt. Der Wert steht in pins_config.h;
0 schaltet die Überbrückung ab. Zu groß gewählt verzögert er das Loslassen und dämpft
den Schwung beim Wischen.
- Der Filter hängt sich zur Laufzeit in den Treiber ein, die Herstellerdateien bleiben
unverändert.
Version 1.6.8:
- Scrollen und Wischen laufen am Waveshare-Panel flüssiger: LVGL rechnet dort jetzt im
16-Millisekunden-Takt statt alle 33 ms. Dieser Wert steuert nicht nur die Bildrate,
sondern auch, wie oft der Touch abgetastet und wie fein eine Animation gerechnet wird -
mit 30 Schritten je Sekunde war vor allem das Ziehen mit dem Finger sichtbar ruckelig.
Das Panel läuft mit 60 Hz, mehr als 16 ms bringt also nichts.
- Kommt das Zeichnen einmal nicht hinterher, wird ein Bild später fertig; kaputt geht
dabei nichts. Die JC-Panels bleiben bei 33 ms.
Version 1.6.7:
- Der Menue-Knopf oben links fängt Tipps jetzt auch knapp daneben ab. Mit 48x36 Pixeln war
er auf dem 7-Zoll-Panel ein sehr kleines Ziel; gemessen wurde ein Fehlgriff von rund
10 Pixeln neben der Fläche, weshalb sich das Menü scheinbar nicht öffnen ließ. Optisch
bleibt der Knopf unverändert, die Trefferfläche wächst um 20 Pixel nach allen Seiten.
Sie wirkt nur innerhalb der Kopfleiste - dem Seiteninhalt darunter wird nichts genommen.
- Die Touch-Zuordnung selbst war korrekt: Eine Messung mit WS7_TOUCH_DEBUG hat gezeigt,
dass Achsen und Spiegelung stimmen.
Version 1.6.6:
- Neuer Schalter WS7_TOUCH_DEBUG in pins_config.h: Auf 1 gesetzt, gibt jeder Berührpunkt
seine Rohwerte und die daraus errechnete Bildposition auf der seriellen Konsole aus.
Gedacht zum Einmessen des Touch, wenn Bedienelemente nicht reagieren - insbesondere am
oberen Bildrand, wo die 44 Pixel hohe Kopfleiste sitzt.
Version 1.6.5:
- Zwei der drei Tempo-Maßnahmen aus 1.6.4 haben sich am Gerät als untauglich erwiesen und
stehen wieder auf ihrem alten Wert. Sie bleiben als Schalter erhalten, mit Notiz, woran
sie gescheitert sind.
* WS7_COLOR_BITS wieder 24: Die Bridge dieses Panels nimmt kein RGB565 an, mit 16 Bit
kommt kein brauchbares Bild.
* WS7_PARTIAL_REFRESH wieder 0: Der Menü-Vorhang ließ sich nicht mehr öffnen. Er ist
halbtransparent und wird deshalb in den gerade aktiven Bildpuffer eingemischt; die
nächste Zustandsmeldung der S3 zeichnet aber in den zweiten Puffer, der ihn nie
bekommen hat - der Vorhang war also sofort wieder weg. Nutzbar wäre der Modus erst,
wenn der LVGL-Port die geänderten Bereiche zwischen beiden Puffern abgleicht.
- WS7_PARALLEL_RENDER bleibt eingeschaltet: LVGL zeichnet weiterhin mit zwei Threads auf
beiden Prozessorkernen. Von den drei Maßnahmen trägt nur diese.
Version 1.6.4:
- Waveshare 7" (H): Drei Maßnahmen gegen die träge Bedienung am großen Panel. 1280x720
sind 2,4-mal so viele Pixel wie beim 4,3-Zöller, und bis 1.6.3 wurde bei jeder Änderung
+15 -6
View File
@@ -44,13 +44,13 @@ Vendor-Pakete: 4,3" im Ordner `JC4880P443C_I_W/`, 7,0" im Repo-Ordner
| Haupt-MCU (UI) | ESP32-P4 | ESP32-P4 | ESP32-P4 (32 MB PSRAM, 32 MB Flash) |
| WLAN/BT (hier ungenutzt) | ESP32-C6 | ESP32-C6 | — (kein Funkmodul) |
| Display | ST7701, 480×800 IPS, MIPI-DSI | JD9165, 1024×600 IPS, MIPI-DSI | 1280×720 IPS, MIPI-DSI 2 Lanes über Waveshare-Bridge |
| Farbformat | RGB565 | RGB565 | RGB565 oder RGB888, `WS7_COLOR_BITS` |
| Farbformat | RGB565 | RGB565 | **RGB888** — die Bridge nimmt kein RGB565 (geprüft) |
| LVGL-Ausrichtung | Rotation **270°** (PPA) → 800×480 | **keine** Rotation, nativ 1024×600 | **keine** Rotation, nativ 1280×720 |
| Touch | GT911, I²C SDA=GPIO7 / SCL=GPIO8 | GT911, I²C SDA=GPIO7 / SCL=GPIO8 | **GT9271** (I²C-Adresse **0x14**), SDA=GPIO7 / SCL=GPIO8 |
| 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 | 2 × 1,8 MB ≈ 3,7 MB PSRAM (RGB565, Teil-Neuzeichnen) |
| Framebuffer | 3 × 750 KB ≈ 2,3 MB PSRAM | 3 × 1,2 MB ≈ 3,6 MB PSRAM | 3 × 2,8 MB ≈ 8,3 MB PSRAM |
| 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** |
@@ -67,6 +67,11 @@ Das Panel hängt hinter einer Waveshare-Bridge und braucht **keinen** Hersteller
- Reihenfolge: Bridge-Grundinitialisierung (`C0`/`C2`/`AC`) → DSI → DCS `MADCTL`/`Sleep Out`/
`Display On` → DPI-Start → **erst dann** Hintergrundbeleuchtung. Wird das Licht früher
eingeschaltet, blitzt beim Start Bildrauschen auf.
- **Nach einem Reset:** Die Bridge hat keine Reset-Leitung und hängt an Dauerstrom — ein
Reset des P4 setzt sie **nicht** zurück. Der Bringup schaltet sie deshalb zuerst
definiert ab, wartet `WS7_BRIDGE_RESET_MS` und fährt sie dann neu hoch. Ohne das trifft
ein frischer DSI-Start auf eine noch laufende Bridge: Bild schwarz, Beleuchtung an.
Nach dem Flashen fällt das nicht auf, weil dabei die Versorgung getrennt wird.
- **Einbaulage:** `WS7_ROTATE_180` in [`pins_config.h`](pins_config.h) dreht Bild **und**
Touch um 180°, falls das Panel auf dem Kopf montiert wird. Vorgabe ist **0** — in der
jetzigen Einbaulage steht das Bild richtig herum. Die Drehung macht der
@@ -81,11 +86,15 @@ Das Panel hängt hinter einer Waveshare-Bridge und braucht **keinen** Hersteller
[`pins_config.h`](pins_config.h) halten die Bedienung flüssig; jeder ist einzeln
zurückstellbar, falls er Ärger macht:
| Schalter | Vorgabe | Wirkung | Wenn es klemmt |
| Schalter | Vorgabe | Wirkung | Stand am Gerät |
|---|---|---|---|
| `WS7_COLOR_BITS` | `16` | RGB565 halbiert die Datenmenge je Bild gegenüber RGB888. Sichtbar nur in den dunklen Verläufen der Rundanzeige. | Bild falschfarbig oder dunkel → die Bridge will kein RGB565, auf `24` stellen |
| `WS7_PARTIAL_REFRESH` | `1` | Nur geänderte Bildbereiche neu zeichnen statt jedes Mal des ganzen Bildes (LVGL-Direct-Mode, zwei Puffer). Größter Gewinn. | Flackern in Flächen, die selten neu gezeichnet werden → auf `0` |
| `WS7_PARALLEL_RENDER` | `1` | LVGL zeichnet mit zwei Threads auf beiden Prozessorkernen. | P4 startet nicht mehr (zwei zusätzliche Stacks im knappen internen RAM) → zuerst hier auf `0` |
| `WS7_COLOR_BITS` | `24` | `16` (RGB565) würde die Datenmenge je Bild halbieren. | **Geht an diesem Panel nicht** — die Bridge nimmt nur RGB888 |
| `WS7_PARTIAL_REFRESH` | `0` | `1` zeichnet nur geänderte Bereiche neu (LVGL-Direct-Mode, zwei wechselnde Puffer). Wäre der größte Gewinn. | **Geht so nicht** — der halbtransparente Menü-Vorhang landet nur in einem der beiden Puffer und ist sofort wieder weg |
| `WS7_PARALLEL_RENDER` | `1` | LVGL zeichnet mit zwei Threads auf beiden Prozessorkernen. | Aktiv |
> Damit `WS7_PARTIAL_REFRESH` nutzbar würde, müsste der LVGL-Port die geänderten Bereiche
> zwischen beiden Puffern abgleichen. Die Maschinerie dafür liegt in `lvgl_port_v9.c`,
> wird aber nur bei gedrehter Ausgabe übersetzt.
Die Farbtiefe muss für Sketch **und** LVGL-Bibliothek dieselbe sein; `lv_conf.h` liest
`WS7_COLOR_BITS` deshalb direkt aus `pins_config.h`.
+91 -2
View File
@@ -29,6 +29,7 @@
#include "esp_cache.h"
#include "esp_heap_caps.h"
#include "esp_rom_sys.h"
#include "esp_timer.h"
#include "esp_ldo_regulator.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_ops.h"
@@ -109,8 +110,16 @@ static void ws7_bridge_write(uint8_t reg, uint8_t value)
i2c_master_transmit(s_bridge_handle, buf, sizeof(buf), 100);
}
// Bridge am I2C-Bus anmelden und Grundinitialisierung schreiben. Muss VOR dem
// DSI-Bringup laufen; die Hintergrundbeleuchtung bleibt dabei noch aus.
// Bridge in einen definierten Grundzustand bringen und neu initialisieren.
//
// WICHTIG - der Grund fuer das Abschalten am Anfang: Die Bridge hat keine Reset-Leitung
// und haengt an Dauerstrom. Ein Reset des P4 setzt sie also NICHT zurueck; ihre Register
// stehen noch so, wie die vorige Sitzung sie hinterlassen hat. Der P4 baut seine
// DSI-Strecke aber komplett neu auf. Trifft ein frischer DSI-Start auf eine bereits
// laufende Bridge, bleibt das Bild schwarz, waehrend die Hintergrundbeleuchtung brennt.
// Nach dem Flashen faellt das nicht auf, weil dabei die Versorgung getrennt wird.
//
// Deshalb erst ausschalten (Beleuchtung, dann Bridge), kurz warten, dann normal hochfahren.
static void ws7_bridge_pre_init(void)
{
i2c_device_config_t dev_cfg = {
@@ -122,9 +131,22 @@ static void ws7_bridge_pre_init(void)
s_bridge_handle = NULL;
return;
}
// --- definierter Aus-Zustand (umgekehrte Reihenfolge zum Einschalten) ---
ws7_bridge_write(0xAB, 0xFF); // Helligkeit 0
ws7_bridge_write(0xAA, 0x01); // uebernehmen
ws7_bridge_write(0xAD, 0x00); // Bridge-Ausgabe aus
vTaskDelay(pdMS_TO_TICKS(20));
ws7_bridge_write(0xAC, 0x00);
ws7_bridge_write(0xC2, 0x00);
ws7_bridge_write(0xC0, 0x00);
vTaskDelay(pdMS_TO_TICKS(WS7_BRIDGE_RESET_MS));
// --- Grundinitialisierung wie im Linux-Treiber ---
ws7_bridge_write(0xC0, 0x01);
ws7_bridge_write(0xC2, 0x01);
ws7_bridge_write(0xAC, 0x01);
vTaskDelay(pdMS_TO_TICKS(20));
}
void jc_backlight_init(void)
@@ -184,6 +206,63 @@ IRAM_ATTR static bool on_vsync(esp_lcd_panel_handle_t panel,
}
#if JC_PANEL_TYPE == WS_PANEL_7H
// ------------------------------------------------------------------------------------
// Aussetzer des GT9271 ueberbruecken
//
// Der Controller laesst gelegentlich einen Messzyklus aus und liefert ab und zu ein
// unplausibles Paket - die Werks-Testskizze hat solche Pakete ebenfalls verworfen. Der
// Hersteller-Treiber kann "gerade nichts Neues" nicht von "Finger weg" unterscheiden und
// meldet beides als losgelassen. Seit die Oberflaeche doppelt so oft abtastet, faellt das
// auf: Aus einem Tipp wird Druecken-Loslassen-Druecken-Loslassen, der Knopf loest also
// mehrfach aus.
//
// Deshalb liegt hier ein eigener get_xy-Aufsatz vor dem Treiber: Er verwirft unplausible
// Rohwerte und haelt den letzten gueltigen Punkt kurz fest. Losgelassen wird erst
// gemeldet, wenn WS7_TOUCH_HOLD_MS lang wirklich nichts mehr kam.
// ------------------------------------------------------------------------------------
static bool (*s_touch_get_xy_orig)(esp_lcd_touch_handle_t, uint16_t *, uint16_t *,
uint16_t *, uint8_t *, uint8_t) = NULL;
static uint16_t s_touch_last_x = 0;
static uint16_t s_touch_last_y = 0;
static int64_t s_touch_last_us = 0;
static bool s_touch_down = false;
static bool ws7_touch_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y,
uint16_t *strength, uint8_t *point_num, uint8_t max_point_num)
{
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.
if (got && *point_num > 0 &&
(x[0] > WS7_TOUCH_RAW_X_MAX || y[0] > WS7_TOUCH_RAW_Y_MAX)) {
got = false;
*point_num = 0;
}
if (got && *point_num > 0) {
s_touch_last_x = x[0];
s_touch_last_y = y[0];
s_touch_last_us = now;
s_touch_down = true;
return true;
}
#if WS7_TOUCH_HOLD_MS > 0
if (s_touch_down && (now - s_touch_last_us) < ((int64_t)WS7_TOUCH_HOLD_MS * 1000)) {
x[0] = s_touch_last_x;
y[0] = s_touch_last_y;
if (strength) strength[0] = 0;
*point_num = 1;
return true;
}
#endif
s_touch_down = false;
return false;
}
// Der GT9271 des Waveshare-Panels meldet im Hochformat (Roh-X 0..720, Roh-Y 0..1280),
// das Bild laeuft aber im Querformat 1280x720. Achsentausch (und bei Bedarf Spiegelung)
// deshalb ueber den process_coordinates-Hook, der VOR den swap/mirror-Flags von
@@ -211,6 +290,10 @@ static void ws7_touch_map(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y,
// Bild wird um 180 Grad gedreht ausgegeben -> Touch muss mitdrehen.
px = (uint16_t)(LCD_H_RES - 1 - px);
py = (uint16_t)(LCD_V_RES - 1 - py);
#endif
#if WS7_TOUCH_DEBUG
esp_rom_printf("[Touch] roh X=%u Y=%u -> Bild X=%u Y=%u\n",
(unsigned)x[i], (unsigned)y[i], (unsigned)px, (unsigned)py);
#endif
x[i] = px;
y[i] = py;
@@ -463,6 +546,12 @@ bool jc_board_bringup(void)
esp_rom_printf("[Panel] Touch-Controller nicht gefunden - Anzeige laeuft ohne Bedienung.\n");
tp_handle = NULL;
}
#if JC_PANEL_TYPE == WS_PANEL_7H
if (tp_handle) { // Aussetzer-Filter vor den Treiber haengen
s_touch_get_xy_orig = tp_handle->get_xy;
tp_handle->get_xy = ws7_touch_get_xy;
}
#endif
lvgl_port_interface_t interface =
(dpi_config.flags.use_dma2d) ? LVGL_PORT_INTERFACE_MIPI_DSI_DMA
+1 -1
View File
@@ -126,7 +126,7 @@
// -------------------------------------------------------------------------------------
// Firmware
// -------------------------------------------------------------------------------------
#define DISPLAY_FW_VERSION "1.6.4" // Firmware-Stand der P4-Display-Steuerung (Info-Seite)
#define DISPLAY_FW_VERSION "1.6.11" // Firmware-Stand der P4-Display-Steuerung (Info-Seite)
// -------------------------------------------------------------------------------------
// Protokoll
+16 -1
View File
@@ -91,7 +91,17 @@
*====================*/
/*Default display refresh, input device read and animation step period.*/
/* Der Wert bestimmt nicht nur die Bildrate, sondern auch, wie oft der Touch abgetastet
* und wie fein eine Animation gerechnet wird. 33 ms sind 30 Schritte je Sekunde - beim
* Ziehen mit dem Finger deutlich als Stocken zu sehen. Das Waveshare-Panel laeuft mit
* 60 Hz, deshalb dort 16 ms; mehr als das Panel zeigen kann, bringt nichts. Kommt das
* Zeichnen nicht hinterher, wird es einfach seltener fertig - kaputt geht dabei nichts.
* Die JC-Panels bleiben bei 33 ms, damit sich ihr Verhalten nicht aendert. */
#if JC_PANEL_TYPE == WS_PANEL_7H
#define LV_DEF_REFR_PERIOD 16 /*[ms]*/
#else
#define LV_DEF_REFR_PERIOD 33 /*[ms]*/
#endif
/*Default Dot Per Inch. Used to initialize default sizes such as widgets sized, style paddings.
*(Not so important, you can adjust it to modify default sizes and spaces)*/
@@ -905,14 +915,19 @@
#define LV_USE_SNAPSHOT 0
/*1: Enable system monitor component*/
/* Nur fuer die Messeinblendung des Waveshare-Panels, siehe WS7_PERF_MONITOR. */
#if (JC_PANEL_TYPE == WS_PANEL_7H) && WS7_PERF_MONITOR
#define LV_USE_SYSMON 1
#else
#define LV_USE_SYSMON 0
#endif
#if LV_USE_SYSMON
/*Get the idle percentage. E.g. uint32_t my_get_idle(void);*/
#define LV_SYSMON_GET_IDLE lv_timer_get_idle
/*1: Show CPU usage and FPS count
* Requires `LV_USE_SYSMON = 1`*/
#define LV_USE_PERF_MONITOR 0
#define LV_USE_PERF_MONITOR 1
#if LV_USE_PERF_MONITOR
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
+32 -9
View File
@@ -16,19 +16,22 @@
// 1280x720 ist gegenueber den JC-Panels ein Vielfaches an Pixeln. Die drei Schalter
// senken die Last und lassen sich einzeln zurueckstellen, falls einer Aerger macht.
//
// WS7_COLOR_BITS 16 = RGB565: halbe Datenmenge je Bild, dafuer 65.000 statt
// 16,7 Mio. Farben (sichtbar nur in den dunklen Verlaeufen der
// Rundanzeige). 24 = RGB888 wie bis 1.6.3.
// ACHTUNG: Nimmt die Bridge des Panels kein RGB565 an, bleibt
// das Bild falschfarbig oder aus -> wieder auf 24 stellen.
// WS7_COLOR_BITS 24 = RGB888. GEPRUEFT: Die Bridge dieses Panels nimmt KEIN RGB565
// an - mit 16 kommt kein brauchbares Bild. Einstellbar bleibt es
// nur, weil andere Waveshare-Panels an derselben Firmware
// haengen koennten.
// WS7_PARTIAL_REFRESH 1 = nur geaenderte Bildbereiche neu zeichnen statt jedes Mal des
// gesamten Bildes. Groesster Tempogewinn. Am 4,3-Zoll-Panel
// hatte dieser Modus geflackert; tritt das hier auch auf, auf 0.
// gesamten Bildes (LVGL-Direct-Mode, zwei wechselnde Puffer).
// Groesster Tempogewinn, besonders waehrend eines Bezugs: Die
// Zeitanzeige laeuft zehnmal je Sekunde weiter, und mit 0 wuerde
// dafuer jedes Mal das ganze Bild neu gezeichnet. Am Geraet
// geprueft, kein Flackern - am 4,3-Zoll-Panel hatte derselbe
// Modus dagegen geflackert.
// WS7_PARALLEL_RENDER 1 = LVGL zeichnet mit zwei Threads auf beiden Prozessorkernen.
// Kostet zwei zusaetzliche Task-Stacks im knappen internen RAM;
// startet der P4 nicht mehr, hier zuerst auf 0 stellen.
// -------------------------------------------------------------------------------------
#define WS7_COLOR_BITS 16
#define WS7_COLOR_BITS 24
#define WS7_PARTIAL_REFRESH 1
#define WS7_PARALLEL_RENDER 1
@@ -111,6 +114,12 @@
// nicht bekannt; die 180-Grad-Drehung macht deshalb der PPA (WS7_ROTATE_180).
#define WS7_MADCTL 0x00
// So lange bleibt die Bridge beim Start stromlos geschaltet, bevor sie neu
// initialisiert wird. Sie hat keine Reset-Leitung und ueberlebt einen Reset des P4;
// ohne diese Pause trifft ein frischer DSI-Start auf eine noch laufende Bridge und das
// Bild bleibt schwarz. Bei schwarzem Bild nach Reset zuerst diesen Wert erhoehen.
#define WS7_BRIDGE_RESET_MS 120
// Der GT9271 meldet im Hochformat: Roh-X 0..720, Roh-Y 0..1280. Fuer das Querformat
// werden die Achsen getauscht. Die Spiegelung geschieht VOR dem Tausch, also noch auf den
// Rohwerten: Roh-X wird zur Bildschirmhoehe, Roh-Y zur Bildschirmbreite.
@@ -123,6 +132,20 @@
#define WS7_TOUCH_MIRROR_RAW_X 1
#define WS7_TOUCH_MIRROR_RAW_Y 0
// Zeigt unten rechts Bilder je Sekunde und Prozessorlast ein. Nur zum Messen gedacht:
// Der Wert sagt, ob sich weitere Muehe beim Zeichnen ueberhaupt lohnt.
#define WS7_PERF_MONITOR 0
// Zum Einmessen des Touch: 1 gibt jeden Beruehrpunkt roh und umgerechnet auf der
// seriellen Konsole aus. Danach wieder auf 0, sonst laeuft das Log dauernd mit.
#define WS7_TOUCH_DEBUG 0
// So lange gilt eine Beruehrung nach dem letzten gueltigen Messwert noch als anliegend.
// Ueberbrueckt Aussetzer des GT9271, die sonst als Loslassen durchgehen und einen Tipp in
// mehrere Klicks zerlegen. 0 schaltet die Ueberbrueckung ab. Nicht zu gross waehlen: Der
// Wert verzoegert das Loslassen und daempft dadurch den Schwung beim Wischen.
#define WS7_TOUCH_HOLD_MS 40
#elif JC_PANEL_TYPE == JC_PANEL_70
#define LCD_H_RES 1024
@@ -131,7 +154,7 @@
#define LCD_RST 27
#define LCD_LED 23
#else
#elsealle
#define LCD_H_RES 480
#define LCD_V_RES 800
+10 -1
View File
@@ -453,7 +453,11 @@ static lv_obj_t* make_page(lv_obj_t* parent) {
lv_obj_t* p = lv_obj_create(parent);
lv_obj_set_size(p, LV_PCT(100), LV_PCT(100));
lv_obj_set_pos(p, 0, 0);
lv_obj_set_style_bg_opa(p, LV_OPA_TRANSP, 0);
// Deckend in der Hintergrundfarbe statt durchsichtig. Sieht identisch aus - die Ebenen
// darunter haben dieselbe Farbe -, erspart LVGL beim Scrollen aber, sie mitzuzeichnen
// und durchzumischen.
lv_obj_set_style_bg_color(p, COL_BG, 0);
lv_obj_set_style_bg_opa(p, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(p, 0, 0);
lv_obj_set_style_pad_all(p, 8, 0);
lv_obj_set_style_pad_row(p, 6, 0);
@@ -3171,6 +3175,11 @@ void ui_init(ProtocolClient* client) {
lv_obj_t* burger = th_button(header, LV_SYMBOL_LIST, COL_CARD2, COL_TEXT);
lv_obj_set_size(burger, 48, 36);
// Der Knopf bleibt optisch klein, faengt Tipps aber auch knapp daneben ab. 48x36 Pixel
// sind auf dem 7-Zoll-Panel ein sehr kleines Ziel; gemessen wurde ein Fehlgriff von
// rund 10 Pixeln. Die Vergroesserung wirkt nur innerhalb der Kopfleiste - darunter
// beschneidet sie die Leiste selbst, sodass dem Seiteninhalt nichts weggenommen wird.
lv_obj_set_ext_click_area(burger, 20);
lv_obj_add_event_cb(burger, hamburger_cb, LV_EVENT_CLICKED, nullptr);
g_hdrTitle = lv_label_create(header);