perf: optimize ST7789 LVGL touch responsiveness
This commit is contained in:
@@ -30,13 +30,13 @@
|
|||||||
static const char *TAG = "lvgl_touch";
|
static const char *TAG = "lvgl_touch";
|
||||||
|
|
||||||
#define LCD_SPI_HOST SPI2_HOST
|
#define LCD_SPI_HOST SPI2_HOST
|
||||||
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (10 * 1000 * 1000)
|
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (40 * 1000 * 1000)
|
||||||
#define EXAMPLE_LCD_CMD_BITS 8
|
#define EXAMPLE_LCD_CMD_BITS 8
|
||||||
#define EXAMPLE_LCD_PARAM_BITS 8
|
#define EXAMPLE_LCD_PARAM_BITS 8
|
||||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||||
#define EXAMPLE_LVGL_BUFFER_LINES 80
|
#define EXAMPLE_LVGL_BUFFER_LINES 120
|
||||||
#define EXAMPLE_TOUCH_I2C_FREQ_HZ (100 * 1000)
|
#define EXAMPLE_TOUCH_I2C_FREQ_HZ (400 * 1000)
|
||||||
#define EXAMPLE_TOUCH_LOG_PERIOD_MS 120
|
#define EXAMPLE_TOUCH_LOG_PERIOD_MS 500
|
||||||
#define EXAMPLE_TOUCH_PROBE_TIMEOUT_MS 30
|
#define EXAMPLE_TOUCH_PROBE_TIMEOUT_MS 30
|
||||||
|
|
||||||
// Current adapter wiring:
|
// Current adapter wiring:
|
||||||
@@ -85,6 +85,12 @@ static bool notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_
|
|||||||
|
|
||||||
static void lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
|
static void lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map)
|
||||||
{
|
{
|
||||||
|
size_t pixel_count = (size_t)(area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1);
|
||||||
|
|
||||||
|
// LVGL stores RGB565 pixels in the ESP32's native little-endian byte order,
|
||||||
|
// while this ST7789 panel expects the high byte on the SPI bus first.
|
||||||
|
lv_draw_sw_rgb565_swap(px_map, pixel_count);
|
||||||
|
|
||||||
esp_err_t ret = esp_lcd_panel_draw_bitmap(s_panel, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map);
|
esp_err_t ret = esp_lcd_panel_draw_bitmap(s_panel, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "LCD flush failed: %s", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "LCD flush failed: %s", esp_err_to_name(ret));
|
||||||
@@ -159,10 +165,10 @@ static void lvgl_task(void *arg)
|
|||||||
(void)arg;
|
(void)arg;
|
||||||
while (1) {
|
while (1) {
|
||||||
uint32_t delay_ms = lv_timer_handler();
|
uint32_t delay_ms = lv_timer_handler();
|
||||||
if (delay_ms < 2) {
|
if (delay_ms < 1) {
|
||||||
delay_ms = 2;
|
delay_ms = 1;
|
||||||
} else if (delay_ms > 8) {
|
} else if (delay_ms > 5) {
|
||||||
delay_ms = 8;
|
delay_ms = 5;
|
||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
||||||
}
|
}
|
||||||
@@ -396,60 +402,11 @@ static esp_err_t init_i2c_bus(void)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t release_touch_reset_before_i2c(void)
|
static void log_gt911_i2c_idle_levels(void)
|
||||||
{
|
{
|
||||||
gpio_config_t rst_gpio_config = {
|
ESP_LOGI(TAG, "GT911 I2C idle levels: SCL(IO%d)=%d SDA(IO%d)=%d",
|
||||||
.mode = GPIO_MODE_OUTPUT,
|
EXAMPLE_PIN_NUM_TOUCH_SCL, gpio_get_level(EXAMPLE_PIN_NUM_TOUCH_SCL),
|
||||||
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_TOUCH_RST,
|
EXAMPLE_PIN_NUM_TOUCH_SDA, gpio_get_level(EXAMPLE_PIN_NUM_TOUCH_SDA));
|
||||||
};
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Release GT911 reset on IO%d before I2C bus init", EXAMPLE_PIN_NUM_TOUCH_RST);
|
|
||||||
esp_err_t ret = gpio_config(&rst_gpio_config);
|
|
||||||
if (ret != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "GPIO%d configuration failed: %s (0x%x)", EXAMPLE_PIN_NUM_TOUCH_RST,
|
|
||||||
esp_err_to_name(ret), ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = gpio_set_level(EXAMPLE_PIN_NUM_TOUCH_RST, 1);
|
|
||||||
if (ret != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "GPIO%d release failed: %s (0x%x)", EXAMPLE_PIN_NUM_TOUCH_RST,
|
|
||||||
esp_err_to_name(ret), ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(120));
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool scan_i2c_bus_handle(i2c_master_bus_handle_t bus, const char *label, int scl, int sda)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Scan I2C devices on %s: SCL=IO%d SDA=IO%d", label, scl, sda);
|
|
||||||
for (uint8_t addr = 0x08; addr < 0x78; addr++) {
|
|
||||||
esp_err_t ret = i2c_master_probe(bus, addr, 10);
|
|
||||||
if (ret == ESP_OK) {
|
|
||||||
ESP_LOGI(TAG, "I2C device found on %s at 0x%02x", label, addr);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
ESP_LOGW(TAG, "No I2C device found on %s: SCL=IO%d SDA=IO%d", label, scl, sda);
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool scan_i2c_bus(void)
|
|
||||||
{
|
|
||||||
bool found = scan_i2c_bus_handle(s_i2c_bus, "configured GT911 bus", EXAMPLE_PIN_NUM_TOUCH_SCL,
|
|
||||||
EXAMPLE_PIN_NUM_TOUCH_SDA);
|
|
||||||
if (!found) {
|
|
||||||
ESP_LOGW(TAG, "Check T_SCL/T_SDA wiring, touch power, common GND, and I2C pull-ups");
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t select_gt911_address(uint8_t dev_addr)
|
static esp_err_t select_gt911_address(uint8_t dev_addr)
|
||||||
@@ -473,16 +430,23 @@ static esp_err_t select_gt911_address(uint8_t dev_addr)
|
|||||||
ESP_RETURN_ON_ERROR(gpio_set_level(EXAMPLE_PIN_NUM_TOUCH_IRQ, 0), TAG, "drive GT911 INT low failed");
|
ESP_RETURN_ON_ERROR(gpio_set_level(EXAMPLE_PIN_NUM_TOUCH_IRQ, 0), TAG, "drive GT911 INT low failed");
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
ESP_RETURN_ON_ERROR(gpio_set_level(EXAMPLE_PIN_NUM_TOUCH_IRQ, int_level), TAG, "set GT911 address level failed");
|
ESP_RETURN_ON_ERROR(gpio_set_level(EXAMPLE_PIN_NUM_TOUCH_IRQ, int_level), TAG, "set GT911 address level failed");
|
||||||
vTaskDelay(pdMS_TO_TICKS(2));
|
vTaskDelay(pdMS_TO_TICKS(1));
|
||||||
ESP_RETURN_ON_ERROR(gpio_set_level(EXAMPLE_PIN_NUM_TOUCH_RST, 1), TAG, "release GT911 reset failed");
|
ESP_RETURN_ON_ERROR(gpio_set_level(EXAMPLE_PIN_NUM_TOUCH_RST, 1), TAG, "release GT911 reset failed");
|
||||||
vTaskDelay(pdMS_TO_TICKS(80));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
ESP_RETURN_ON_ERROR(gpio_set_direction(EXAMPLE_PIN_NUM_TOUCH_IRQ, GPIO_MODE_INPUT), TAG,
|
||||||
|
"release GT911 INT failed");
|
||||||
|
ESP_RETURN_ON_ERROR(gpio_set_pull_mode(EXAMPLE_PIN_NUM_TOUCH_IRQ, GPIO_PULLUP_ONLY), TAG,
|
||||||
|
"enable GT911 INT pull-up failed");
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(50));
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t try_init_gt911_touch(uint8_t dev_addr)
|
static esp_err_t try_init_gt911_touch(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Initialize GT911 touch at I2C address 0x%02x", dev_addr);
|
ESP_LOGI(TAG, "Initialize GT911 at 0x%02x with RST=IO%d INT=IO%d",
|
||||||
|
dev_addr, EXAMPLE_PIN_NUM_TOUCH_RST, EXAMPLE_PIN_NUM_TOUCH_IRQ);
|
||||||
ESP_RETURN_ON_ERROR(select_gt911_address(dev_addr), TAG, "select GT911 address failed");
|
ESP_RETURN_ON_ERROR(select_gt911_address(dev_addr), TAG, "select GT911 address failed");
|
||||||
|
log_gt911_i2c_idle_levels();
|
||||||
|
|
||||||
esp_err_t ret = i2c_master_probe(s_i2c_bus, dev_addr, EXAMPLE_TOUCH_PROBE_TIMEOUT_MS);
|
esp_err_t ret = i2c_master_probe(s_i2c_bus, dev_addr, EXAMPLE_TOUCH_PROBE_TIMEOUT_MS);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
@@ -540,11 +504,13 @@ static esp_err_t init_gt911_touch(void)
|
|||||||
|
|
||||||
static void init_touch_optional(void)
|
static void init_touch_optional(void)
|
||||||
{
|
{
|
||||||
esp_err_t ret = release_touch_reset_before_i2c();
|
esp_err_t ret = init_i2c_bus();
|
||||||
if (ret == ESP_OK) {
|
if (ret == ESP_OK) {
|
||||||
ret = init_i2c_bus();
|
esp_err_t reset_ret = i2c_master_bus_reset(s_i2c_bus);
|
||||||
|
if (reset_ret != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, "GT911 I2C bus recovery failed: %s", esp_err_to_name(reset_ret));
|
||||||
|
log_gt911_i2c_idle_levels();
|
||||||
}
|
}
|
||||||
if (ret == ESP_OK) {
|
|
||||||
ret = init_gt911_touch();
|
ret = init_gt911_touch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -556,7 +522,8 @@ static void init_touch_optional(void)
|
|||||||
ESP_LOGE(TAG, "GT911 is unavailable: %s. Continue with LCD only", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "GT911 is unavailable: %s. Continue with LCD only", esp_err_to_name(ret));
|
||||||
s_touch = NULL;
|
s_touch = NULL;
|
||||||
if (s_i2c_bus != NULL) {
|
if (s_i2c_bus != NULL) {
|
||||||
scan_i2c_bus();
|
log_gt911_i2c_idle_levels();
|
||||||
|
ESP_LOGW(TAG, "Check T_SCL/T_SDA wiring, touch power, common GND, and I2C pull-ups");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,6 +580,6 @@ void app_main(void)
|
|||||||
|
|
||||||
ESP_ERROR_CHECK(init_spi_bus());
|
ESP_ERROR_CHECK(init_spi_bus());
|
||||||
ESP_ERROR_CHECK(init_st7789_panel(&panel_io));
|
ESP_ERROR_CHECK(init_st7789_panel(&panel_io));
|
||||||
ESP_ERROR_CHECK(init_display_buffer());
|
init_touch_optional();
|
||||||
ESP_ERROR_CHECK(display_standard_diagnostic());
|
ESP_ERROR_CHECK(init_lvgl(panel_io));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ CONFIG_LV_FONT_MONTSERRAT_18=y
|
|||||||
CONFIG_ESP_LCD_TOUCH_MAX_POINTS=5
|
CONFIG_ESP_LCD_TOUCH_MAX_POINTS=5
|
||||||
CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS=0
|
CONFIG_ESP_LCD_TOUCH_MAX_BUTTONS=0
|
||||||
CONFIG_FREERTOS_HZ=1000
|
CONFIG_FREERTOS_HZ=1000
|
||||||
|
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
||||||
|
CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||||
CONFIG_IDF_TARGET="esp32s3"
|
CONFIG_IDF_TARGET="esp32s3"
|
||||||
CONFIG_EXAMPLE_LCD_CONTROLLER_ST7789=y
|
CONFIG_EXAMPLE_LCD_CONTROLLER_ST7789=y
|
||||||
CONFIG_EXAMPLE_LCD_ST7735_H_RES=240
|
CONFIG_EXAMPLE_LCD_ST7735_H_RES=240
|
||||||
|
|||||||
Reference in New Issue
Block a user