diff --git a/src/lgfx/v1/platforms/esp32/Light_PWM.cpp b/src/lgfx/v1/platforms/esp32/Light_PWM.cpp index 676b90e6..2286881c 100644 --- a/src/lgfx/v1/platforms/esp32/Light_PWM.cpp +++ b/src/lgfx/v1/platforms/esp32/Light_PWM.cpp @@ -19,6 +19,9 @@ Original Source: #include #include "Light_PWM.hpp" +#include "common.hpp" + +#include #if defined ( ARDUINO ) #include @@ -26,7 +29,6 @@ Original Source: #include #endif #else - #include #include #endif @@ -39,7 +41,7 @@ Original Source: #endif #endif #if !defined LGFX_LEDCINIT // pre-3.x cores, including 1.x where ESP_ARDUINO_VERSION is absent - #define LGFX_LEDCINIT(pin_bl, freq, bits, pwm_channel) { ledcSetup(pwm_channel, freq, bits); ledcAttachPin(pin_bl, pwm_channel); } + #define LGFX_LEDCINIT(pin_bl, freq, bits, pwm_channel) ( ledcSetup(pwm_channel, freq, bits) > 0 && (ledcAttachPin(pin_bl, pwm_channel), true) ) #define LGFX_LEDCWRITE(pin_bl, pwm_channel, duty) ledcWrite(pwm_channel, duty) #endif @@ -65,10 +67,21 @@ namespace lgfx bool Light_PWM::init(uint8_t brightness) { + if ((size_t)_cfg.pin_bl >= GPIO_NUM_MAX || !GPIO_IS_VALID_OUTPUT_GPIO((gpio_num_t)_cfg.pin_bl)) + { + return false; + } + + // The LEDC driver does not fully normalize the pad state: the open-drain + // flag is never cleared, and ESP-IDF v6 no longer selects the GPIO + // function in IO_MUX. Reconfigure the pin as a push-pull GPIO output + // first, latching it to the "off" level to avoid a visible glitch. + if (_cfg.invert) { gpio_hi(_cfg.pin_bl); } else { gpio_lo(_cfg.pin_bl); } + lgfx::pinMode(_cfg.pin_bl, pin_mode_t::output); #if defined ( ARDUINO ) - LGFX_LEDCINIT(_cfg.pin_bl, _cfg.freq, PWM_BITS, _cfg.pwm_channel); + bool result = LGFX_LEDCINIT(_cfg.pin_bl, _cfg.freq, PWM_BITS, _cfg.pwm_channel); #else // esp-idf @@ -87,7 +100,7 @@ namespace lgfx #endif #endif }; - ledc_channel_config(&ledc_channel); + bool result = (ESP_OK == ledc_channel_config(&ledc_channel)); static ledc_timer_config_t ledc_timer; { ledc_timer.speed_mode = LGFX_LEDC_SPEED_MODE; // timer mode @@ -95,10 +108,11 @@ namespace lgfx ledc_timer.freq_hz = _cfg.freq; // frequency of PWM signal ledc_timer.timer_num = ledc_channel.timer_sel; // timer index }; - ledc_timer_config(&ledc_timer); + result = (ESP_OK == ledc_timer_config(&ledc_timer)) && result; #endif + if (!result) { return false; } setBrightness(brightness); return true; } diff --git a/src/lgfx/v1/platforms/esp32/common.cpp b/src/lgfx/v1/platforms/esp32/common.cpp index bdf0e82b..063e6a28 100644 --- a/src/lgfx/v1/platforms/esp32/common.cpp +++ b/src/lgfx/v1/platforms/esp32/common.cpp @@ -92,6 +92,8 @@ Original Source: #include #endif +#include + #if __has_include() #include #endif @@ -625,6 +627,25 @@ namespace lgfx // ------------------------------------------------------------------------ + // Clear stale open-drain state on the bus pins. + // spi_bus_initialize does not clear the pad open-drain flag (ESP-IDF v6 + // no longer configures it at all), so a pin left in open-drain mode by a + // previous use may not rise fast enough at typical SPI clock rates. + static void clear_open_drain(std::initializer_list pins) + { + for (int pin : pins) + { + if ((size_t)pin < GPIO_NUM_MAX) + { +#if __has_include() + gpio_ll_od_disable(&GPIO, (gpio_num_t)pin); +#else // ESP-IDF v3 (plain ESP32 only) + GPIO.pin[pin].pad_driver = 0; +#endif + } + } + } + cpp::result init(int spi_host, int spi_sclk, int spi_miso, int spi_mosi) { return init(spi_host, spi_sclk, spi_miso, spi_mosi, 0); // SPI_DMA_CH_AUTO; @@ -700,21 +721,7 @@ namespace lgfx } } - // SPIバスのピンを push-pull 出力へ明示的に戻す。 - // pinMode の input 系設定はパッドを open-drain にするが、ESP-IDF v6 以降の - // spi_bus_initialize はピンの open-drain 設定を解除しないため、直前のピン状態が - // 残っていると SCLK/MOSI が open-drain 駆動となり、高クロックで波形が立ち上がらない。 - for (int pin : { spi_sclk, spi_mosi, spi_miso }) - { - if ((size_t)pin < GPIO_NUM_MAX) - { -#if __has_include() - gpio_ll_od_disable(&GPIO, (gpio_num_t)pin); -#else // ESP-IDF v3 系 (無印 ESP32 のみ) - GPIO.pin[pin].pad_driver = 0; -#endif - } - } + clear_open_drain({ spi_sclk, spi_mosi, spi_miso }); writereg(SPI_USER_REG(spi_port), SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN); // need SD card access (full duplex setting) writereg(SPI_CTRL_REG(spi_port), 0); @@ -797,6 +804,8 @@ namespace lgfx #pragma GCC diagnostic pop + clear_open_drain({ spi_sclk, spi_io0, spi_io1, spi_io2, spi_io3 }); + writereg(SPI_USER_REG(spi_port), SPI_USR_MOSI | SPI_USR_MISO | SPI_DOUTDIN); // need SD card access (full duplex setting) writereg(SPI_CTRL_REG(spi_port), 0); #if defined ( SPI_CTRL1_REG ) diff --git a/src/lgfx/v1/platforms/esp32s2/Bus_Parallel16.cpp b/src/lgfx/v1/platforms/esp32s2/Bus_Parallel16.cpp index 4e46c2e3..0a778a21 100644 --- a/src/lgfx/v1/platforms/esp32s2/Bus_Parallel16.cpp +++ b/src/lgfx/v1/platforms/esp32s2/Bus_Parallel16.cpp @@ -96,6 +96,13 @@ namespace lgfx bool Bus_Parallel16::init(void) { + // The GPIO matrix routing used below does not configure pad direction / + // open-drain, so normalize the data pins as push-pull GPIO outputs first. + for (int pin : _cfg.pin_data) + { + lgfx::pinMode(pin, pin_mode_t::output); + } + _init_pin(); for (size_t i = 0; i < 3; ++i) diff --git a/src/lgfx/v1/platforms/esp32s2/Bus_Parallel8.cpp b/src/lgfx/v1/platforms/esp32s2/Bus_Parallel8.cpp index 5fc1312d..1c89f482 100644 --- a/src/lgfx/v1/platforms/esp32s2/Bus_Parallel8.cpp +++ b/src/lgfx/v1/platforms/esp32s2/Bus_Parallel8.cpp @@ -96,6 +96,13 @@ namespace lgfx bool Bus_Parallel8::init(void) { + // The GPIO matrix routing used below does not configure pad direction / + // open-drain, so normalize the data pins as push-pull GPIO outputs first. + for (int pin : _cfg.pin_data) + { + lgfx::pinMode(pin, pin_mode_t::output); + } + _init_pin(); for (size_t i = 0; i < 3; ++i) diff --git a/src/lgfx/v1/platforms/esp32s3/Bus_Parallel16.cpp b/src/lgfx/v1/platforms/esp32s3/Bus_Parallel16.cpp index 8dd0a399..96aae269 100644 --- a/src/lgfx/v1/platforms/esp32s3/Bus_Parallel16.cpp +++ b/src/lgfx/v1/platforms/esp32s3/Bus_Parallel16.cpp @@ -80,6 +80,14 @@ namespace lgfx bool Bus_Parallel16::init(void) { + // esp_lcd_new_i80_bus does not configure pad direction / open-drain, so + // normalize the data pins as push-pull GPIO outputs first (same + // normalization used by Bus_EPD). + for (int pin : _cfg.pin_data) + { + lgfx::pinMode(pin, pin_mode_t::output); + } + _init_pin(); for (size_t i = 0; i < 3; ++i) diff --git a/src/lgfx/v1/platforms/esp32s3/Bus_Parallel8.cpp b/src/lgfx/v1/platforms/esp32s3/Bus_Parallel8.cpp index bdcfa058..a69ceacd 100644 --- a/src/lgfx/v1/platforms/esp32s3/Bus_Parallel8.cpp +++ b/src/lgfx/v1/platforms/esp32s3/Bus_Parallel8.cpp @@ -80,6 +80,14 @@ namespace lgfx bool Bus_Parallel8::init(void) { + // esp_lcd_new_i80_bus does not configure pad direction / open-drain, so + // normalize the data pins as push-pull GPIO outputs first (same + // normalization used by Bus_EPD). + for (int pin : _cfg.pin_data) + { + lgfx::pinMode(pin, pin_mode_t::output); + } + _init_pin(); for (size_t i = 0; i < 3; ++i)