Closed krupis closed 1 year ago
Hello, the touch driver for CST816 is here: https://components.espressif.com/components/espressif/esp_lcd_touch_cst816s
Hello, the touch driver for CST816 is here: https://components.espressif.com/components/espressif/esp_lcd_touch_cst816s
Thanks for quick reply. Is CST816 the same as CST816S? Because the driver that you linked is for CST816S.
Regardless, I have tried to use this touch driver. My full function that initializes the LVGL Display:
void lvgl_setup()
{
gpio_config_t pwr_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_POWER};
ESP_ERROR_CHECK(gpio_config(&pwr_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_POWER, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
gpio_config_t input_conf =
{
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pin_bit_mask = 1ULL << PIN_LCD_RD};
ESP_ERROR_CHECK(gpio_config(&input_conf));
gpio_config_t bk_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
static lv_disp_drv_t disp_drv; // contains callback functions
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.dc_gpio_num = EXAMPLE_PIN_NUM_DC,
.wr_gpio_num = EXAMPLE_PIN_NUM_PCLK,
.data_gpio_nums = {
EXAMPLE_PIN_NUM_DATA0,
EXAMPLE_PIN_NUM_DATA1,
EXAMPLE_PIN_NUM_DATA2,
EXAMPLE_PIN_NUM_DATA3,
EXAMPLE_PIN_NUM_DATA4,
EXAMPLE_PIN_NUM_DATA5,
EXAMPLE_PIN_NUM_DATA6,
EXAMPLE_PIN_NUM_DATA7,
},
.bus_width = 8,
.max_transfer_bytes = LVGL_LCD_BUF_SIZE * sizeof(uint16_t)
//.psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
//.sram_trans_align = 4,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
.trans_queue_depth = 20,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,
},
.on_color_trans_done = example_notify_lvgl_flush_ready,
.user_ctx = &disp_drv,
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
esp_lcd_panel_handle_t panel_handle = NULL;
ESP_LOGI(TAG, "Install LCD driver of st7789");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = ESP_LCD_COLOR_SPACE_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
// ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
// ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));
// ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, true));
// ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, 0, 35));
esp_lcd_panel_invert_color(panel_handle, true);
esp_lcd_panel_swap_xy(panel_handle, true);
esp_lcd_panel_mirror(panel_handle, false, true);
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
esp_lcd_panel_set_gap(panel_handle, 0, 35);
esp_lcd_panel_io_tx_param(io_handle, 0xF2, (uint8_t[]){0}, 1); // 3Gamma function disable
esp_lcd_panel_io_tx_param(io_handle, 0x26, (uint8_t[]){1}, 1); // Gamma curve 1 selected
esp_lcd_panel_io_tx_param(io_handle, 0xE0, (uint8_t[]){ // Set positive gamma
0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00},
15);
esp_lcd_panel_io_tx_param(io_handle, 0xE1, (uint8_t[]){// Set negative gamma
0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F},
15);
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
//TOUCH FUNCTIONS
esp_lcd_touch_handle_t tp = NULL;
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
const i2c_config_t i2c_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = EXAMPLE_I2C_SDA,
.scl_io_num = EXAMPLE_I2C_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000,
};
ESP_LOGI(TAG,"Initializing I2C for display touch");
/* Initialize I2C */
ESP_ERROR_CHECK(i2c_param_config(EXAMPLE_I2C_NUM, &i2c_conf));
ESP_ERROR_CHECK(i2c_driver_install(EXAMPLE_I2C_NUM, i2c_conf.mode, 0, 0, 0));
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
ESP_LOGI(TAG,"esp_lcd_new_panel_io_i2c");
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)EXAMPLE_I2C_NUM, &tp_io_config, &tp_io_handle));
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
ESP_LOGI(TAG,"esp_lcd_touch_new_i2c_cst816s");
esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp);
// static lv_indev_drv_t indev_drv; // Input device driver (Touch)
// lv_indev_drv_init(&indev_drv);
// indev_drv.type = LV_INDEV_TYPE_POINTER;
// indev_drv.disp = disp;
// indev_drv.read_cb = example_lvgl_touch_cb;
// indev_drv.user_data = tp;
// lv_indev_drv_register(&indev_drv);
//END TOUCH FUNCTIONS
lv_init();
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
lv_color_t *buf1 = heap_caps_malloc(LVGL_LCD_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1);
lv_disp_draw_buf_init(&disp_buf, buf1, NULL, LVGL_LCD_BUF_SIZE);
ESP_LOGI(TAG, "Register display driver to LVGL");
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = EXAMPLE_LCD_H_RES;
disp_drv.ver_res = EXAMPLE_LCD_V_RES;
disp_drv.flush_cb = example_lvgl_flush_cb;
disp_drv.draw_buf = &disp_buf;
disp_drv.user_data = panel_handle;
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
ESP_LOGI(TAG, "Install LVGL tick timer");
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
const esp_timer_create_args_t lvgl_tick_timer_args = {
.callback = &example_increase_lvgl_tick,
.name = "lvgl_tick"};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
xTaskCreatePinnedToCore(lvgl_timer_task, "lvgl Timer", 10000, NULL, 4, NULL, 1);
}
The display itself works without any issues. I can display images and etc using LVGL. Lets have a look at functions I use to initialize touch display:
#define EXAMPLE_I2C_NUM 0 // I2C number
#define EXAMPLE_I2C_SCL 18
#define EXAMPLE_I2C_SDA 17
//TOUCH FUNCTIONS
esp_lcd_touch_handle_t tp = NULL;
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
const i2c_config_t i2c_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = EXAMPLE_I2C_SDA,
.scl_io_num = EXAMPLE_I2C_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000,
};
ESP_LOGI(TAG,"Initializing I2C for display touch");
/* Initialize I2C */
ESP_ERROR_CHECK(i2c_param_config(EXAMPLE_I2C_NUM, &i2c_conf));
ESP_ERROR_CHECK(i2c_driver_install(EXAMPLE_I2C_NUM, i2c_conf.mode, 0, 0, 0));
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
ESP_LOGI(TAG,"esp_lcd_new_panel_io_i2c");
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)EXAMPLE_I2C_NUM, &tp_io_config, &tp_io_handle));
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
ESP_LOGI(TAG,"esp_lcd_touch_new_i2c_cst816s");
esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp);
I get the following errors printed in the console:
[1B][0;32mI (505) LVGL_SETUP: esp_lcd_new_panel_io_i2c[1B][0m
[1B][0;32mI (505) LVGL_SETUP: esp_lcd_touch_new_i2c_cst816s[1B][0m
[1B][0;32mI (505) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (515) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2 [1B][0m
[1B][0;31mE (545) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (545) CST816S: read_id(174): I2C read failed[1B][0m
[1B][0;31mE (545) CST816S: esp_lcd_touch_new_i2c_cst816s(84): Read version failed[1B][0m
[1B][0;32mI (545) gpio: GPIO[16]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (555) gpio: GPIO[21]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;31mE (565) CST816S: Initialization failed![1B][0m
It does not seem to be able to read the i2c device id:
[1B][0;31mE (545) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (545) CST816S: read_id(174): I2C read failed[1B][0m
[1B][0;31mE (545) CST816S: esp_lcd_touch_new_i2c_cst816s(84): Read version failed[1B][0m
Hello,
it seems, that CST816
and CST816S
are same. Same address and same registers. I haven't got same board and I cannot test it now. It seems, you have mistake in GPIOS on I2C. It should be like here:
#define EXAMPLE_I2C_SCL 17
#define EXAMPLE_I2C_SDA 18
Hello, it seems, that
CST816
andCST816S
are same. Same address and same registers. I haven't got same board and I cannot test it now. It seems, you have mistake in GPIOS on I2C. It should be like here:#define EXAMPLE_I2C_SCL 17 #define EXAMPLE_I2C_SDA 18
Thanks for your response. I still havent been able to get it running. Can you confirm where did you get these I2C GPIO declaration. I have declared:
#define EXAMPLE_I2C_SCL 18
#define EXAMPLE_I2C_SDA 17
And that is correct according to the
Anyways, I have tried to reconfigure but getting the identical error in the terminal.
I found it on the schematics: https://github.com/Xinyuan-LilyGO/T-Display-S3/blob/main/schematic/T_Display_S3.pdf
I found it on the schematics: https://github.com/Xinyuan-LilyGO/T-Display-S3/blob/main/schematic/T_Display_S3.pdf
Yeah you are right. In the schematic it shows the following:
but in the Readme.md it shows the following:
Lets hope to hear from someone who managed to get it to work on the esp-idf.
@Lzw655 please, could you help with this? I haven't got HW for CST816 touch.
How is it going regarding the CST816 touch driver? Has there been any updates ?
Highly appreciate!
@krupis Sorry for being late. I have an LCD with CST816 touch in the home and I'll use it to test the driver tomorrow. Please wait another day.
But we can do some tests first. You can run the below codes and check the I2C address of the touch.
i2c_cmd_handle_t cmd;
for (int i = 0; i < 0x7f; i++) {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
if (i2c_master_cmd_begin(BSP_I2C_NUM, cmd, portMAX_DELAY) == ESP_OK) {
ESP_LOGW(TAG, "%02X", i);
}
i2c_cmd_link_delete(cmd);
}
i2c_cmd_handle_t cmd; for (int i = 0; i < 0x7f; i++) { cmd = i2c_cmd_link_create(); i2c_master_start(cmd); i2c_master_write_byte(cmd, (i << 1) | I2C_MASTER_WRITE, true); i2c_master_stop(cmd); if (i2c_master_cmd_begin(BSP_I2C_NUM, cmd, portMAX_DELAY) == ESP_OK) { ESP_LOGW(TAG, "%02X", i); } i2c_cmd_link_delete(cmd); }
Not a problem at all.
Do you have a T-Display-S3 from Lilygo or some custom board?
I have tried to run the command that you have suggested. I have a public repository for testing CST816 that here: https://github.com/krupis/T-Display-S3-esp-idf
I have a lvgl_setup function that is being called in main.c to initialise the whole display:
void lvgl_setup()
{
gpio_config_t pwr_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_POWER};
ESP_ERROR_CHECK(gpio_config(&pwr_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_POWER, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
gpio_config_t input_conf =
{
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pin_bit_mask = 1ULL << PIN_LCD_RD};
ESP_ERROR_CHECK(gpio_config(&input_conf));
gpio_config_t bk_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
static lv_disp_drv_t disp_drv; // contains callback functions
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.dc_gpio_num = EXAMPLE_PIN_NUM_DC,
.wr_gpio_num = EXAMPLE_PIN_NUM_PCLK,
.data_gpio_nums = {
EXAMPLE_PIN_NUM_DATA0,
EXAMPLE_PIN_NUM_DATA1,
EXAMPLE_PIN_NUM_DATA2,
EXAMPLE_PIN_NUM_DATA3,
EXAMPLE_PIN_NUM_DATA4,
EXAMPLE_PIN_NUM_DATA5,
EXAMPLE_PIN_NUM_DATA6,
EXAMPLE_PIN_NUM_DATA7,
},
.bus_width = 8,
.max_transfer_bytes = LVGL_LCD_BUF_SIZE * sizeof(uint16_t)
//.psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
//.sram_trans_align = 4,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
.trans_queue_depth = 20,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,
},
.on_color_trans_done = example_notify_lvgl_flush_ready,
.user_ctx = &disp_drv,
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
esp_lcd_panel_handle_t panel_handle = NULL;
ESP_LOGI(TAG, "Install LCD driver of st7789");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = ESP_LCD_COLOR_SPACE_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
// ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
// ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));
// ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, true));
// ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, 0, 35));
esp_lcd_panel_invert_color(panel_handle, true);
esp_lcd_panel_swap_xy(panel_handle, true);
esp_lcd_panel_mirror(panel_handle, false, true);
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
esp_lcd_panel_set_gap(panel_handle, 0, 35);
esp_lcd_panel_io_tx_param(io_handle, 0xF2, (uint8_t[]){0}, 1); // 3Gamma function disable
esp_lcd_panel_io_tx_param(io_handle, 0x26, (uint8_t[]){1}, 1); // Gamma curve 1 selected
esp_lcd_panel_io_tx_param(io_handle, 0xE0, (uint8_t[]){ // Set positive gamma
0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00},
15);
esp_lcd_panel_io_tx_param(io_handle, 0xE1, (uint8_t[]){// Set negative gamma
0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F},
15);
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
lv_init();
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
lv_color_t *buf1 = heap_caps_malloc(LVGL_LCD_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1);
lv_disp_draw_buf_init(&disp_buf, buf1, NULL, LVGL_LCD_BUF_SIZE);
ESP_LOGI(TAG, "Register display driver to LVGL");
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = EXAMPLE_LCD_H_RES;
disp_drv.ver_res = EXAMPLE_LCD_V_RES;
disp_drv.flush_cb = example_lvgl_flush_cb;
disp_drv.draw_buf = &disp_buf;
disp_drv.user_data = panel_handle;
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
ESP_LOGI(TAG, "Install LVGL tick timer");
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
const esp_timer_create_args_t lvgl_tick_timer_args = {
.callback = &example_increase_lvgl_tick,
.name = "lvgl_tick"};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
xTaskCreatePinnedToCore(lvgl_timer_task, "lvgl Timer", 10000, NULL, 4, NULL, 1);
//CST816 TOUCH TESTING
esp_lcd_touch_handle_t tp = NULL;
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
i2c_config_t i2c_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = EXAMPLE_I2C_SDA,
.scl_io_num = EXAMPLE_I2C_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000,
};
ESP_LOGI(TAG,"Initializing I2C for display touch");
/* Initialize I2C */
ESP_ERROR_CHECK(i2c_param_config(EXAMPLE_I2C_NUM, &i2c_conf));
ESP_ERROR_CHECK(i2c_driver_install(EXAMPLE_I2C_NUM, i2c_conf.mode, 0, 0, 0));
i2c_cmd_handle_t cmd;
for (int i = 0; i < 0x7f; i++) {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
if (i2c_master_cmd_begin(EXAMPLE_I2C_NUM, cmd, portMAX_DELAY) == ESP_OK) {
ESP_LOGW(TAG, "%02X", i);
}
i2c_cmd_link_delete(cmd);
}
}
As you can see at the end of my lvgl_setup, I have added the following functions:
i2c_config_t i2c_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = EXAMPLE_I2C_SDA,
.scl_io_num = EXAMPLE_I2C_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000,
};
ESP_LOGI(TAG,"Initializing I2C for display touch");
/* Initialize I2C */
ESP_ERROR_CHECK(i2c_param_config(EXAMPLE_I2C_NUM, &i2c_conf));
ESP_ERROR_CHECK(i2c_driver_install(EXAMPLE_I2C_NUM, i2c_conf.mode, 0, 0, 0));
i2c_cmd_handle_t cmd;
for (int i = 0; i < 0x7f; i++) {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
if (i2c_master_cmd_begin(EXAMPLE_I2C_NUM, cmd, portMAX_DELAY) == ESP_OK) {
ESP_LOGW(TAG, "%02X", i);
}
i2c_cmd_link_delete(cmd);
}
And when I flash my device, it does not seem to return any errors:
[1B][0;32mI (122) esp_image: segment 3: paddr=00030020 vaddr=420000
[1B][0;32mI (221) cpu_start: Project name: i80_controller[1B][0m
[1B][0;32mI (227) cpu_start: App version: 5552b0b-dirty[1B][0m
[1B][0;32mI (232) cpu_start: Compile time: Jun 13 2023 10:05:43[1B][0m
[1B][0;32mI (239) cpu_start: ELF file SHA256: a573f2e0a487791a...[1B][0m
[1B][0;32mI (245) cpu_start: ESP-IDF: v5.0.1-dirty[1B][0m
[1B][0;32mI (250) cpu_start: Min chip rev: v0.0[1B][0m
[1B][0;32mI (255) cpu_start: Max chip rev: v0.99 [1B][0m
[1B][0;32mI (259) cpu_start: Chip rev: v0.1[1B][0m
[1B][0;32mI (264) heap_init: Initializing. RAM available for dynamic allocation:[1B][0m
[1B][0;32mI (271) heap_init: At 3FC96598 len 00053178 (332 KiB): D/IRAM[1B][0m
[1B][0;32mI (278) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM[1B][0m
[1B][0;32mI (284) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM[1B][0m
[1B][0;32mI (291) heap_init: At 600FE010 len 00001FF0 (7 KiB): RTCRAM[1B][0m
[1B][0;32mI (298) spi_flash: detected chip: winbond[1B][0m
[1B][0;32mI (302) spi_flash: flash io: dio[1B][0m
[1B][0;33mW (306) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.[1B][0m
[1B][0;32mI (319) cpu_start: Starting scheduler on PRO CPU.[1B][0m
[1B][0;32mI (0) cpu_start: Starting scheduler on APP CPU.[1B][0m
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.1, 2MB external flash
Minimum free heap size: 379836 bytes
[1B][0;32mI (381) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (391) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (391) gpio: GPIO[38]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (401) LVGL_SETUP: Initialize Intel 8080 bus[1B][0m
[1B][0;32mI (411) LVGL_SETUP: Install LCD driver of st7789[1B][0m
[1B][0;32mI (411) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (541) LVGL_SETUP: Register display driver to LVGL[1B][0m
[1B][0;32mI (541) LVGL_SETUP: Install LVGL tick timer[1B][0m
[1B][0;32mI (541) LVGL_SETUP: Initializing I2C for display touch[1B][0m
I am guessing that's a good sign.
But when I try to call the functions to initialize CST816 driver:
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
ESP_LOGI(TAG,"esp_lcd_new_panel_io_i2c");
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)EXAMPLE_I2C_NUM, &tp_io_config, &tp_io_handle));
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
ESP_LOGI(TAG,"esp_lcd_touch_new_i2c_cst816s");
esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp);
I am getting errors:
[1B][0;32mI (539) LVGL_SETUP: Register display driver to LVGL[1B][0m
[1B][0;32mI (539) LVGL_SETUP: Install LVGL tick timer[1B][0m
[1B][0;32mI (539) LVGL_SETUP: Initializing I2C for display touch[1B][0m
[1B][0;32mI (539) LVGL_SETUP: esp_lcd_new_panel_io_i2c[1B][0m
[1B][0;32mI (549) LVGL_SETUP: esp_lcd_touch_new_i2c_cst816s[1B][0m
[1B][0;32mI (549) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (559) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2 [1B][0m
[1B][0;31mE (589) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (589) CST816S: read_id(174): I2C read failed[1B][0m
[1B][0;31mE (589) CST816S: esp_lcd_touch_new_i2c_cst816s(84): Read version failed[1B][0m
[1B][0;32mI (589) gpio: GPIO[16]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (599) gpio: GPIO[21]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;31mE (609) CST816S: Initialization failed![1B][0m
If you want, you can try use my example project to get going from your side. The display seems to work fine (I can display images and other things on the display with that example project). It is just the Display that I am struggling with.
Well, I only have a custom board.
The given code is used to probe and print the I2C address of touch IC. But according to your results as below, there is no address (like 0x15) that can be found.
[1B][0;32mI (122) esp_image: segment 3: paddr=00030020 vaddr=420000
[1B][0;32mI (221) cpu_start: Project name: i80_controller[1B][0m
[1B][0;32mI (227) cpu_start: App version: 5552b0b-dirty[1B][0m
[1B][0;32mI (232) cpu_start: Compile time: Jun 13 2023 10:05:43[1B][0m
[1B][0;32mI (239) cpu_start: ELF file SHA256: a573f2e0a487791a...[1B][0m
[1B][0;32mI (245) cpu_start: ESP-IDF: v5.0.1-dirty[1B][0m
[1B][0;32mI (250) cpu_start: Min chip rev: v0.0[1B][0m
[1B][0;32mI (255) cpu_start: Max chip rev: v0.99 [1B][0m
[1B][0;32mI (259) cpu_start: Chip rev: v0.1[1B][0m
[1B][0;32mI (264) heap_init: Initializing. RAM available for dynamic allocation:[1B][0m
[1B][0;32mI (271) heap_init: At 3FC96598 len 00053178 (332 KiB): D/IRAM[1B][0m
[1B][0;32mI (278) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM[1B][0m
[1B][0;32mI (284) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM[1B][0m
[1B][0;32mI (291) heap_init: At 600FE010 len 00001FF0 (7 KiB): RTCRAM[1B][0m
[1B][0;32mI (298) spi_flash: detected chip: winbond[1B][0m
[1B][0;32mI (302) spi_flash: flash io: dio[1B][0m
[1B][0;33mW (306) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.[1B][0m
[1B][0;32mI (319) cpu_start: Starting scheduler on PRO CPU.[1B][0m
[1B][0;32mI (0) cpu_start: Starting scheduler on APP CPU.[1B][0m
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.1, 2MB external flash
Minimum free heap size: 379836 bytes
[1B][0;32mI (381) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (391) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (391) gpio: GPIO[38]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (401) LVGL_SETUP: Initialize Intel 8080 bus[1B][0m
[1B][0;32mI (411) LVGL_SETUP: Install LCD driver of st7789[1B][0m
[1B][0;32mI (411) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (541) LVGL_SETUP: Register display driver to LVGL[1B][0m
[1B][0;32mI (541) LVGL_SETUP: Install LVGL tick timer[1B][0m
[1B][0;32mI (541) LVGL_SETUP: Initializing I2C for display touch[1B][0m
So I suspect that there is a problem with your I2C pins. You can try to swap the gpio of SDA and SCL, then run the given code again. If there is no address to be printed, maybe the hardware has some problems. Do you have another board to test?
@Lzw655
I have tried to swap the SDA and SCL pins around but the results are the same.
It is most definately not the HW related issue since I can run the LilyGO provided example code based on Arduino IDE and the Touch works fine. Unfortunately, I do not prefer the Arduino IDE and I am hoping to get it working on the esp-idf.
Hello, I have the exact same issue with also the T-Display-S3, I have tested your code suggestion for swapping pin and it does not work. It also work fine with Arduino IDE on my side Seb
@krupis @C-basstien Get it. Let me take a look at the code in Arduino.
@Lzw655
UPDATE As I was testing out the I2C, I have found out a few things: There is a RES (IO 21) pin on the T-Display-S3 display.
I have toggled it HIGH before scanning the i2c devices and it detected 0x15 I2C device.
My lvgl_setup looks like: (Notice I added setting IO 21 high and also reorganized where I call the I2C functions)
void lvgl_setup()
{
gpio_config_t pwr_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_POWER};
ESP_ERROR_CHECK(gpio_config(&pwr_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_POWER, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
gpio_config_t input_conf =
{
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pin_bit_mask = 1ULL << PIN_LCD_RD};
ESP_ERROR_CHECK(gpio_config(&input_conf));
gpio_config_t bk_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
//CST816 TOUCH TESTING FUNCTION
gpio_config_t touch_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << PIN_TOUCH_RES};
ESP_ERROR_CHECK(gpio_config(&touch_gpio_config));
gpio_set_level(PIN_TOUCH_RES, 1);
//END OF CST816 TOUCH TESTING FUNCTION
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
static lv_disp_drv_t disp_drv; // contains callback functions
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.dc_gpio_num = EXAMPLE_PIN_NUM_DC,
.wr_gpio_num = EXAMPLE_PIN_NUM_PCLK,
.data_gpio_nums = {
EXAMPLE_PIN_NUM_DATA0,
EXAMPLE_PIN_NUM_DATA1,
EXAMPLE_PIN_NUM_DATA2,
EXAMPLE_PIN_NUM_DATA3,
EXAMPLE_PIN_NUM_DATA4,
EXAMPLE_PIN_NUM_DATA5,
EXAMPLE_PIN_NUM_DATA6,
EXAMPLE_PIN_NUM_DATA7,
},
.bus_width = 8,
.max_transfer_bytes = LVGL_LCD_BUF_SIZE * sizeof(uint16_t)
//.psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
//.sram_trans_align = 4,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
.trans_queue_depth = 20,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,
},
.on_color_trans_done = example_notify_lvgl_flush_ready,
.user_ctx = &disp_drv,
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
esp_lcd_panel_handle_t panel_handle = NULL;
ESP_LOGI(TAG, "Install LCD driver of st7789");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = ESP_LCD_COLOR_SPACE_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
// ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
// ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));
// ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, true));
// ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, 0, 35));
esp_lcd_panel_invert_color(panel_handle, true);
esp_lcd_panel_swap_xy(panel_handle, true);
esp_lcd_panel_mirror(panel_handle, false, true);
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
esp_lcd_panel_set_gap(panel_handle, 0, 35);
esp_lcd_panel_io_tx_param(io_handle, 0xF2, (uint8_t[]){0}, 1); // 3Gamma function disable
esp_lcd_panel_io_tx_param(io_handle, 0x26, (uint8_t[]){1}, 1); // Gamma curve 1 selected
esp_lcd_panel_io_tx_param(io_handle, 0xE0, (uint8_t[]){ // Set positive gamma
0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00},
15);
esp_lcd_panel_io_tx_param(io_handle, 0xE1, (uint8_t[]){// Set negative gamma
0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F},
15);
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
//CST816 TOUCH TESTING FUNCTION
esp_lcd_touch_handle_t tp = NULL;
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
i2c_config_t i2c_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = EXAMPLE_I2C_SDA,
.scl_io_num = EXAMPLE_I2C_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000,
};
ESP_LOGI(TAG,"Initializing I2C for display touch");
/* Initialize I2C */
ESP_ERROR_CHECK(i2c_param_config(EXAMPLE_I2C_NUM, &i2c_conf));
ESP_ERROR_CHECK(i2c_driver_install(EXAMPLE_I2C_NUM, i2c_conf.mode, 0, 0, 0));
i2c_cmd_handle_t cmd;
for (int i = 0; i < 0x7f; i++) {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
if (i2c_master_cmd_begin(EXAMPLE_I2C_NUM, cmd, portMAX_DELAY) == ESP_OK) {
ESP_LOGW("I2C_TEST", "%02X", i);
}
i2c_cmd_link_delete(cmd);
}
//END OF CST816 TOUCH TESTING FUNCTION
lv_init();
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
lv_color_t *buf1 = heap_caps_malloc(LVGL_LCD_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1);
lv_disp_draw_buf_init(&disp_buf, buf1, NULL, LVGL_LCD_BUF_SIZE);
ESP_LOGI(TAG, "Register display driver to LVGL");
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = EXAMPLE_LCD_H_RES;
disp_drv.ver_res = EXAMPLE_LCD_V_RES;
disp_drv.flush_cb = example_lvgl_flush_cb;
disp_drv.draw_buf = &disp_buf;
disp_drv.user_data = panel_handle;
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
ESP_LOGI(TAG, "Install LVGL tick timer");
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
const esp_timer_create_args_t lvgl_tick_timer_args = {
.callback = &example_increase_lvgl_tick,
.name = "lvgl_tick"};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
xTaskCreatePinnedToCore(lvgl_timer_task, "lvgl Timer", 10000, NULL, 4, NULL, 1);
}
The serial console output:
[1B][0;32mI (122) esp_image: segment 3: paddr=00030020 vaddr=420000ation:[1B][0m
[1B][0;32mI (221) cpu_start: Project name: i80_controller[1B][0m
[1B][0;32mI (227) cpu_start: App version: 4803def-dirty[1B][0m
[1B][0;32mI (232) cpu_start: Compile time: Jun 13 2023 10:23:08[1B][0m
[1B][0;32mI (239) cpu_start: ELF file SHA256: 4653f03e400515cd...[1B][0m
[1B][0;32mI (245) cpu_start: ESP-IDF: v5.0.1-dirty[1B][0m
[1B][0;32mI (250) cpu_start: Min chip rev: v0.0[1B][0m
[1B][0;32mI (255) cpu_start: Max chip rev: v0.99 [1B][0m
[1B][0;32mI (259) cpu_start: Chip rev: v0.1[1B][0m
[1B][0;32mI (264) heap_init: Initializing. RAM available for dynamic allocation:[1B][0m
[1B][0;32mI (272) heap_init: At 3FC96598 len 00053178 (332 KiB): D/IRAM[1B][0m
[1B][0;32mI (278) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM[1B][0m
[1B][0;32mI (284) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM[1B][0m
[1B][0;32mI (291) heap_init: At 600FE010 len 00001FF0 (7 KiB): RTCRAM[1B][0m
[1B][0;32mI (298) spi_flash: detected chip: winbond[1B][0m
[1B][0;32mI (302) spi_flash: flash io: dio[1B][0m
[1B][0;33mW (306) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.[1B][0m
[1B][0;32mI (320) cpu_start: Starting scheduler on PRO CPU.[1B][0m
[1B][0;32mI (0) cpu_start: Starting scheduler on APP CPU.[1B][0m
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.1, 2MB external flash
Minimum free heap size: 379836 bytes
[1B][0;32mI (381) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (391) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (391) gpio: GPIO[38]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (401) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (411) LVGL_SETUP: Initialize Intel 8080 bus[1B][0m
[1B][0;32mI (421) LVGL_SETUP: Install LCD driver of st7789[1B][0m
[1B][0;32mI (421) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (551) LVGL_SETUP: Initializing I2C for display touch[1B][0m
[1B][0;33mW (551) I2C_TEST: 15[1B][0m
[1B][0;32mI (561) LVGL_SETUP: Register display driver to LVGL[1B][0m
[1B][0;32mI (561) LVGL_SETUP: Install LVGL tick timer[1B][0m
That is a good sign, device with 0x15 address was found.
Now I replace
i2c_cmd_handle_t cmd;
for (int i = 0; i < 0x7f; i++) {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
if (i2c_master_cmd_begin(EXAMPLE_I2C_NUM, cmd, portMAX_DELAY) == ESP_OK) {
ESP_LOGW("I2C_TEST", "%02X", i);
}
i2c_cmd_link_delete(cmd);
}
with :
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
ESP_LOGI(TAG,"esp_lcd_new_panel_io_i2c");
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)EXAMPLE_I2C_NUM, &tp_io_config, &tp_io_handle));
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 1,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
ESP_LOGI(TAG,"esp_lcd_touch_new_i2c_cst816s");
esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp);
The result:
[1B][0;32mI (549) LVGL_SETUP: Initializing I2C for display touch[1B][0m
[1B][0;32mI (549) LVGL_SETUP: esp_lcd_new_panel_io_i2c[1B][0m
[1B][0;32mI (549) LVGL_SETUP: esp_lcd_touch_new_i2c_cst816s[1B][0m
[1B][0;32mI (549) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (559) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2 [1B][0m
[1B][0;31mE (589) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (589) CST816S: read_id(174): I2C read failed[1B][0m
[1B][0;31mE (589) CST816S: esp_lcd_touch_new_i2c_cst816s(84): Read version failed[1B][0m
I try to play with esp_lcd_touch_config_t
Replace:
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 1,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
With
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = -1,
.int_gpio_num = -1,
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
The serial console output:
[1B][0;32mI (382) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (392) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (392) gpio: GPIO[38]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (402) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (412) LVGL_SETUP: Initialize Intel 8080 bus[1B][0m
[1B][0;32mI (422) LVGL_SETUP: Install LCD driver of st7789[1B][0m
[1B][0;32mI (422) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (552) LVGL_SETUP: Initializing I2C for display touch[1B][0m
[1B][0;32mI (552) LVGL_SETUP: esp_lcd_new_panel_io_i2c[1B][0m
[1B][0;32mI (552) LVGL_SETUP: esp_lcd_touch_new_i2c_cst816s[1B][0m
[1B][0;32mI (552) CST816S: IC id: 181[1B][0m
[1B][0;32mI (552) LVGL_SETUP: Register display driver to LVGL[1B][0m
[1B][0;32mI (562) LVGL_SETUP: Install LVGL tick timer[1B][0m
There are no more error messages. I am very confused. What was the issue with my initial esp_lcd_touch_config_t declaration.
@krupis Thanks for your patient test. I just notice that the RST
should be set to high first.
And according to your results, I find an error in the source code. Line 71 should be placed to line 64. It may cause the level of RST
not right.
https://github.com/espressif/esp-bsp/blob/22aa83177ed0affa79853081cc113fac09dd83cc/components/lcd_touch/esp_lcd_touch_cst816s/esp_lcd_touch_cst816s.c#L60-L80
Can you help me to verify it? If success, I'll fix it now.
For this test, do you want me to remove the below from my code?
gpio_config_t touch_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << PIN_TOUCH_RES};
ESP_ERROR_CHECK(gpio_config(&touch_gpio_config));
gpio_set_level(PIN_TOUCH_RES, 1);
For the time being, i didint remove the above.
Since I made changes in the managed component, I can no longer build the project
ERROR: Some components (espressif/esp_lcd_touch_cst816s) in the
"managed_components" directory were modified on the disk since the last run
of the CMake. Content of this directory is managed automatically.
If you want to keep the changes, you can move the directory with the
component to the "components"directory of your project.
I.E. for "espressif__esp_lcd_touch_cst816s" run:
mv
C:\Users\petrikas.lu\Desktop\WORK\ESP32\T-Display-S3-test\T-Display-S3-esp-idf\managed_components\espressif__esp_lcd_touch_cst816s
C:\Users\petrikas.lu\Desktop\WORK\ESP32\T-Display-S3-test\T-Display-S3-esp-idf\components\espressif__esp_lcd_touch_cst816s
Or, if you want to discard the changes remove the ".component_hash" file
from the component's directory.
I.E. for "espressif__esp_lcd_touch_cst816s" run:
rm
C:\Users\petrikas.lu\Desktop\WORK\ESP32\T-Display-S3-test\T-Display-S3-esp-idf\managed_components\espressif__esp_lcd_touch_cst816s\.component_hash
It tells me to copy the cst816s managed component and place it to my components folder. I just manually cloned the whole espressif__esp_lcd_touch_cst816s folder and moved it into my components folder.
After building and flashing the device, It seems that it still does not work with the below esp_lcd_touch_config_t
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 1,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
[1B][0;32mI (557) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2 [1B][0m
[1B][0;32mI (567) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;31mE (597) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (597) CST816S: read_id(176): I2C read failed[1B][0m
[1B][0;31mE (597) CST816S: esp_lcd_touch_new_i2c_cst816s(86): Read version failed[1B][0m
[1B][0;32mI (597) gpio: GPIO[16]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (607) gpio: GPIO[21]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;31mE (617) CST816S: Initialization failed![1B][0m
There seems to be an issue with the rst pin.
The below works without any issues
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = -1,
.int_gpio_num = 16,
.levels = {
//.reset = 1,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
However, this one do not:
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 1,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
Keep in mind that I still have my:
#define PIN_TOUCH_RES 21
gpio_config_t touch_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << PIN_TOUCH_RES};
ESP_ERROR_CHECK(gpio_config(&touch_gpio_config));
gpio_set_level(PIN_TOUCH_RES, 1);
at the beggining of the lvgl_setup
I have updated the code in my repository. You can have a look for full source code there
@krupis Please remove:
#define PIN_TOUCH_RES 21
gpio_config_t touch_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << PIN_TOUCH_RES};
ESP_ERROR_CHECK(gpio_config(&touch_gpio_config));
gpio_set_level(PIN_TOUCH_RES, 1);
And try the code (.reset = 0):
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
I tried your suggestion. My lvgl_setup:
void lvgl_setup()
{
gpio_config_t pwr_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_POWER};
ESP_ERROR_CHECK(gpio_config(&pwr_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_POWER, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
gpio_config_t input_conf =
{
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pin_bit_mask = 1ULL << PIN_LCD_RD};
ESP_ERROR_CHECK(gpio_config(&input_conf));
gpio_config_t bk_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
//CST816 TOUCH TESTING FUNCTION
// gpio_config_t touch_gpio_config =
// {
// .mode = GPIO_MODE_OUTPUT,
// .pin_bit_mask = 1ULL << PIN_TOUCH_RES};
// ESP_ERROR_CHECK(gpio_config(&touch_gpio_config));
// gpio_set_level(PIN_TOUCH_RES, 1);
//END OF CST816 TOUCH TESTING FUNCTION
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
static lv_disp_drv_t disp_drv; // contains callback functions
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.dc_gpio_num = EXAMPLE_PIN_NUM_DC,
.wr_gpio_num = EXAMPLE_PIN_NUM_PCLK,
.data_gpio_nums = {
EXAMPLE_PIN_NUM_DATA0,
EXAMPLE_PIN_NUM_DATA1,
EXAMPLE_PIN_NUM_DATA2,
EXAMPLE_PIN_NUM_DATA3,
EXAMPLE_PIN_NUM_DATA4,
EXAMPLE_PIN_NUM_DATA5,
EXAMPLE_PIN_NUM_DATA6,
EXAMPLE_PIN_NUM_DATA7,
},
.bus_width = 8,
.max_transfer_bytes = LVGL_LCD_BUF_SIZE * sizeof(uint16_t)
//.psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
//.sram_trans_align = 4,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
.trans_queue_depth = 20,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,
},
.on_color_trans_done = example_notify_lvgl_flush_ready,
.user_ctx = &disp_drv,
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
esp_lcd_panel_handle_t panel_handle = NULL;
ESP_LOGI(TAG, "Install LCD driver of st7789");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = ESP_LCD_COLOR_SPACE_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
// ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
// ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));
// ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, false, true));
// ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel_handle, 0, 35));
esp_lcd_panel_invert_color(panel_handle, true);
esp_lcd_panel_swap_xy(panel_handle, true);
esp_lcd_panel_mirror(panel_handle, false, true);
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
esp_lcd_panel_set_gap(panel_handle, 0, 35);
esp_lcd_panel_io_tx_param(io_handle, 0xF2, (uint8_t[]){0}, 1); // 3Gamma function disable
esp_lcd_panel_io_tx_param(io_handle, 0x26, (uint8_t[]){1}, 1); // Gamma curve 1 selected
esp_lcd_panel_io_tx_param(io_handle, 0xE0, (uint8_t[]){ // Set positive gamma
0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00},
15);
esp_lcd_panel_io_tx_param(io_handle, 0xE1, (uint8_t[]){// Set negative gamma
0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F},
15);
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
//CST816 TOUCH TESTING FUNCTION
esp_lcd_touch_handle_t tp = NULL;
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
i2c_config_t i2c_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = EXAMPLE_I2C_SDA,
.scl_io_num = EXAMPLE_I2C_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000,
};
ESP_LOGI(TAG,"Initializing I2C for display touch");
/* Initialize I2C */
ESP_ERROR_CHECK(i2c_param_config(EXAMPLE_I2C_NUM, &i2c_conf));
ESP_ERROR_CHECK(i2c_driver_install(EXAMPLE_I2C_NUM, i2c_conf.mode, 0, 0, 0));
i2c_cmd_handle_t cmd;
for (int i = 0; i < 0x7f; i++) {
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
if (i2c_master_cmd_begin(EXAMPLE_I2C_NUM, cmd, portMAX_DELAY) == ESP_OK) {
ESP_LOGW("I2C_TEST", "%02X", i);
}
i2c_cmd_link_delete(cmd);
}
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
ESP_LOGI(TAG,"esp_lcd_new_panel_io_i2c");
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)EXAMPLE_I2C_NUM, &tp_io_config, &tp_io_handle));
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
}
ESP_LOGI(TAG,"esp_lcd_touch_new_i2c_cst816s");
esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp);
//END OF CST816 TOUCH TESTING FUNCTION
lv_init();
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
lv_color_t *buf1 = heap_caps_malloc(LVGL_LCD_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1);
lv_disp_draw_buf_init(&disp_buf, buf1, NULL, LVGL_LCD_BUF_SIZE);
ESP_LOGI(TAG, "Register display driver to LVGL");
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = EXAMPLE_LCD_H_RES;
disp_drv.ver_res = EXAMPLE_LCD_V_RES;
disp_drv.flush_cb = example_lvgl_flush_cb;
disp_drv.draw_buf = &disp_buf;
disp_drv.user_data = panel_handle;
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
ESP_LOGI(TAG, "Install LVGL tick timer");
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
const esp_timer_create_args_t lvgl_tick_timer_args = {
.callback = &example_increase_lvgl_tick,
.name = "lvgl_tick"};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
xTaskCreatePinnedToCore(lvgl_timer_task, "lvgl Timer", 10000, NULL, 4, NULL, 1);
}
Unfortunately same results:
[1B][0;32mI (401) LVGL_SETUP: Initialize Intel 8080 bus[1B][0m
[1B][0;32mI (411) LVGL_SETUP: Install LCD driver of st7789[1B][0m
[1B][0;32mI (411) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (541) LVGL_SETUP: Initializing I2C for display touch[1B][0m
[1B][0;32mI (551) LVGL_SETUP: esp_lcd_new_panel_io_i2c[1B][0m
[1B][0;32mI (551) LVGL_SETUP: esp_lcd_touch_new_i2c_cst816s[1B][0m
CUSTON COMPONENT CST816S config
[1B][0;32mI (551) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2 [1B][0m
[1B][0;32mI (561) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;31mE (591) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (591) CST816S: read_id(177): I2C read failed[1B][0m
[1B][0;31mE (591) CST816S: esp_lcd_touch_new_i2c_cst816s(87): Read version failed[1B][0m
[1B][0;32mI (591) gpio: GPIO[16]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (601) gpio: GPIO[21]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;31mE (611) CST816S: Initialization failed![1B][0m
[1B][0;32mI (621) LVGL_SETUP: Register display driver to LVGL[1B][0m
[1B][0;32mI (631) LVGL_SETUP: Install LVGL tick timer[1B][0m
I dont think the esp_lcd_touch_new_i2c_cst816s pulls the RES pin high hence it does not work. I can try put a scope on that pin if I can
@Lzw655 Il do a scope measurement tommorow. In the meantine, can you try with your custom CST816 device to see if yours is working?
@Lzw655 Il do a scope measurement tommorow. In the meantine, can you try with your custom CST816 device to see if yours is working?
Yeah, of course!
I managed to make it work. The issue is related to reset / init timing of the CST816 component. I saw that in arduino touchlib the reset setup hold and release timing setting was 200 ms. Maybe 200ms is quite and can be set down, but one has to experiment this since there is not reset timing info in the CST816 datasheet (https://www.buydisplay.com/download/ic/DS-CST816S_DS_V1.3.pdf) Here is the trick:
static esp_err_t reset(esp_lcd_touch_handle_t tp)
{
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed");
vTaskDelay(pdMS_TO_TICKS(200));
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed");
vTaskDelay(pdMS_TO_TICKS(200));
}
return ESP_OK;
}
Do not forget to configure an interrupt callback in the esp_lcd_touch_config_t structure and it should work. Let me know, if it is working on your side too.
Nice work! I'll fix it according to your code.
Nice work! I'll fix it according to your code.
I am glad you guys have managed to find a fix but I still cannot get the touch to work properly (perhaps this time it is no longer the driver issue but my code issue?)
After making a modification :
static esp_err_t reset(esp_lcd_touch_handle_t tp)
{
if (tp->config.rst_gpio_num != GPIO_NUM_NC) {
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed");
vTaskDelay(pdMS_TO_TICKS(200));
ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed");
vTaskDelay(pdMS_TO_TICKS(200));
}
return ESP_OK;
}
In my custom esl_lcd_touch_cst816s.c component (I cloned it from the managed component to make changes). I was able to build the code without any issues with the following code commented out:
gpio_config_t touch_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << PIN_TOUCH_RES};
ESP_ERROR_CHECK(gpio_config(&touch_gpio_config));
gpio_set_level(PIN_TOUCH_RES, 1);
and using the following esp_lcd_touch_config_t: (Not sure why it does not work if I set .reset = 1. I must use .reset = 0.)
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 0,
},
};
I have then added the following callback:
static void example_lvgl_touch_cb(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
uint16_t touchpad_x[1] = {0};
uint16_t touchpad_y[1] = {0};
uint8_t touchpad_cnt = 0;
/* Read touch controller data */
esp_lcd_touch_read_data(drv->user_data);
/* Get coordinates */
bool touchpad_pressed = esp_lcd_touch_get_coordinates(drv->user_data, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1);
if (touchpad_pressed && touchpad_cnt > 0) {
data->point.x = touchpad_x[0];
data->point.y = touchpad_y[0];
data->state = LV_INDEV_STATE_PRESSED;
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
and the following functions at the bottom of my lvgl_setup:
static lv_indev_drv_t indev_drv; // Input device driver (Touch)
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.disp = disp;
indev_drv.read_cb = example_lvgl_touch_cb;
indev_drv.user_data = tp;
lv_indev_drv_register(&indev_drv);
The result:
[1B][0;32mI (122) esp_image: segment 3: paddr=00030020 vaddr=4200000m
[1B][0;32mI (235) cpu_start: Compile time: Jun 13 2023 12:16:03[1B][0m
[1B][0;32mI (241) cpu_start: ELF file SHA256: ed8ab6f2674b1c7a...[1B][0m
[1B][0;32mI (247) cpu_start: ESP-IDF: v5.0.1-dirty[1B][0m
[1B][0;32mI (252) cpu_start: Min chip rev: v0.0[1B][0m
[1B][0;32mI (257) cpu_start: Max chip rev: v0.99 [1B][0m
[1B][0;32mI (262) cpu_start: Chip rev: v0.1[1B][0m
[1B][0;32mI (266) heap_init: Initializing. RAM available for dynamic allocation:[1B][0m
[1B][0;32mI (274) heap_init: At 3FC967B8 len 00052F58 (331 KiB): D/IRAM[1B][0m
[1B][0;32mI (280) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM[1B][0m
[1B][0;32mI (287) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM[1B][0m
[1B][0;32mI (293) heap_init: At 600FE010 len 00001FF0 (7 KiB): RTCRAM[1B][0m
[1B][0;32mI (300) spi_flash: detected chip: winbond[1B][0m
[1B][0;32mI (304) spi_flash: flash io: dio[1B][0m
[1B][0;33mW (308) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.[1B][0m
[1B][0;32mI (322) cpu_start: Starting scheduler on PRO CPU.[1B][0m
[1B][0;32mI (0) cpu_start: Starting scheduler on APP CPU.[1B][0m
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.1, 2MB external flash
Minimum free heap size: 379292 bytes
[1B][0;32mI (383) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (393) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (393) gpio: GPIO[38]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (403) LVGL_SETUP: Initialize Intel 8080 bus[1B][0m
[1B][0;32mI (413) LVGL_SETUP: Install LCD driver of st7789[1B][0m
[1B][0;32mI (413) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (543) LVGL_SETUP: Initializing I2C for display touch[1B][0m
[1B][0;32mI (553) LVGL_SETUP: esp_lcd_new_panel_io_i2c[1B][0m
[1B][0;32mI (553) LVGL_SETUP: esp_lcd_touch_new_i2c_cst816s[1B][0m
[1B][0;32mI (553) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2 [1B][0m
[1B][0;32mI (563) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (973) CST816S: IC id: 181[1B][0m
[1B][0;32mI (973) LVGL_SETUP: Register display driver to LVGL[1B][0m
[1B][0;32mI (973) LVGL_SETUP: Install LVGL tick timer[1B][0m
[1B][0;31mE (1313) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1313) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1343) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1343) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1373) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1373) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1403) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1403) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1433) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1433) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1463) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1463) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1493) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1493) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1523) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1523) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1553) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1553) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1583) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1583) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1613) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1613) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1643) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1643) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1673) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1673) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1703) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1703) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1733) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1733) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1763) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1763) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1793) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1793) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1823) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
I have updated my repository if you would like to view the full source code as usual.
@C-basstien Mentioned that I may need to configure interrupt callback in esp_lcd_touch_config_t but in the i80_controller esp-idf example they do not do that. They just use:
static lv_indev_drv_t indev_drv; // Input device driver (Touch)
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.disp = disp;
indev_drv.read_cb = example_lvgl_touch_cb;
indev_drv.user_data = tp;
lv_indev_drv_register(&indev_drv);
Is configuring callback in esp_lcd_touch_config_t required for cst816?
UPDATE
So it turns out the touch funcionality actually works. I have added a debug printf statement inside touch callback:
if (touchpad_pressed && touchpad_cnt > 0) {
data->point.x = touchpad_x[0];
data->point.y = touchpad_y[0];
data->state = LV_INDEV_STATE_PRESSED;
printf("data->point.x = %u \n",data->point.x);
printf("data->point.y = %u \n",data->point.y);
}
and when I click on the display, the callback executes and prints the coordinates. However, I cant stop the
[1B][0;31mE (1700) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1700) CST816S: read_data(115): I2C read failed[1B][0m
logs from popping up.
[1B][0;32mI (105) esp_image: segment 1: paddr=000215a4 vaddr=3fc934[1B][0;32mI (183) esp_image: segment 4: paddr=0007f2bc vaddr=40380634 size=02d6ch ( 11628) load[1B][0m
[1B][0;32mI (192) boot: Loaded app from partition at offset 0x10000[1B][0m
[1B][0;32mI (192) boot: Disabling RNG early entropy source...[1B][0m
[1B][0;32mI (203) cpu_start: Pro cpu up.[1B][0m
[1B][0;32mI (203) cpu_start: Starting app cpu, entry point is 0x403753cc[1B][0m
[1B][0;32mI (0) cpu_start: App cpu up.[1B][0m
[1B][0;32mI (218) cpu_start: Pro cpu start user code[1B][0m
[1B][0;32mI (218) cpu_start: cpu freq: 160000000 Hz[1B][0m
[1B][0;32mI (218) cpu_start: Application information:[1B][0m
[1B][0;32mI (221) cpu_start: Project name: i80_controller[1B][0m
[1B][0;32mI (227) cpu_start: App version: 21d1c86-dirty[1B][0m
[1B][0;32mI (232) cpu_start: Compile time: Jun 14 2023 07:57:57[1B][0m
[1B][0;32mI (238) cpu_start: ELF file SHA256: 70ff9de2385d389f...[1B][0m
[1B][0;32mI (244) cpu_start: ESP-IDF: v5.0.1-dirty[1B][0m
[1B][0;32mI (249) cpu_start: Min chip rev: v0.0[1B][0m
[1B][0;32mI (254) cpu_start: Max chip rev: v0.99 [1B][0m
[1B][0;32mI (259) cpu_start: Chip rev: v0.1[1B][0m
[1B][0;32mI (264) heap_init: Initializing. RAM available for dynamic allocation:[1B][0m
[1B][0;32mI (271) heap_init: At 3FC967B8 len 00052F58 (331 KiB): D/IRAM[1B][0m
[1B][0;32mI (277) heap_init: At 3FCE9710 len 00005724 (21 KiB): STACK/DRAM[1B][0m
[1B][0;32mI (284) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM[1B][0m
[1B][0;32mI (290) heap_init: At 600FE010 len 00001FF0 (7 KiB): RTCRAM[1B][0m
[1B][0;32mI (297) spi_flash: detected chip: winbond[1B][0m
[1B][0;32mI (301) spi_flash: flash io: dio[1B][0m
[1B][0;33mW (305) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.[1B][0m
[1B][0;32mI (319) cpu_start: Starting scheduler on PRO CPU.[1B][0m
[1B][0;32mI (0) cpu_start: Starting scheduler on APP CPU.[1B][0m
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.1, 2MB external flash
Minimum free heap size: 379292 bytes
[1B][0;32mI (380) gpio: GPIO[15]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (390) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (390) gpio: GPIO[38]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (400) LVGL_SETUP: Initialize Intel 8080 bus[1B][0m
[1B][0;32mI (410) LVGL_SETUP: Install LCD driver of st7789[1B][0m
[1B][0;32mI (410) gpio: GPIO[5]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (540) LVGL_SETUP: Initializing I2C for display touch[1B][0m
[1B][0;32mI (550) LVGL_SETUP: esp_lcd_new_panel_io_i2c[1B][0m
[1B][0;32mI (550) LVGL_SETUP: esp_lcd_touch_new_i2c_cst816s[1B][0m
[1B][0;32mI (550) gpio: GPIO[16]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:2 [1B][0m
[1B][0;32mI (560) gpio: GPIO[21]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [1B][0m
[1B][0;32mI (970) CST816S: IC id: 181[1B][0m
[1B][0;32mI (970) LVGL_SETUP: Register display driver to LVGL[1B][0m
[1B][0;32mI (970) LVGL_SETUP: Install LVGL tick timer[1B][0m
[1B][0;31mE (1310) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1310) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1340) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1340) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1370) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1370) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1400) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1400) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1430) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1430) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1460) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1460) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1490) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1490) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1520) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1520) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1550) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1550) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1580) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1580) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1610) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1610) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1640) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1640) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1670) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1670) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1700) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1700) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1730) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1730) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1760) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1760) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1790) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1790) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1820) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1820) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1850) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1850) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1880) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1880) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1910) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1910) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1940) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1940) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (1970) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (1970) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (2000) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (2000) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (2030) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (2030) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (2060) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (2060) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (2090) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (2090) CST816S: read_data(115): I2C read failed[1B][0m
data->point.x = 67
data->point.y = 229
data->point.x = 67
data->point.y = 229
data->point.x = 67
data->point.y = 229
data->point.x = 67
data->point.y = 229
data->point.x = 56
data->point.y = 215
data->point.x = 56
data->point.y = 215
data->point.x = 56
data->point.y = 215
data->point.x = 56
data->point.y = 215
[1B][0;31mE (5270) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5270) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5300) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5300) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5330) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5330) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5360) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5360) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5390) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5390) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5420) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5420) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5450) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5450) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5480) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5480) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5510) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5510) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5540) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5540) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5570) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5570) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5600) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5600) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5630) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5630) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5660) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5660) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5690) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5690) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5720) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5720) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5750) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
[1B][0;31mE (5750) CST816S: read_data(115): I2C read failed[1B][0m
[1B][0;31mE (5780) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
@krupis Oh, I get the same error logs as below. But the touch function works well, I can control my screen correctly. Can't you?
[1B][0;31mE (1793) CST816S: read_data(112): I2C read failed[1B][0m
[1B][0;31mE (1823) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
I think the error reason maybe is caused by the work mode (datasheet Page Four) of CST816. And its I2C can't work when not in dynamic mode.
And I find a doc that also mentions that.
So we should call esp_lcd_touch_get_coordinates()
when get a signal through interrupt callback.
@krupis Oh, I get the same error logs as below. But the touch function works well, I can control my screen correctly. Can't you?
[1B][0;31mE (1793) CST816S: read_data(112): I2C read failed[1B][0m [1B][0;31mE (1823) lcd_panel.io.i2c: panel_io_i2c_rx_buffer(135): i2c transaction failed[1B][0m
I think the error reason maybe is caused by the work mode (datasheet Page Four) of CST816. And its I2C can't work when not in dynamic mode.
And I find a doc that also enhances that.
So we should call
esp_lcd_touch_get_coordinates()
when get a signal through interrupt callback.
Yeah I just figured out that the touch callback actually works but its constantly printing those i2c error messages. I have made an update at the same time you wrote your response :)
Would you be able to show how to properly handle it in this case (only calling the get_coordinates upon the interrupt)?
Yeah, let me try.
Good news, I finish it. You can refer to the following steps (code):
First, use a mutex for touch and create it before init touch:
static SemaphoreHandle_t touch_mux; // Touch mutex
touch_mux = xSemaphoreCreateBinary();
Then, create a callback which used to send mutex and install it:
static void touch_callback(esp_lcd_touch_handle_t tp)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(touch_mux, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR();
}
}
const esp_lcd_touch_config_t tp_cfg = {
...
.interrupt_callback = touch_callback,
};
Finally, take mutex before read_data:
static void bsp_touchpad_read(lv_indev_drv_t *indev_drv, lv_indev_data_t *data)
{
esp_lcd_touch_handle_t tp = (esp_lcd_touch_handle_t) indev_drv->user_data;
uint16_t touchpad_x[1] = {0};
uint16_t touchpad_y[1] = {0};
uint8_t touchpad_cnt = 0;
assert(tp);
/* Read data from touch controller into memory */
if (xSemaphoreTake(touch_mux, 0) == pdTRUE) {
esp_lcd_touch_read_data(tp);
}
/* Read data from touch controller */
bool touchpad_pressed = esp_lcd_touch_get_coordinates(tp, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1);
if (touchpad_pressed && touchpad_cnt > 0) {
data->point.x = touchpad_x[0];
data->point.y = touchpad_y[0];
data->state = LV_INDEV_STATE_PRESSED;
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
You can refer to this file or just simply replace them with ESP_ERROR_CHECK()
or assert()
.
Hi, the indev_drv->read_cb (here bsp_touchpad_read) is never called on my side, how is it supposed to be triggered by an lvgl timer or manually with an example ? I am polling the indev_drv->read_cb upon a timer, but I am not sure it is the intended way to do it. Could you provide me an example ?
@Lzw655 Thank you very much, what a legend you are!
I have got it to work. The updated code for the Lilygo T-3 Display is on my repository.
Just one quick question:
Whenever I want to draw a widget, do I need to call bsp_display_lock(0);
and after I finished drawing bsp_display_unlock();
Is that how it supposed to be?
@C-basstien Try my example code, perhaps that will help. It seems to be working on my side. The lvgl meter widget is displayed and I can touch the screen and get the coordinates.
Whenever I want to draw a widget, do I need to call
bsp_display_lock(0);
and after I finished drawingbsp_display_unlock();
Is that how it supposed to be?
@krupis In any function that is not processed by the LVGL task (which runs lv_timer_handler()
). And you shouldn't call them in LVGL's event or timer callback.
Hi, the indev_drv->read_cb (here bsp_touchpad_read) is never called on my side, how is it supposed to be triggered by an lvgl timer or manually with an example ? I am polling the indev_drv->read_cb upon a timer, but I am not sure it is the intended way to do it. Could you provide me an example ?
Are you using esp_lvgl_port
component?
@Lzw655 Thanks, sounds good. Glad we got it working in the end. It was a tough one 👍 I am sure this will be very helpful for other people as well! I know at least a couple of people who struggled with Lilygo CST816 touch on the esp-idf
@Lzw655 Thanks, sounds good. Glad we got it working in the end. It was a tough one 👍 I am sure this will be very helpful for other people as well! I know at least a couple of people who struggled with Lilygo CST816 touch on the esp-idf
Yeah, thank you for helping us to test it!
Should I close this issue for the time being and reopen it if having any other issues with the CST816S touch?
Should I close this issue for the time being and reopen it if having any other issues with the CST816S touch?
Not necessary. It'll be closed when this PR is merged.
@Lzw655
Hello. I know this issue has been completed but I have been coming back to it and it haunts me. I hope you can clarify to me.
Its been a while but you have helped me solve the issue with the touch callback.
Current solution is as following: (pseudocode)
SemaphoreHandle_t touch_mux; // Touch mutex
esp_lcd_touch_config_t tp_cfg = {
.x_max = 320,
.y_max = 170,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 1,
.mirror_x = 0,
.mirror_y = 0,
},
.interrupt_callback = touch_callback,
};
static lv_indev_drv_t indev_drv; // Input device driver (Touch)
lv_indev_t *indev_touchpad;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.disp = disp;
indev_drv.read_cb = bsp_touchpad_read;
indev_drv.user_data = tp;
indev_touchpad = lv_indev_drv_register(&indev_drv);
BSP_NULL_CHECK(indev_touchpad, ESP_ERR_NO_MEM);
static void bsp_touchpad_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
uint16_t touchpad_x[1] = {0};
uint16_t touchpad_y[1] = {0};
uint8_t touchpad_cnt = 0;
/* Read data from touch controller into memory */
if (xSemaphoreTake(touch_mux, 0) == pdTRUE) {
esp_lcd_touch_read_data(drv->user_data);
}
/* Get coordinates */
bool touchpad_pressed = esp_lcd_touch_get_coordinates(drv->user_data, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1);
if (touchpad_pressed && touchpad_cnt > 0) {
data->point.x = touchpad_x[0];
data->point.y = touchpad_y[0];
data->state = LV_INDEV_STATE_PRESSED;
printf("data->point.x = %u \n",data->point.x);
printf("data->point.y = %u \n",data->point.y);
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
}
static void touch_callback(esp_lcd_touch_handle_t tp)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(touch_mux, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR();
}
}
As you can see from above, in lv_indev_drv_t
we create callback bsp_touchpad_read
.
I cannot wrap my head around what is the reason of using touch_callback
in esp_lcd_touch_config_t
. Why can't we not do anything in bsp_touchpad_read
?
Lets say I have connected an I2C sensor to the same I2C bus that I2C touch and its collecting data in a seperate FreeRTOS task.
How can I ensure that my sensor does not collect data at the same time the touch is triggered. Do I need to wrap touch_mux
in another semaphore called i2c_mux
?
Hi @krupis , hope the answers can be helpful.
LVGL will periodically call touch_callback
in esp_lcd_touch_config_t
to obtain the state and coordinates of a touch point. We need to update the lv_indev_data_t * data
in this function.
Yes, you need to perform synchronization, and using the same semaphore is the correct approach.
@Lzw655
Thanks for a quick response
Regarding Question1:
but indev_drv.read_cb = bsp_touchpad_read;
Ensures that bsp_touchpad_read
is called immediatelly when touch is detected. Why cannot update lv_indev_data_t * data
directly in bsp_touchpad_read
and why use touch_callback
at all?
Regarding Question2:
I dont really understand how would that be possible with the current logic. The semaphore is taken in bsp_touchpad_read
. and only released after touch event. That means that no one else can take this semaphore.
Could you provide some pseudo code how could I synchronize it using the same semaphore touch_mux
.
My I2C sensor function that I use:
float ADS7828_Read_Current(enum ADS7828_channel_e channel,uint8_t device_address,uint8_t coeff){
//need to implement semaphore here
uint16_t read_adc = I2C_read_ads7828(channel,device_address);
return read_adc ;
}
@krupis
As we talked before, the CST816S needs to wait for the interrupt signal to arrive before it can read the coordinates. This signal can be obtained through the touch_callback()
function.
I'm sorry, I misunderstood your intention. The touch_mux
can only be used to obtain the interrupt signal from the CST816S. You need to create another semaphore called i2c_mux
to synchronize the operations of devices on the same I2C bus. Like below:
SemaphoreHandle_t i2c_mux;
static void bsp_touchpad_read(lv_indev_drv_t * drv, lv_indev_data_t * data)
{
uint16_t touchpad_x[1] = {0};
uint16_t touchpad_y[1] = {0};
uint8_t touchpad_cnt = 0;
/* Read data from touch controller into memory */
if ((xSemaphoreTake(touch_mux, 0) == pdTRUE) && (xSemaphoreTake(i2c_mux, your_wait_time) == pdTRUE)) {
esp_lcd_touch_read_data(drv->user_data);
xSemaphoreGive(i2c_mux);
}
...
}
float ADS7828_Read_Current(enum ADS7828_channel_e channel,uint8_t device_address,uint8_t coeff){
//need to implement semaphore here
uint16_t read_adc = 0;
if (xSemaphoreTake(i2c_mux, your_wait_time) == pdTRUE ) {
I2C_read_ads7828(channel,device_address);
xSemaphoreGive(i2c_mux);
}
return read_adc ;
}
@Lzw655 I understood. Thank you very much !
@Lzw655 Sorry to bring this back again after such a long time. My project was on hold for a while since I had some other urgent projects to develop.
I have tried your suggestion regarding synchronizing multiple I2C devices on the same I2C bus and it does not seem to work as expected.
In my Display component I have the following:
SemaphoreHandle_t i2c_mux;
SemaphoreHandle_t lvgl_mux; // LVGL mutex
SemaphoreHandle_t touch_mux; // Touch mutex
static void bsp_touchpad_read(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
uint16_t touchpad_x[1] = {0};
uint16_t touchpad_y[1] = {0};
uint8_t touchpad_cnt = 0;
if ((xSemaphoreTake(touch_mux, 0) == pdTRUE) && (xSemaphoreTake(i2c_mux, 100) == pdTRUE)) {
esp_lcd_touch_read_data(drv->user_data);
xSemaphoreGive(i2c_mux);
}
/* Get coordinates */
bool touchpad_pressed = esp_lcd_touch_get_coordinates(drv->user_data, touchpad_x, touchpad_y, NULL, &touchpad_cnt, 1);
if (touchpad_pressed && touchpad_cnt > 0)
{
data->point.x = touchpad_x[0];
data->point.y = touchpad_y[0];
data->state = LV_INDEV_STATE_PRESSED;
printf("data->point.x = %u \n", data->point.x);
printf("data->point.y = %u \n", data->point.y);
}
else
{
data->state = LV_INDEV_STATE_RELEASED;
}
}
static void touch_callback(esp_lcd_touch_handle_t tp)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(touch_mux, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken)
{
portYIELD_FROM_ISR();
}
}
void lvgl_setup()
{
static lv_disp_draw_buf_t disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
static lv_disp_drv_t disp_drv; // contains callback functions
gpio_config_t pwr_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_POWER};
ESP_ERROR_CHECK(gpio_config(&pwr_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_POWER, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
gpio_config_t input_conf =
{
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pin_bit_mask = 1ULL << PIN_LCD_RD};
ESP_ERROR_CHECK(gpio_config(&input_conf));
gpio_config_t bk_gpio_config =
{
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = 1ULL << EXAMPLE_PIN_NUM_BK_LIGHT};
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
ESP_LOGI(TAG, "Initialize Intel 8080 bus");
esp_lcd_i80_bus_handle_t i80_bus = NULL;
esp_lcd_i80_bus_config_t bus_config = {
.clk_src = LCD_CLK_SRC_DEFAULT,
.dc_gpio_num = EXAMPLE_PIN_NUM_DC,
.wr_gpio_num = EXAMPLE_PIN_NUM_PCLK,
.data_gpio_nums = {
EXAMPLE_PIN_NUM_DATA0,
EXAMPLE_PIN_NUM_DATA1,
EXAMPLE_PIN_NUM_DATA2,
EXAMPLE_PIN_NUM_DATA3,
EXAMPLE_PIN_NUM_DATA4,
EXAMPLE_PIN_NUM_DATA5,
EXAMPLE_PIN_NUM_DATA6,
EXAMPLE_PIN_NUM_DATA7,
},
.bus_width = 8,
.max_transfer_bytes = LVGL_LCD_BUF_SIZE * sizeof(uint16_t)
//.psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
//.sram_trans_align = 4,
};
ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
.trans_queue_depth = 20,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,
},
.on_color_trans_done = example_notify_lvgl_flush_ready,
.user_ctx = &disp_drv,
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
esp_lcd_panel_handle_t panel_handle = NULL;
ESP_LOGI(TAG, "Install LCD driver of st7789");
esp_lcd_panel_dev_config_t panel_config = {
.reset_gpio_num = EXAMPLE_PIN_NUM_RST,
.rgb_endian = ESP_LCD_COLOR_SPACE_RGB,
.bits_per_pixel = 16,
};
ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
esp_lcd_panel_reset(panel_handle);
esp_lcd_panel_init(panel_handle);
esp_lcd_panel_invert_color(panel_handle, true);
esp_lcd_panel_swap_xy(panel_handle, true);
esp_lcd_panel_mirror(panel_handle, false, true);
// the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
esp_lcd_panel_set_gap(panel_handle, 0, 35);
esp_lcd_panel_io_tx_param(io_handle, 0xF2, (uint8_t[]){0}, 1); // 3Gamma function disable
esp_lcd_panel_io_tx_param(io_handle, 0x26, (uint8_t[]){1}, 1); // Gamma curve 1 selected
esp_lcd_panel_io_tx_param(io_handle, 0xE0, (uint8_t[]){ // Set positive gamma
0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00},
15);
esp_lcd_panel_io_tx_param(io_handle, 0xE1, (uint8_t[]){// Set negative gamma
0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F},
15);
ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
// CST816 TOUCH TESTING FUNCTION
#if USE_TOUCH_DISPLAY
esp_lcd_touch_handle_t tp = NULL;
esp_lcd_panel_io_handle_t tp_io_handle = NULL;
i2c_config_t i2c_conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = EXAMPLE_I2C_SDA,
.scl_io_num = EXAMPLE_I2C_SCL,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 400000,
};
ESP_LOGI(TAG, "Initializing I2C for display touch");
/* Initialize I2C */
ESP_ERROR_CHECK(i2c_param_config(EXAMPLE_I2C_NUM, &i2c_conf));
ESP_ERROR_CHECK(i2c_driver_install(EXAMPLE_I2C_NUM, i2c_conf.mode, 0, 0, 0));
i2c_cmd_handle_t cmd;
for (int i = 0; i < 0x7f; i++)
{
cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (i << 1) | I2C_MASTER_WRITE, true);
i2c_master_stop(cmd);
if (i2c_master_cmd_begin(EXAMPLE_I2C_NUM, cmd, portMAX_DELAY) == ESP_OK)
{
ESP_LOGW("I2C_TEST", "%02X", i);
}
i2c_cmd_link_delete(cmd);
}
esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
ESP_LOGI(TAG, "esp_lcd_new_panel_io_i2c");
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)EXAMPLE_I2C_NUM, &tp_io_config, &tp_io_handle));
// if display is rotated 270 degrees
esp_lcd_touch_config_t tp_cfg = {
.x_max = 170,
.y_max = 320,
.rst_gpio_num = 21,
.int_gpio_num = 16,
.levels = {
.reset = 0,
.interrupt = 0,
},
.flags = {
.swap_xy = 1,
.mirror_x = 0,
.mirror_y = 1,
},
.interrupt_callback = touch_callback,
};
// esp_lcd_touch_config_t tp_cfg = {
// .x_max = 170,
// .y_max = 320,
// .rst_gpio_num = 21,
// .int_gpio_num = 16,
// .levels = {
// .reset = 0,
// .interrupt = 0,
// },
// .flags = {
// .swap_xy = 1,
// .mirror_x = 0,
// .mirror_y = 1,
// },
// .interrupt_callback = touch_callback,
// };
ESP_LOGI(TAG, "esp_lcd_touch_new_i2c_cst816s");
esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp);
#endif
// END OF CST816 TOUCH TESTING FUNCTION
lv_init();
lvgl_mux = xSemaphoreCreateMutex();
BSP_NULL_CHECK(lvgl_mux, NULL);
touch_mux = xSemaphoreCreateBinary();
BSP_NULL_CHECK(touch_mux, NULL);
i2c_mux = xSemaphoreCreateMutex();
BSP_NULL_CHECK(i2c_mux, NULL);
// it's recommended to choose the size of the draw buffer(s) to be at least 1/10 screen sized
lv_color_t *buf1 = heap_caps_malloc(LVGL_LCD_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
assert(buf1);
lv_disp_draw_buf_init(&disp_buf, buf1, NULL, LVGL_LCD_BUF_SIZE);
ESP_LOGI(TAG, "Register display driver to LVGL");
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = EXAMPLE_LCD_H_RES;
disp_drv.ver_res = EXAMPLE_LCD_V_RES;
disp_drv.flush_cb = example_lvgl_flush_cb;
disp_drv.draw_buf = &disp_buf;
disp_drv.user_data = panel_handle;
disp_drv.sw_rotate = 1;
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
ESP_LOGI(TAG, "Install LVGL tick timer");
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
const esp_timer_create_args_t lvgl_tick_timer_args = {
.callback = &example_increase_lvgl_tick,
.name = "lvgl_tick"};
esp_timer_handle_t lvgl_tick_timer = NULL;
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer, EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
#if USE_TOUCH_DISPLAY
static lv_indev_drv_t indev_drv; // Input device driver (Touch)
lv_indev_t *indev_touchpad;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.disp = disp;
indev_drv.read_cb = bsp_touchpad_read;
indev_drv.user_data = tp;
indev_touchpad = lv_indev_drv_register(&indev_drv);
BSP_NULL_CHECK(indev_touchpad, ESP_ERR_NO_MEM);
#endif
xTaskCreatePinnedToCore(lvgl_timer_task, "lvgl Timer", 10000, NULL, 4, NULL, 1);
}
and in my other I2C temperature/humidity sensor I do the following:
extern SemaphoreHandle_t touch_mux;
extern SemaphoreHandle_t i2c_mux;
esp_err_t Measure_temp_humidity(uint8_t precision)
{
uint8_t read_buffer[6];
uint8_t write_command[1] = {precision};
esp_err_t err;
err = i2c_master_write_to_device(I2C_MASTER_NUM, SHT40_SENSOR_ADDR, &write_command, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
if (err != ESP_OK)
{
printf("Error in writing to SHT40 device \n");
return err;
}
vTaskDelay(20 / portTICK_PERIOD_MS);
err = i2c_master_read_from_device(I2C_MASTER_NUM, SHT40_SENSOR_ADDR, &read_buffer, 6, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
if (err != ESP_OK)
{
printf("Error in reading from SHT40 device \n");
return err;
}
float t_ticks = read_buffer[0] * 256 + read_buffer[1];
float rh_ticks = read_buffer[3] * 256 + read_buffer[4];
float t_degC = -45 + 175 * t_ticks / 65535;
float rh_pRH = -6 + 125 * rh_ticks / 65535;
printf("temperature = %.2f \n", t_degC);
printf("humidity = %.2f \n", rh_pRH);
return ESP_OK;
}
//SHT40_task is a free rtos task that is being created in my main.c.
void SHT40_task(void *argument)
{
for (;;)
{
if ((xSemaphoreTake(touch_mux, 0) == pdTRUE) && (xSemaphoreTake(i2c_mux, 100) == pdTRUE))
{
Measure_temp_humidity(SHT40_TEMP_HUMID_REG_HIGH_PREC);
xSemaphoreGive(i2c_mux);
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
As you can see from the SHT40_task, it should capture temperature and humidity readings every 100ms.
I think the issue lies somewhere within touch_mux. Instead of taking a temperature reading every 100ms, it only captures a temperature/humidity reading every time I touch on the display. See the logs below:
2023/09/15 08:27:21: data->point.x = 217
data->point.y = 35
data->point.x = 217
data->point.y = 35
temperature = 26.43
humidity = 45.33
2023/09/15 08:27:23: data->point.x = 155
data->point.y = 114
data->point.x = 155
data->point.y = 114
temperature = 26.42
humidity = 44.88
2023/09/15 08:27:27: data->point.x = 166
data->point.y = 97
data->point.x = 166
data->point.y = 97
temperature = 26.40
humidity = 43.70
Perhaps you have any ideas why that might happen and how to overcome this to ensure proper synchronization between multiple I2C devices? I really appreciate your help!
My guess is that touch_mux is only given in touch_callback (whenever the touch is detected)
static void touch_callback(esp_lcd_touch_handle_t tp)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(touch_mux, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken)
{
portYIELD_FROM_ISR();
}
}
Since it is only given when touch is detected, in SHT40_task the condition:
if ((xSemaphoreTake(touch_mux, 0) == pdTRUE) && (xSemaphoreTake(i2c_mux, 100) == pdTRUE))
is never going to be true because we cannot take the touch_mux semaphore unless it is given
@krupis Yeah, your guess is right. The touch_mux
shouldn't be taken in SHT40_task()
. And your SHT40_task()
should like below:
//SHT40_task is a free rtos task that is being created in my main.c.
void SHT40_task(void *argument)
{
for (;;)
{
if (xSemaphoreTake(i2c_mux, 100) == pdTRUE)
{
Measure_temp_humidity(SHT40_TEMP_HUMID_REG_HIGH_PREC);
xSemaphoreGive(i2c_mux);
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
hii @Lzw655 I have same issue like picture bellow, Help me plss , I config like `#define LCD_TOUCH_SDA 18
`ESP_ERROR_CHECK(i2c_param_config(LCD_TOUCH_I2C_NUM, &i2c_conf)); ESP_ERROR_CHECK(i2c_driver_install(LCD_TOUCH_I2C_NUM, i2c_conf.mode, 0, 0, 0));
esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG();
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c((esp_lcd_i2c_bus_handle_t)LCD_TOUCH_I2C_NUM, &io_config, &io_handle));`
I think this is because the CST816 goes to sleep after a while, after which it no longer responds to I2C transactions.
Modifying read_data( )
as follows fixes this problem by declining to read from the sensor unless IRQ is low.
static esp_err_t read_data(esp_lcd_touch_handle_t tp)
{
typedef struct {
uint8_t num;
uint8_t x_h : 4;
uint8_t : 4;
uint8_t x_l;
uint8_t y_h : 4;
uint8_t : 4;
uint8_t y_l;
} data_t;
data_t point;
// Only do this read if the interrupt line is low
if ( ( tp->config.int_gpio_num != GPIO_NUM_NC ) && gpio_get_level( tp->config.int_gpio_num ) ) {
portENTER_CRITICAL(&tp->data.lock);
tp->data.points = 0;
portEXIT_CRITICAL(&tp->data.lock);
return ESP_OK;
}
ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, DATA_START_REG, (uint8_t *)&point, sizeof(data_t)), TAG, "I2C read failed");
portENTER_CRITICAL(&tp->data.lock);
point.num = (point.num > POINT_NUM_MAX ? POINT_NUM_MAX : point.num);
tp->data.points = point.num;
/* Fill all coordinates */
for (int i = 0; i < point.num; i++) {
tp->data.coords[i].x = point.x_h << 8 | point.x_l;
tp->data.coords[i].y = point.y_h << 8 | point.y_l;
}
portEXIT_CRITICAL(&tp->data.lock);
return ESP_OK;
}
Hi there.
I have a problem, that seems somewhat similar to this. I am using esp_lvgl_port and the esp_led_touch_cs816s driver for that. I have installed both as components, and it kind of work.
Problem is the wakeup and sleep of the CST816.
This function fails esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &touch_handle);
due to no communication from adr. 0x15, due to the CST816 sleeping.
So I need to wake up the CST816 in order to be able to register the interupt callback. But I can only communicate with the CST816 in a timewindow following the interupt. Its like the hen and the egg.......
I can not wakeup the CST816 by toggling the reset.
Right now my only workaround is to continously tap the display during boot, to keep it alive, until I get a CST816 init OK. Then all works. This way the esp_lcd_touch_new_i2c_cst816s do not fail, and callback is registred correctly. But that is not a usable solution.
A note to David. It is true, that CST going to sleep causes this - and I will probably implement your workaround. There is also another solution. You can disable autosleep writing value 0xFF into register 0xFE. I tested this, but again you need to wake up CST816 in the first place, in order to be able to write to it. And it do not solve my problem, getting the callback registred to the lvgl before the first interupt......
Any suggestions?
Is your feature request related to a problem?
I have been using ST7789 display from the lilygo and it works flawlesly.
The only issue is that I believe the esp-idf does not currently support the touch driver (CST816) for this display.
https://www.lilygo.cc/products/t-display-s3
I think adding support for this touch driver would be very useful for developers such as myself.
Describe the solution you'd like.
Working touch display driver for CST816 and example project on how to get it going.
Describe alternatives you've considered.
Using different displays.
Additional context.
No response