# JC-Touch-Display-Firmware (ESP32-P4) Client-Firmware für die Guition-Smart-Displays **JC4880P443C-I-W (4,3")** und **JC1060P470C-I-W (7,0")**, die als UART-Touch-Bedienung für die Dual-PID-Siebträgersteuerung dienen. Beide Panels teilen sich denselben Sketch; das Zielpanel wird über **`JC_PANEL_TYPE`** in [`config.h`](config.h) gewählt. Die **Hauptplatine (ESP32-S3, `Dual_PID_FastHeatUp.ino`)** bleibt die Steuerzentrale inkl. WLAN/Webinterface. Dieses Display ist ein **reiner UART-Client**: es empfängt den Zustand und sendet Bedienkommandos. Protokoll: siehe [`../Doku/JC-Display_UART-Protokoll.md`](../Doku/JC-Display_UART-Protokoll.md). ## Panel-Auswahl In [`config.h`](config.h): ```c #define JC_PANEL_TYPE JC_PANEL_43 // 4,3" JC4880P443C-I-W (Vorgabe) #define JC_PANEL_TYPE JC_PANEL_70 // 7,0" JC1060P470C-I-W ``` Alternativ ohne Quelltextänderung per Compiler-Flag `-DJC_PANEL_TYPE=70`. Der Schalter steuert Panel-Treiber, Auflösung, Rotation, LCD-Reset-Pin und die Touch-Skalierung; UI, Protokoll und Pinbelegung des UART bleiben identisch. ## Hardware Vendor-Pakete: 4,3" im Ordner `JC4880P443C_I_W/`, 7,0" im Repo-Ordner `../JC_Display_Firmware_7zoll/`. | Komponente | 4,3" JC4880P443C-I-W | 7,0" JC1060P470C-I-W | |---|---|---| | Haupt-MCU (UI) | ESP32-P4 | ESP32-P4 | | WLAN/BT (hier ungenutzt) | ESP32-C6 | ESP32-C6 | | Display | ST7701, 480×800 IPS, MIPI-DSI | JD9165, 1024×600 IPS, MIPI-DSI | | LVGL-Ausrichtung | Rotation **270°** (PPA) → 800×480 | **keine** Rotation, nativ 1024×600 | | Touch | GT911, I²C SDA=GPIO7 / SCL=GPIO8 | GT911, I²C SDA=GPIO7 / SCL=GPIO8 | | Touch-Rohkoordinaten | 480×800 (= Panelraster) | **800×480** → wird auf 1024×600 skaliert | | LCD-Reset | GPIO5 | **GPIO27** | | Backlight | GPIO23 (LEDC-PWM) | GPIO23 (LEDC-PWM) | | Framebuffer (3×, RGB565) | 3 × 750 KB ≈ 2,3 MB PSRAM | 3 × 1,2 MB ≈ 3,6 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 | > Beim 7-Zöller ist die Expansion-IO **kein Stiftleisten-Header**, sondern eine > FPC-Buchse (1,0 mm Raster, 16-polig) — für die UART-Verdrahtung wird ein > FPC-Breakout/Adapterkabel gebraucht. Schaltplan: `../JC_Display_Firmware_7zoll/5-Schematic/4_CONN.png`. ## Verkabelung zur Hauptplatine (UART, gekreuzt) Für **beide** Panels dieselben P4-Pins (4,3": Header JP1, Schaltplan `JC4880P443C_I_W/5-Schematic/4_USB&IO.png` · 7,0": FPC-Buchse FPC4): ``` S3 GPIO43 (TX) ----> P4 GPIO31 (RX) (DISPLAY_UART_RX_PIN) S3 GPIO44 (RX) <---- P4 GPIO33 (TX) (DISPLAY_UART_TX_PIN) S3 GND ------ P4 GND ``` > Die rechte JP1-Spalte (`C6_U01TXD`/`C6_I10RXD`/…) gehört zum **ESP32-C6** — nicht > verwenden. 3,3-V-Logik beidseitig → keine Pegelwandlung nötig. ## Projektstruktur (eigener Code) | Datei | Zweck | |---|---| | `JC_Display_Firmware.ino` | setup()/loop(), verdrahtet die Module | | `config.h` | Pins, UART, Protokoll-Parameter | | `machine_state.h` | Spiegel des `state`-Objekts der S3 | | `protocol_client.h/.cpp` | UART-Protokoll: hello/state/ack/profiles/… + Heartbeat | | `ui.h/.cpp` | LVGL-Dashboard (hardwareunabhängig) | | `display_hal.h/.cpp` | LVGL-/UI-Verdrahtung + Lock-Wrapper | | `board_bringup.c` | esp_lcd-Hardware-Bringup (C; nur bei `JC_USE_REAL_PANEL=1`) | ## Abhängigkeiten - **Arduino-ESP32** ≥ 3.1 (mit ESP32-P4-Support), Board: *ESP32P4 Dev Module*, **PSRAM aktiviert**. - **LVGL** 9.x + `lv_conf.h`. Tipp: die `lv_conf.h` aus dem Vendor-Beispiel (`JC4880P443C_I_W/1-Demo/arduino_examples/lvgl_v9_sw_rotation/lv_conf.h`) übernehmen und `LV_FONT_MONTSERRAT_40` aktivieren (große Temperaturanzeige). - **ArduinoJson** 7.x. ## Zwei Betriebsmodi (`JC_USE_REAL_PANEL` in `display_hal.h`) ### `0` = Stub-Modus (Standard) Kompiliert **ohne** Display-Treiber (eigenes Minimal-LVGL, rendert ins Leere). Ideal, um **Protokoll/UART/Logik** am Schreibtisch zu testen (Debug über USB-CDC `Serial`). Läuft auf jedem ESP32 mit LVGL+ArduinoJson. ### `1` = echte Hardware (Hersteller-BSP) `display_hal.cpp` baut auf der **erprobten Hersteller-Portierung** auf. Dazu folgende Dateien aus `JC4880P443C_I_W/1-Demo/arduino_examples/lvgl_v9_sw_rotation/` **in diesen Sketch-Ordner kopieren**: ``` pins_config.h lvgl_port_v9.h lvgl_port_v9.c src/lcd/ (esp_lcd_st7701*.c/.h + st7701_lcd.* sowie esp_lcd_jd9165.c/.h) src/touch/ (komplett: esp_lcd_touch*.c/.h, gt911_touch.*) ``` Diese Dateien liegen bereits im Sketch. `esp_lcd_jd9165.*` stammt aus dem 7-Zoll-Vendor-Paket (`../JC_Display_Firmware_7zoll/1-Demo/Demo_Arduino/1_2_Lvgl_V9/.../src/lcd/`); je nach `JC_PANEL_TYPE` wird nur einer der beiden Panel-Treiber eingebunden. Der Init-Ablauf (MIPI-DSI-PHY-LDO, ST7701 bzw. JD9165, GT911, LEDC-Backlight, `lvgl_port_init`) ist 1:1 aus dem Vendor-Beispiel `lvgl_sw_rotation.c` übernommen — nur der Demo-Aufruf (`lv_demo_widgets()`) wurde durch `ui_init()` ersetzt. Die Touch-Skalierung des 7-Zöllers hängt in `board_bringup.c` am `process_coordinates`-Hook von `esp_lcd_touch`, damit die Vendor-Datei `esp_lcd_touch_gt911.c` unverändert bleibt (im Vendor-Demo ist die Umrechnung direkt in den Treiber gepatcht). **Wichtig:** Im realen Modus läuft LVGL in einem **eigenen FreeRTOS-Task**. UI-Zugriffe aus der Arduino-`loop()` (z. B. `ui_update` bei jedem state-Push) sind daher in `hal_lock()/hal_unlock()` (= `lvgl_port_lock/unlock`) gekapselt — ist in der `.ino` bereits umgesetzt. ### Ausrichtung Das Dashboard ist **Querformat**. Beim 4,3-Zöller (physisch 480×800) wird das per LVGL-Rotation **270°** mit PPA-Beschleunigung erreicht → 800×480. Der 7-Zöller ist nativ 1024×600, dort steht die Rotation auf **0** und PPA ist abgeschaltet. Beides setzt `pins_config.h` automatisch anhand von `JC_PANEL_TYPE`. Das Layout arbeitet fast durchgehend mit `LV_PCT`/`LV_SIZE_CONTENT` und skaliert deshalb mit. Feste Pixelmaße (Rundinstrumente, Thermometer, Buttons) bleiben gleich groß — auf dem 7-Zöller entsteht dadurch mehr Luft. Die Schriftgrößen bleiben ebenfalls unverändert: 4,3" ≈ 213 dpi, 7,0" ≈ 170 dpi, gleiche Pixelhöhe wirkt dort physisch größer. ## Status **Fertig & hardwareunabhängig:** - Vollständiger UART-Protokoll-Client (v2): hello-Handshake, state-Parsing, ack/error, Profile, Heartbeat, Link-Timeout. - Dashboard: Live-Temperaturen Wasser/Dampf (ist/soll), Duty-Balken, Status-Banner (Farbe nach `statusKey`), Verbindungs- & WLAN-Anzeige, Bezugs-Timer, Bedien-Buttons. - Senden für `setPid`, `startAutotune`/`stopAutotune`, `getProfileDetails` vorhanden. **Board-Bringup:** auf die konkreten JC-Pins/Treiber gesetzt (ST7701 bzw. JD9165, GT911, Backlight, I²C) — sobald die BSP-Dateien kopiert und `JC_USE_REAL_PANEL=1` gesetzt ist, lauffähig. **Noch offen (UI-Ausbau):** weitere Screens — Einstellungen (Brew/Service/Sensor), Profil-Auswahl/-Editor, PID/AutoTune-Bedienung. ## Inbetriebnahme / Fehlersuche (Lessons learned) - **Stromversorgung:** Jedes Board **eigene** Versorgung. Zwischen P4 und S3 nur **GND + TX + RX** — **kein** 3V3/5V! Den S3 nicht über den 3V3-Header des Displays speisen (reicht nicht / Regler-Rückspeisung). - **Pins nach Silkscreen:** Die UART-Pads am Board nach Aufdruck **`GPIO50`/`GPIO51`** identifizieren, nicht nach Header-Pin-Nummern. - **S3-Seite:** muss mit `TOUCH_UART_ENABLED 1` geflasht sein und laufen. Da `Serial` (Debug) und der Touch-UART beide auf GPIO43/44 liegen, ggf. **„USB CDC On Boot: Enabled"** verwenden, damit der Debug-Port nicht die UART-Pins blockiert. ### Diagnose-Schalter (in `config.h`) - `SHOW_DEBUG_OVERLAY 1` → blendet unten ein grünes Panel ein: gesendete `hello`, empfangene Bytes/Zeilen, Parse-Fehler, letzte Rohzeile, Link-Status. - `UART_SELFTEST_INTERNAL_LOOPBACK 1` → legt TX chip-intern auf RX (ohne Draht/Pins). Läuft „RX byte" hoch, sind Firmware+UART ok → Problem liegt an Pins/Verkabelung. **Nach dem Test wieder auf 0!**