diff --git a/README.md b/README.md index c0d2dea..47e8aeb 100644 --- a/README.md +++ b/README.md @@ -595,6 +595,8 @@ The following libraries are used from the [Espressif component registry](https:/ ## Version history +- October 2024 + - Fix for LVGL 9.2.2 that removed the sw_rotate flag - August 2024 - LVGL 9.2 - New boards diff --git a/boards b/boards index ae8d611..35fd2d6 160000 --- a/boards +++ b/boards @@ -1 +1 @@ -Subproject commit ae8d611a0ed8dacc744246bcaabd6711ccf793e9 +Subproject commit 35fd2d6067e1ce49e4460dff2be6c84c432042f6 diff --git a/library.json b/library.json index e31567d..d33e2d9 100644 --- a/library.json +++ b/library.json @@ -35,6 +35,6 @@ "frameworks": "arduino", "platforms": "espressif32", "dependencies": { - "lvgl/lvgl": "^9.2.0" + "lvgl/lvgl": "^9.2.2" } } \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index d2f7403..870b320 100644 --- a/platformio.ini +++ b/platformio.ini @@ -59,7 +59,7 @@ build_flags = '-D ESP_LCD_PANEL_IO_ADDITIONS_VER_PATCH=1' lib_deps = - lvgl/lvgl@^9.2.0 + lvgl/lvgl@^9.2.2 # The platformio.test_dir contains the test_main.cpp just to have an setup() and loop() function # so it will compile ${platformio.test_dir} diff --git a/src/esp32_smartdisplay.c b/src/esp32_smartdisplay.c index ccf1809..b7f46ea 100644 --- a/src/esp32_smartdisplay.c +++ b/src/esp32_smartdisplay.c @@ -94,11 +94,11 @@ void smartdisplay_lcd_set_brightness_cb(smartdisplay_lcd_adaptive_brightness_cb_ log_v("adaptive_brightness_cb:0x%08x, interval:%u", cb, interval); // Delete current timer if any - if (update_brightness_timer) + if (update_brightness_timer != NULL) lv_timer_del(update_brightness_timer); // Use callback for intensity or 50% default - if (cb && interval > 0) + if (cb != NULL && interval > 0) update_brightness_timer = lv_timer_create(adaptive_brightness, interval, cb); else smartdisplay_lcd_set_backlight(0.5f); @@ -107,7 +107,7 @@ void smartdisplay_lcd_set_brightness_cb(smartdisplay_lcd_adaptive_brightness_cb_ #ifdef BOARD_HAS_RGB_LED void smartdisplay_led_set_rgb(bool r, bool g, bool b) { - log_d("R:%d, G:%d, B:%d", r, b, b); + log_d("R:%d, G:%d, B:%d", r, g, b); digitalWrite(RGB_LED_R, !r); digitalWrite(RGB_LED_G, !g); @@ -193,9 +193,11 @@ void smartdisplay_init() #endif // Setup TFT display display = lvgl_lcd_init(); + +#ifndef DISPLAY_SOFTWARE_ROTATION // Register callback for hardware rotation - if (!display->sw_rotate) - lv_display_add_event_cb(display, lvgl_display_resolution_changed_callback, LV_EVENT_RESOLUTION_CHANGED, NULL); + lv_display_add_event_cb(display, lvgl_display_resolution_changed_callback, LV_EVENT_RESOLUTION_CHANGED, NULL); +#endif // Clear screen lv_obj_clean(lv_scr_act()); @@ -214,10 +216,11 @@ void smartdisplay_init() #endif } +#ifndef DISPLAY_SOFTWARE_ROTATION // Called when driver resolution is updated (including rotation) // Top of the display is top left when connector is at the bottom // The rotation values are relative to how you would rotate the physical display in the clockwise direction. -// Thus, LV_DISPLAY_ROTATION_90 means you rotate the hardware 90 degrees clockwise, and the display rotates 90 degrees counterclockwise to compensate. +// So, LV_DISPLAY_ROTATION_90 means you rotate the hardware 90 degrees clockwise, and the display rotates 90 degrees counterclockwise to compensate. void lvgl_display_resolution_changed_callback(lv_event_t *event) { const esp_lcd_panel_handle_t panel_handle = display->user_data; @@ -240,4 +243,6 @@ void lvgl_display_resolution_changed_callback(lv_event_t *event) ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, !DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); break; } -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/esp_touch_cst816s.c b/src/esp_touch_cst816s.c index 1ca139b..4d3ff8f 100644 --- a/src/esp_touch_cst816s.c +++ b/src/esp_touch_cst816s.c @@ -86,6 +86,12 @@ esp_err_t cst816s_reset(esp_lcd_touch_handle_t th) if (th == NULL) return ESP_ERR_INVALID_ARG; + if (th->config.rst_gpio_num == GPIO_NUM_NC) + { + log_w("No RST pin defined"); + return ESP_OK; + } + esp_err_t res; // Set RST active if ((res = gpio_set_level(th->config.rst_gpio_num, th->config.levels.reset)) != ESP_OK) @@ -259,14 +265,29 @@ esp_err_t esp_lcd_touch_new_i2c_cst816s(const esp_lcd_panel_io_handle_t io, cons memcpy(&th->config, config, sizeof(esp_lcd_touch_config_t)); portMUX_INITIALIZE(&th->data.lock); + // Reset controller + if ((res = cst816s_reset(th)) != ESP_OK) + { + log_e("GT911 reset failed"); + cst816s_del(th); + return res; + } + + // Read type and resolution + if ((res = cst816s_read_info(th)) != ESP_OK) + { + log_e("GT911 read info failed"); + cst816s_del(th); + return res; + } + if (config->int_gpio_num != GPIO_NUM_NC) { esp_rom_gpio_pad_select_gpio(config->int_gpio_num); const gpio_config_t cfg = { .pin_bit_mask = BIT64(config->int_gpio_num), .mode = GPIO_MODE_INPUT, - // If the user has provided a callback routine for the interrupt enable the interrupt mode on the negative edge. - .intr_type = config->interrupt_callback ? GPIO_INTR_NEGEDGE : GPIO_INTR_DISABLE}; + .intr_type = config->levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE}; if ((res = gpio_config(&cfg)) != ESP_OK) { free(th); @@ -278,9 +299,11 @@ esp_err_t esp_lcd_touch_new_i2c_cst816s(const esp_lcd_panel_io_handle_t io, cons { if ((res = esp_lcd_touch_register_interrupt_callback(th, config->interrupt_callback)) != ESP_OK) { - gpio_reset_pin(th->config.int_gpio_num); + if (config->int_gpio_num != GPIO_NUM_NC) + gpio_reset_pin(th->config.int_gpio_num); + free(th); - log_e("Registering INT callback failed"); + log_e("Registering interrupt callback failed"); return res; } } @@ -306,22 +329,6 @@ esp_err_t esp_lcd_touch_new_i2c_cst816s(const esp_lcd_panel_io_handle_t io, cons return res; } } - - // Reset controller - if ((res = cst816s_reset(th)) != ESP_OK) - { - log_e("GT911 reset failed"); - cst816s_del(th); - return res; - } - - // Read type and resolution - if ((res = cst816s_read_info(th)) != ESP_OK) - { - log_e("GT911 read info failed"); - cst816s_del(th); - return res; - } } log_d("handle:0x%08x", th); diff --git a/src/esp_touch_gt911.c b/src/esp_touch_gt911.c index d79930c..7e15308 100644 --- a/src/esp_touch_gt911.c +++ b/src/esp_touch_gt911.c @@ -82,6 +82,12 @@ esp_err_t gt911_reset(esp_lcd_touch_handle_t th) if (th == NULL) return ESP_ERR_INVALID_ARG; + if (th->config.rst_gpio_num == GPIO_NUM_NC) + { + log_w("No RST pin defined"); + return ESP_OK; + } + esp_err_t res; // Set RST active if ((res = gpio_set_level(th->config.rst_gpio_num, th->config.levels.reset)) != ESP_OK) @@ -397,53 +403,19 @@ esp_err_t esp_lcd_touch_new_i2c_gt911(const esp_lcd_panel_io_handle_t io, const memcpy(&th->config, config, sizeof(esp_lcd_touch_config_t)); portMUX_INITIALIZE(&th->data.lock); - if (config->int_gpio_num != GPIO_NUM_NC) + // Initialize RST pin + if (config->rst_gpio_num != GPIO_NUM_NC) { - esp_rom_gpio_pad_select_gpio(config->int_gpio_num); + esp_rom_gpio_pad_select_gpio(config->rst_gpio_num); const gpio_config_t cfg = { - .pin_bit_mask = BIT64(config->int_gpio_num), - .mode = GPIO_MODE_INPUT, - // If the user has provided a callback routine for the interrupt enable the interrupt mode on the negative edge. - .intr_type = config->interrupt_callback ? GPIO_INTR_NEGEDGE : GPIO_INTR_DISABLE}; + .pin_bit_mask = BIT64(config->rst_gpio_num), + .mode = GPIO_MODE_OUTPUT}; if ((res = gpio_config(&cfg)) != ESP_OK) { free(th); - log_e("Configuring GPIO for INT failed"); + log_e("Configuring or setting GPIO for RST failed"); return res; } - - if (config->interrupt_callback != NULL) - { - if ((res = esp_lcd_touch_register_interrupt_callback(th, config->interrupt_callback)) != ESP_OK) - { - gpio_reset_pin(th->config.int_gpio_num); - free(th); - log_e("Registering INT callback failed"); - return res; - } - } - - if (config->rst_gpio_num != GPIO_NUM_NC) - { - esp_rom_gpio_pad_select_gpio(config->rst_gpio_num); - const gpio_config_t cfg = { - .pin_bit_mask = BIT64(config->rst_gpio_num), - .mode = GPIO_MODE_OUTPUT}; - if ((res = gpio_config(&cfg)) != ESP_OK) - { - if (th->config.int_gpio_num != GPIO_NUM_NC) - { - if (config->interrupt_callback != NULL) - gpio_isr_handler_remove(th->config.int_gpio_num); - - gpio_reset_pin(th->config.int_gpio_num); - } - - free(th); - log_e("Configuring or setting GPIO for RST failed"); - return res; - } - } } // Reset controller @@ -462,6 +434,32 @@ esp_err_t esp_lcd_touch_new_i2c_gt911(const esp_lcd_panel_io_handle_t io, const return res; } + if (config->int_gpio_num != GPIO_NUM_NC) + { + esp_rom_gpio_pad_select_gpio(config->int_gpio_num); + const gpio_config_t cfg = { + .pin_bit_mask = BIT64(config->int_gpio_num), + .mode = GPIO_MODE_INPUT, + .intr_type = config->levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE}; + if ((res = gpio_config(&cfg)) != ESP_OK) + { + free(th); + log_e("Configuring GPIO for INT failed"); + return res; + } + + if (config->interrupt_callback != NULL) + { + if ((res = esp_lcd_touch_register_interrupt_callback(th, config->interrupt_callback)) != ESP_OK) + { + gpio_reset_pin(th->config.int_gpio_num); + free(th); + log_e("Registering interrupt callback failed"); + return res; + } + } + } + log_d("handle:0x%08x", th); *handle = th; diff --git a/src/esp_touch_xpt2046.c b/src/esp_touch_xpt2046.c index 27ff477..8c52434 100644 --- a/src/esp_touch_xpt2046.c +++ b/src/esp_touch_xpt2046.c @@ -204,8 +204,7 @@ esp_err_t esp_lcd_touch_new_spi_xpt2046(const esp_lcd_panel_io_handle_t io, cons const gpio_config_t cfg = { .pin_bit_mask = BIT64(config->int_gpio_num), .mode = GPIO_MODE_INPUT, - // If the user has provided a callback routine for the interrupt enable the interrupt mode on the negative edge. - .intr_type = config->interrupt_callback ? GPIO_INTR_NEGEDGE : GPIO_INTR_DISABLE}; + .intr_type = config->levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE}; if ((res = gpio_config(&cfg)) != ESP_OK) { free(th); @@ -219,7 +218,7 @@ esp_err_t esp_lcd_touch_new_spi_xpt2046(const esp_lcd_panel_io_handle_t io, cons { gpio_reset_pin(th->config.int_gpio_num); free(th); - log_e("Registering INT callback failed"); + log_e("Registering interrupt callback failed"); return res; } } diff --git a/src/lvgl_panel_gc9a01_spi.c b/src/lvgl_panel_gc9a01_spi.c index 7360336..b6c0b85 100644 --- a/src/lvgl_panel_gc9a01_spi.c +++ b/src/lvgl_panel_gc9a01_spi.c @@ -17,6 +17,7 @@ bool gc9a01_color_trans_done(esp_lcd_panel_io_handle_t panel_io_handle, esp_lcd_ void gc9a01_lv_flush(lv_display_t *display, const lv_area_t *area, uint8_t *px_map) { + // Hardware rotation is supported log_v("display:0x%08x, area:%0x%08x, color_map:0x%08x", display, area, px_map); esp_lcd_panel_handle_t panel_handle = display->user_data; @@ -40,10 +41,6 @@ lv_display_t *lvgl_lcd_init() void *drawBuffer = heap_caps_malloc(drawBufferSize, LVGL_BUFFER_MALLOC_FLAGS); lv_display_set_buffers(display, drawBuffer, NULL, drawBufferSize, LV_DISPLAY_RENDER_MODE_PARTIAL); - // Hardware rotation is supported - display->sw_rotate = 0; - display->rotation = LV_DISPLAY_ROTATION_0; - // Create SPI bus const spi_bus_config_t spi_bus_config = { .mosi_io_num = GC9A01_SPI_BUS_MOSI_IO_NUM, diff --git a/src/lvgl_panel_ili9341_spi.c b/src/lvgl_panel_ili9341_spi.c index 62f20f7..a36d53e 100644 --- a/src/lvgl_panel_ili9341_spi.c +++ b/src/lvgl_panel_ili9341_spi.c @@ -15,6 +15,7 @@ bool ili9341_color_trans_done(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_ void ili9341_lv_flush(lv_display_t *display, const lv_area_t *area, uint8_t *px_map) { + // Hardware rotation is supported esp_lcd_panel_handle_t panel_handle = display->user_data; uint32_t pixels = lv_area_get_size(area); uint16_t *p = (uint16_t *)px_map; @@ -36,10 +37,6 @@ lv_display_t *lvgl_lcd_init() void *drawBuffer = heap_caps_malloc(drawBufferSize, LVGL_BUFFER_MALLOC_FLAGS); lv_display_set_buffers(display, drawBuffer, NULL, drawBufferSize, LV_DISPLAY_RENDER_MODE_PARTIAL); - // Hardware rotation is supported - display->sw_rotate = 0; - display->rotation = LV_DISPLAY_ROTATION_0; - // Create SPI bus const spi_bus_config_t spi_bus_config = { .mosi_io_num = ILI9341_SPI_BUS_MOSI_IO_NUM, diff --git a/src/lvgl_panel_st7262_par.c b/src/lvgl_panel_st7262_par.c index a34adaa..81025d7 100644 --- a/src/lvgl_panel_st7262_par.c +++ b/src/lvgl_panel_st7262_par.c @@ -13,6 +13,7 @@ bool direct_io_frame_trans_done(esp_lcd_panel_handle_t panel, esp_lcd_rgb_panel_ void direct_io_lv_flush(lv_display_t *display, const lv_area_t *area, uint8_t *px_map) { + // Hardware rotation is not supported const esp_lcd_panel_handle_t panel_handle = display->user_data; lv_display_rotation_t rotation = lv_display_get_rotation(display); @@ -68,10 +69,6 @@ lv_display_t *lvgl_lcd_init() void *drawBuffer = heap_caps_malloc(drawBufferSize, LVGL_BUFFER_MALLOC_FLAGS); lv_display_set_buffers(display, drawBuffer, NULL, drawBufferSize, LV_DISPLAY_RENDER_MODE_PARTIAL); - // Hardware rotation is not supported - display->sw_rotate = 1; - display->rotation = LV_DISPLAY_ROTATION_0; - // Create direct_io panel handle const esp_lcd_rgb_panel_config_t rgb_panel_config = { .clk_src = ST7262_PANEL_CONFIG_CLK_SRC, diff --git a/src/lvgl_panel_st7701_par.c b/src/lvgl_panel_st7701_par.c index 95a2078..d2861c3 100644 --- a/src/lvgl_panel_st7701_par.c +++ b/src/lvgl_panel_st7701_par.c @@ -15,9 +15,49 @@ bool direct_io_frame_trans_done(esp_lcd_panel_handle_t panel, esp_lcd_rgb_panel_ void direct_io_lv_flush(lv_display_t *display, const lv_area_t *area, uint8_t *px_map) { + // Hardware rotation is not supported const esp_lcd_panel_handle_t panel_handle = display->user_data; - // LV_COLOR_16_SWAP is handled by mapping of the data - ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map)); + + lv_display_rotation_t rotation = lv_display_get_rotation(display); + if (rotation == LV_DISPLAY_ROTATION_0) + { + ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map)); + return; + } + + // Rotated + int32_t w = lv_area_get_width(area); + int32_t h = lv_area_get_height(area); + lv_color_format_t cf = lv_display_get_color_format(display); + uint32_t px_size = lv_color_format_get_size(cf); + size_t buf_size = w * h * px_size; + log_v("alloc rotation buffer to: %u bytes", buf_size); + void *rotation_buffer = heap_caps_malloc(buf_size, LVGL_BUFFER_MALLOC_FLAGS); + assert(rotation_buffer != NULL); + + uint32_t w_stride = lv_draw_buf_width_to_stride(w, cf); + uint32_t h_stride = lv_draw_buf_width_to_stride(h, cf); + + switch (rotation) + { + case LV_DISPLAY_ROTATION_90: + lv_draw_sw_rotate(px_map, rotation_buffer, w, h, w_stride, h_stride, rotation, cf); + ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, area->y1, display->ver_res - area->x1 - w, area->y1 + h, display->ver_res - area->x1, rotation_buffer)); + break; + case LV_DISPLAY_ROTATION_180: + lv_draw_sw_rotate(px_map, rotation_buffer, w, h, w_stride, w_stride, rotation, cf); + ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, display->hor_res - area->x1 - w, display->ver_res - area->y1 - h, display->hor_res - area->x1, display->ver_res - area->y1, rotation_buffer)); + break; + case LV_DISPLAY_ROTATION_270: + lv_draw_sw_rotate(px_map, rotation_buffer, w, h, w_stride, h_stride, rotation, cf); + ESP_ERROR_CHECK(esp_lcd_panel_draw_bitmap(panel_handle, display->hor_res - area->y2 - 1, area->x2 - w + 1, display->hor_res - area->y2 - 1 + h, area->x2 + 1, rotation_buffer)); + break; + default: + assert(false); + break; + } + + free(rotation_buffer); }; lv_display_t *lvgl_lcd_init() @@ -29,10 +69,6 @@ lv_display_t *lvgl_lcd_init() void *drawBuffer = heap_caps_malloc(drawBufferSize, LVGL_BUFFER_MALLOC_FLAGS); lv_display_set_buffers(display, drawBuffer, NULL, drawBufferSize, LV_DISPLAY_RENDER_MODE_PARTIAL); - // Hardware rotation is not supported - display->sw_rotate = 1; - display->rotation = LV_DISPLAY_ROTATION_0; - // Install 3-wire SPI panel IO esp_lcd_panel_io_3wire_spi_config_t io_3wire_spi_config = { .line_config = { diff --git a/src/lvgl_panel_st7789_i80.c b/src/lvgl_panel_st7789_i80.c index 5ef0558..19cbef5 100644 --- a/src/lvgl_panel_st7789_i80.c +++ b/src/lvgl_panel_st7789_i80.c @@ -14,6 +14,7 @@ bool st7789_color_trans_done(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_i void st7789_lv_flush(lv_display_t *drv, const lv_area_t *area, uint8_t *px_map) { + // Hardware rotation is supported const esp_lcd_panel_handle_t panel_handle = drv->user_data; uint32_t pixels = lv_area_get_size(area); uint16_t *p = (uint16_t *)px_map; @@ -35,10 +36,6 @@ lv_display_t *lvgl_lcd_init(uint32_t hor_res, uint32_t ver_res) void *drawBuffer = heap_caps_malloc(drawBufferSize, LVGL_BUFFER_MALLOC_FLAGS); lv_display_set_buffers(display, drawBuffer, NULL, drawBufferSize, LV_DISPLAY_RENDER_MODE_PARTIAL); - // Hardware rotation is supported - display->sw_rotate = 0; - display->rotation = LV_DISPLAY_ROTATION_0; - pinMode(ST7789_RD_GPIO, OUTPUT); digitalWrite(ST7789_RD_GPIO, HIGH); diff --git a/src/lvgl_panel_st7789_spi.c b/src/lvgl_panel_st7789_spi.c index cfdfa9a..24ab2cd 100644 --- a/src/lvgl_panel_st7789_spi.c +++ b/src/lvgl_panel_st7789_spi.c @@ -15,6 +15,7 @@ bool st7789_color_trans_done(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_i void st7789_lv_flush(lv_display_t *display, const lv_area_t *area, uint8_t *px_map) { + // Hardware rotation is supported esp_lcd_panel_handle_t panel_handle = display->user_data; uint32_t pixels = lv_area_get_size(area); uint16_t *p = (uint16_t *)px_map; @@ -36,10 +37,6 @@ lv_display_t *lvgl_lcd_init(uint32_t hor_res, uint32_t ver_res) void *drawBuffer = heap_caps_malloc(drawBufferSize, LVGL_BUFFER_MALLOC_FLAGS); lv_display_set_buffers(display, drawBuffer, NULL, drawBufferSize, LV_DISPLAY_RENDER_MODE_PARTIAL); - // Hardware rotation is supported - display->sw_rotate = 0; - display->rotation = LV_DISPLAY_ROTATION_0; - // Create SPI bus const spi_bus_config_t spi_bus_config = { .mosi_io_num = ST7789_SPI_BUS_MOSI_IO_NUM, diff --git a/src/lvgl_panel_st7796_spi.c b/src/lvgl_panel_st7796_spi.c index 08c9807..5e55a48 100644 --- a/src/lvgl_panel_st7796_spi.c +++ b/src/lvgl_panel_st7796_spi.c @@ -16,6 +16,7 @@ bool st7796_color_trans_done(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_i void st7796_lv_flush(lv_display_t *display, const lv_area_t *area, uint8_t *px_map) { + // Hardware rotation is supported esp_lcd_panel_handle_t panel_handle = display->user_data; uint32_t pixels = lv_area_get_size(area); uint16_t *p = (uint16_t *)px_map; @@ -37,10 +38,6 @@ lv_display_t *lvgl_lcd_init(uint32_t hor_res, uint32_t ver_res) void *drawBuffer = heap_caps_malloc(drawBufferSize, LVGL_BUFFER_MALLOC_FLAGS); lv_display_set_buffers(display, drawBuffer, NULL, drawBufferSize, LV_DISPLAY_RENDER_MODE_PARTIAL); - // Hardware rotation is supported - display->sw_rotate = 0; - display->rotation = LV_DISPLAY_ROTATION_0; - // Create SPI bus const spi_bus_config_t spi_bus_config = { .mosi_io_num = ST7796_SPI_BUS_MOSI_IO_NUM,