diff --git a/P4_Display_Firmware/Changelog.txt b/P4_Display_Firmware/Changelog.txt index 04cf8a3..e7542d6 100644 --- a/P4_Display_Firmware/Changelog.txt +++ b/P4_Display_Firmware/Changelog.txt @@ -1,3 +1,21 @@ +Version 1.6.13: +- Ursache des schwarzen Bildes gefunden: ein haengender I2C-Bus. Trifft ein Reset des P4 + mitten in eine laufende Uebertragung, bleibt der angesprochene Baustein in seiner + Bitausgabe stehen und haelt die Datenleitung dauerhaft auf Masse. Damit schlaegt jede + weitere Uebertragung fehl. Bridge und Touch-Controller haengen an Dauerstrom, weshalb + dieser Zustand jeden Reset und sogar das Flashen ueberlebt - nur echtes Stromabziehen + loest ihn. Die Folge: Die Bridge wird nie initialisiert, das Bild bleibt schwarz, und + weil sie ihre Register behaelt, brennt die Hintergrundbeleuchtung weiter. +- Vor dem Anlegen des I2C-Busses wird die Taktleitung jetzt von Hand getaktet, bis der + Baustein die Datenleitung freigibt, danach folgt eine Stopp-Bedingung. Das ist der in + der I2C-Spezifikation vorgesehene Weg und laeuft bei freiem Bus wirkungslos durch. +- Fehlerbehebung: Schreibzugriffe auf die Bridge liefen stillschweigend ins Leere. Genau + deshalb war der Fehler so schwer zu finden - das Bild blieb ohne jeden Hinweis schwarz. + Sie melden Fehler jetzt im Klartext. +- Fehlerbehebung: In pins_config.h stand seit 1.6.10 "#elsealle" statt "#else". Der + Tippfehler traf nur den Zweig des 4,3-Zoll-Panels, das damit nicht mehr uebersetzbar war. + Beide Panel-Varianten sind jetzt wieder gegengebaut. + Version 1.6.12: - Die Abschaltfolge für die Bridge aus 1.6.11 ist zurückgenommen. Sie hat den Fehler nicht behoben, sondern verschlimmert: Nach dem Nullsetzen von C0/C2/AC kam das Panel auch diff --git a/P4_Display_Firmware/board_bringup.c b/P4_Display_Firmware/board_bringup.c index 8bfdedb..87efda5 100644 --- a/P4_Display_Firmware/board_bringup.c +++ b/P4_Display_Firmware/board_bringup.c @@ -71,6 +71,68 @@ static i2c_master_bus_handle_t s_i2c_handle = NULL; +#if JC_PANEL_TYPE == WS_PANEL_7H +// ------------------------------------------------------------------------------------ +// Haengenden I2C-Bus befreien +// +// Trifft ein Reset des P4 mitten in eine laufende I2C-Uebertragung, bleibt der +// angesprochene Baustein in seiner Bitausgabe stehen und haelt die Datenleitung dauerhaft +// auf Masse. Der Bus ist damit tot: Jede weitere Uebertragung schlaegt fehl. Da Bridge und +// Touch-Controller an Dauerstrom haengen, ueberlebt dieser Zustand jeden Reset und sogar +// das Flashen - nur echtes Stromabziehen loest ihn. +// +// Folge: Die Bridge wird nie initialisiert, das Bild bleibt schwarz, und weil sie ihre +// Register behaelt, brennt die Hintergrundbeleuchtung weiter. Genau dieses Bild. +// +// Abhilfe ist der uebliche Weg aus der I2C-Spezifikation: Vor dem Anlegen des Busses die +// Taktleitung von Hand takten, bis der Baustein sein letztes Bit ausgegeben hat und die +// Datenleitung wieder loslaesst, danach eine Stopp-Bedingung erzeugen. +static void ws7_i2c_bus_recover(void) +{ + gpio_config_t io = { + .pin_bit_mask = BIT64(BSP_I2C_SDA) | BIT64(BSP_I2C_SCL), + .mode = GPIO_MODE_INPUT_OUTPUT_OD, // offener Kollektor, Zustand lesbar + .pull_up_en = GPIO_PULLUP_ENABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&io); + gpio_set_level(BSP_I2C_SDA, 1); + gpio_set_level(BSP_I2C_SCL, 1); + esp_rom_delay_us(10); + + if (gpio_get_level(BSP_I2C_SDA) != 0) { + return; // Bus frei - nichts zu tun + } + + esp_rom_printf("[Panel] I2C-Bus haengt - wird freigetaktet\n"); + + // Bis zu neun Takte: so viele braucht ein Baustein hoechstens, um ein angefangenes + // Byte samt Bestaetigungsbit zu Ende zu schieben. + for (int i = 0; i < 9 && gpio_get_level(BSP_I2C_SDA) == 0; i++) { + gpio_set_level(BSP_I2C_SCL, 0); + esp_rom_delay_us(5); + gpio_set_level(BSP_I2C_SCL, 1); + esp_rom_delay_us(5); + } + + // Stopp-Bedingung: Datenleitung geht bei hoher Taktleitung von Masse auf High. + gpio_set_level(BSP_I2C_SDA, 0); + esp_rom_delay_us(5); + gpio_set_level(BSP_I2C_SCL, 1); + esp_rom_delay_us(5); + gpio_set_level(BSP_I2C_SDA, 1); + esp_rom_delay_us(10); + + esp_rom_printf("[Panel] I2C-Bus nach Freitakten: %s\n", + gpio_get_level(BSP_I2C_SDA) ? "frei" : "weiterhin belegt"); + + // Pins wieder freigeben, damit der I2C-Treiber sie uebernehmen kann. + gpio_reset_pin(BSP_I2C_SDA); + gpio_reset_pin(BSP_I2C_SCL); +} +#endif // JC_PANEL_TYPE == WS_PANEL_7H + // Klartext-Meldung auf der seriellen Konsole. Bewusst esp_rom_printf: das laeuft auch bei // abgeschaltetem Core-Debug-Level und ohne Heap, also genau dann, wenn es darauf ankommt. #define BSP_STEP(call, what) \ @@ -108,7 +170,13 @@ static void ws7_bridge_write(uint8_t reg, uint8_t value) { if (s_bridge_handle == NULL) return; uint8_t buf[2] = { reg, value }; - i2c_master_transmit(s_bridge_handle, buf, sizeof(buf), 100); + esp_err_t err = i2c_master_transmit(s_bridge_handle, buf, sizeof(buf), 100); + if (err != ESP_OK) { + // Frueher lief das stillschweigend ins Leere. Schlaegt es fehl, wird die Bridge + // nie initialisiert und das Bild bleibt schwarz - ohne jeden Hinweis darauf. + esp_rom_printf("[Panel] Bridge-Register 0x%02X liess sich nicht schreiben: %s\n", + reg, esp_err_to_name(err)); + } } // Bridge am I2C-Bus anmelden und Grundinitialisierung schreiben. Muss VOR dem @@ -308,6 +376,10 @@ bool jc_board_bringup(void) { jc_backlight_init(); +#if JC_PANEL_TYPE == WS_PANEL_7H + ws7_i2c_bus_recover(); // haengenden Bus vom letzten Reset befreien +#endif + i2c_master_bus_config_t i2c_bus_conf = { .clk_source = I2C_CLK_SRC_DEFAULT, .sda_io_num = BSP_I2C_SDA, diff --git a/P4_Display_Firmware/pins_config.h b/P4_Display_Firmware/pins_config.h index a0e0fb2..4f1abde 100644 --- a/P4_Display_Firmware/pins_config.h +++ b/P4_Display_Firmware/pins_config.h @@ -148,7 +148,7 @@ #define LCD_RST 27 #define LCD_LED 23 -#elsealle +#else #define LCD_H_RES 480 #define LCD_V_RES 800