From fa7d73f94cdd506c36413ba205e659735a68f059 Mon Sep 17 00:00:00 2001 From: Nurdism Date: Wed, 6 Aug 2025 22:26:43 -0400 Subject: [PATCH] refactor(esp_lcd_touch_spd2010): Refactor the spd2010 touch driver --- .../esp_lcd_touch_spd2010/CHANGELOG.md | 6 + .../esp_lcd_touch_spd2010.c | 397 +++++++++++------- .../esp_lcd_touch_spd2010/idf_component.yml | 2 +- .../include/esp_lcd_touch_spd2010.h | 50 +-- 4 files changed, 280 insertions(+), 175 deletions(-) diff --git a/components/display/lcd_touch/esp_lcd_touch_spd2010/CHANGELOG.md b/components/display/lcd_touch/esp_lcd_touch_spd2010/CHANGELOG.md index a5b34e5f42..a85dc779ce 100644 --- a/components/display/lcd_touch/esp_lcd_touch_spd2010/CHANGELOG.md +++ b/components/display/lcd_touch/esp_lcd_touch_spd2010/CHANGELOG.md @@ -1,5 +1,11 @@ # ChangeLog +## v1.1.0 - 2024-08-12 + +### Enhancements: + +* Refacotr the spd2010 touch driver, code improvement + ## v1.0.0 - 2024-08-12 ### Enhancements: diff --git a/components/display/lcd_touch/esp_lcd_touch_spd2010/esp_lcd_touch_spd2010.c b/components/display/lcd_touch/esp_lcd_touch_spd2010/esp_lcd_touch_spd2010.c index 0862d504e3..8924e0a369 100644 --- a/components/display/lcd_touch/esp_lcd_touch_spd2010/esp_lcd_touch_spd2010.c +++ b/components/display/lcd_touch/esp_lcd_touch_spd2010/esp_lcd_touch_spd2010.c @@ -22,7 +22,10 @@ static const char *TAG = "SPD2010"; -typedef struct { +#define SPD2010_MAX_TOUCH_POINTS 5 + +typedef struct +{ uint8_t none0; uint8_t none1; uint8_t none2; @@ -33,7 +36,8 @@ typedef struct { uint8_t tic_busy; } tp_status_high_t; -typedef struct { +typedef struct +{ uint8_t pt_exist; uint8_t gesture; uint8_t key; @@ -44,20 +48,23 @@ typedef struct { uint8_t none7; } tp_status_low_t; -typedef struct { +typedef struct +{ tp_status_low_t status_low; tp_status_high_t status_high; uint16_t read_len; } tp_status_t; -typedef struct { +typedef struct +{ uint8_t id; uint16_t x; uint16_t y; uint8_t weight; } tp_report_t; -typedef struct { +typedef struct +{ tp_report_t rpt[10]; uint8_t touch_num; uint8_t pack_code; @@ -70,154 +77,180 @@ typedef struct { uint16_t up_y; } tp_touch_t; -typedef struct { +typedef struct +{ uint8_t status; uint16_t next_packet_len; } tp_hdp_status_t; -static esp_err_t read_data(esp_lcd_touch_handle_t tp); -static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num); -static esp_err_t del(esp_lcd_touch_handle_t tp); -static esp_err_t reset(esp_lcd_touch_handle_t tp); - -static esp_err_t write_tp_point_mode_cmd(esp_lcd_touch_handle_t tp); -static esp_err_t write_tp_start_cmd(esp_lcd_touch_handle_t tp); -static esp_err_t write_tp_cpu_start_cmd(esp_lcd_touch_handle_t tp); -static esp_err_t write_tp_clear_int_cmd(esp_lcd_touch_handle_t tp); -static esp_err_t read_tp_status_length(esp_lcd_touch_handle_t tp, tp_status_t *tp_status); -static esp_err_t read_tp_hdp(esp_lcd_touch_handle_t tp, tp_status_t *tp_status, tp_touch_t *touch); -static esp_err_t read_tp_hdp_status(esp_lcd_touch_handle_t tp, tp_hdp_status_t *tp_hdp_status); -static esp_err_t read_fw_version(esp_lcd_touch_handle_t tp); -static esp_err_t tp_read_data(esp_lcd_touch_handle_t tp, tp_touch_t *touch); +static esp_err_t spd2010_read_data(esp_lcd_touch_handle_t tp); +static bool spd2010_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num); +static esp_err_t spd2010_del(esp_lcd_touch_handle_t tp); +static esp_err_t spd2010_reset(esp_lcd_touch_handle_t tp); + +static esp_err_t spd2010_write_tp_point_mode_cmd(esp_lcd_touch_handle_t tp); +static esp_err_t spd2010_write_tp_start_cmd(esp_lcd_touch_handle_t tp); +static esp_err_t spd2010_write_tp_cpu_start_cmd(esp_lcd_touch_handle_t tp); +static esp_err_t spd2010_write_tp_clear_int_cmd(esp_lcd_touch_handle_t tp); +static esp_err_t spd2010_read_tp_status_length(esp_lcd_touch_handle_t tp, tp_status_t *tp_status); +static esp_err_t spd2010_read_tp_hdp(esp_lcd_touch_handle_t tp, tp_status_t *tp_status, tp_touch_t *touch); +static esp_err_t spd2010_read_tp_hdp_status(esp_lcd_touch_handle_t tp, tp_hdp_status_t *tp_hdp_status); +static esp_err_t spd2010_read_fw_version(esp_lcd_touch_handle_t tp); +static esp_err_t spd2010_tp_read_data(esp_lcd_touch_handle_t tp, tp_touch_t *touch); +static esp_err_t spd2010_read_reg(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, size_t len); +static esp_err_t spd2010_write_reg(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, size_t len); esp_err_t esp_lcd_touch_new_i2c_spd2010(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp) { - ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_ARG, TAG, "Invalid io"); - ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Invalid config"); - ESP_RETURN_ON_FALSE(tp, ESP_ERR_INVALID_ARG, TAG, "Invalid touch handle"); - - /* Prepare main structure */ esp_err_t ret = ESP_OK; + + ESP_RETURN_ON_FALSE(io && config && tp, ESP_ERR_INVALID_ARG, TAG, "Invalid arguments"); + esp_lcd_touch_handle_t spd2010 = calloc(1, sizeof(esp_lcd_touch_t)); ESP_GOTO_ON_FALSE(spd2010, ESP_ERR_NO_MEM, err, TAG, "Touch handle malloc failed"); /* Communication interface */ spd2010->io = io; + /* Only supported callbacks are set */ - spd2010->read_data = read_data; - spd2010->get_xy = get_xy; - spd2010->del = del; + spd2010->read_data = spd2010_read_data; + spd2010->get_xy = spd2010_get_xy; + spd2010->del = spd2010_del; + /* Mutex */ spd2010->data.lock.owner = portMUX_FREE_VAL; + /* Save config */ memcpy(&spd2010->config, config, sizeof(esp_lcd_touch_config_t)); /* Prepare pin for touch interrupt */ - if (config->int_gpio_num != GPIO_NUM_NC) { + if (config->int_gpio_num != GPIO_NUM_NC) + { const gpio_config_t int_gpio_config = { .mode = GPIO_MODE_INPUT, + .pull_up_en = true, .intr_type = (config->levels.interrupt) ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE, - .pin_bit_mask = BIT64(config->int_gpio_num) - }; + .pin_bit_mask = BIT64(config->int_gpio_num)}; ESP_GOTO_ON_ERROR(gpio_config(&int_gpio_config), err, TAG, "GPIO intr config failed"); - /* Register interrupt callback */ - if (config->interrupt_callback) { + if (config->interrupt_callback) + { esp_lcd_touch_register_interrupt_callback(spd2010, config->interrupt_callback); } } + /* Prepare pin for touch controller reset */ - if (config->rst_gpio_num != GPIO_NUM_NC) { + if (config->rst_gpio_num != GPIO_NUM_NC) + { const gpio_config_t rst_gpio_config = { .mode = GPIO_MODE_OUTPUT, - .pin_bit_mask = BIT64(config->rst_gpio_num) - }; + .pin_bit_mask = BIT64(config->rst_gpio_num)}; ESP_GOTO_ON_ERROR(gpio_config(&rst_gpio_config), err, TAG, "GPIO reset config failed"); } + /* Reset controller */ - ESP_GOTO_ON_ERROR(reset(spd2010), err, TAG, "Reset failed"); - ESP_GOTO_ON_ERROR(read_fw_version(spd2010), err, TAG, "Read version failed"); + ESP_GOTO_ON_ERROR(spd2010_reset(spd2010), err, TAG, "Reset failed"); - ESP_LOGI(TAG, "Touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_SPD2010_VER_MAJOR, - ESP_LCD_TOUCH_SPD2010_VER_MINOR, ESP_LCD_TOUCH_SPD2010_VER_PATCH); + /* Read chip version */ + ESP_GOTO_ON_ERROR(spd2010_read_fw_version(spd2010), err, TAG, "Read version failed"); + + // ESP_LOGD(TAG, "Touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_SPD2010_VER_MAJOR, ESP_LCD_TOUCH_SPD2010_VER_MINOR, ESP_LCD_TOUCH_SPD2010_VER_PATCH); *tp = spd2010; return ESP_OK; + err: - if (spd2010) { - del(spd2010); + if (spd2010) + { + spd2010_del(spd2010); } - ESP_LOGE(TAG, "Initialization failed!"); + return ret; } -static esp_err_t read_data(esp_lcd_touch_handle_t tp) +static esp_err_t spd2010_read_data(esp_lcd_touch_handle_t tp) { uint8_t touch_cnt = 0; - tp_touch_t touch = {0}; - ESP_RETURN_ON_ERROR(tp_read_data(tp, &touch), TAG, "read data failed"); + + ESP_RETURN_ON_ERROR(spd2010_tp_read_data(tp, &touch), TAG, "read data failed"); portENTER_CRITICAL(&tp->data.lock); + /* Expect Number of touched points */ - touch_cnt = (touch.touch_num > CONFIG_ESP_LCD_TOUCH_MAX_POINTS ? CONFIG_ESP_LCD_TOUCH_MAX_POINTS : touch.touch_num); + touch_cnt = (touch.touch_num > SPD2010_MAX_TOUCH_POINTS ? SPD2010_MAX_TOUCH_POINTS : touch.touch_num); tp->data.points = touch_cnt; /* Fill all coordinates */ - for (int i = 0; i < touch_cnt; i++) { + for (int i = 0; i < touch_cnt; i++) + { tp->data.coords[i].x = touch.rpt[i].x; tp->data.coords[i].y = touch.rpt[i].y; tp->data.coords[i].strength = touch.rpt[i].weight; } + portEXIT_CRITICAL(&tp->data.lock); return ESP_OK; } -static bool get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num) +static bool spd2010_get_xy(esp_lcd_touch_handle_t tp, uint16_t *x, uint16_t *y, uint16_t *strength, uint8_t *point_num, uint8_t max_point_num) { + assert(tp && x && y && point_num); + portENTER_CRITICAL(&tp->data.lock); + /* Count of points */ *point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points); - for (size_t i = 0; i < *point_num; i++) { + + for (size_t i = 0; i < *point_num; i++) + { x[i] = tp->data.coords[i].x; y[i] = tp->data.coords[i].y; - - if (strength) { + if (strength) + { strength[i] = tp->data.coords[i].strength; } } + /* Clear available touch points count */ - tp->data.points = 0; + // tp->data.points = 0; + portEXIT_CRITICAL(&tp->data.lock); return (*point_num > 0); } -static esp_err_t del(esp_lcd_touch_handle_t tp) +static esp_err_t spd2010_del(esp_lcd_touch_handle_t tp) { /* Reset GPIO pin settings */ - if (tp->config.int_gpio_num != GPIO_NUM_NC) { + if (tp->config.int_gpio_num != GPIO_NUM_NC) + { gpio_reset_pin(tp->config.int_gpio_num); } - if (tp->config.rst_gpio_num != GPIO_NUM_NC) { + + if (tp->config.rst_gpio_num != GPIO_NUM_NC) + { gpio_reset_pin(tp->config.rst_gpio_num); - if (tp->config.interrupt_callback) { + if (tp->config.interrupt_callback) + { gpio_isr_handler_remove(tp->config.int_gpio_num); } } + /* Release memory */ free(tp); return ESP_OK; } -static esp_err_t reset(esp_lcd_touch_handle_t tp) +static esp_err_t spd2010_reset(esp_lcd_touch_handle_t tp) { TickType_t delay_tick = 0; - if (tp->config.rst_gpio_num != GPIO_NUM_NC) { + 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"); delay_tick = pdMS_TO_TICKS(2); vTaskDelay((delay_tick > 0) ? delay_tick : 1); @@ -229,10 +262,7 @@ static esp_err_t reset(esp_lcd_touch_handle_t tp) return ESP_OK; } -#define i2c_write(data_p, len) ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(tp->io, 0, data_p, len), TAG, "Tx failed"); -#define i2c_read(data_p, len) ESP_RETURN_ON_ERROR(esp_lcd_panel_io_rx_param(tp->io, 0, data_p, len), TAG, "Rx failed"); - -static esp_err_t write_tp_point_mode_cmd(esp_lcd_touch_handle_t tp) +static esp_err_t spd2010_write_tp_point_mode_cmd(esp_lcd_touch_handle_t tp) { uint8_t sample_data[4]; @@ -241,12 +271,13 @@ static esp_err_t write_tp_point_mode_cmd(esp_lcd_touch_handle_t tp) sample_data[2] = 0x00; sample_data[3] = 0x00; - i2c_write(&sample_data[0], sizeof(sample_data)); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_write_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), &sample_data[2], 2), TAG, "Write point mode command failed"); + // esp_rom_delay_us(200); + return ESP_OK; } -static esp_err_t write_tp_start_cmd(esp_lcd_touch_handle_t tp) +static esp_err_t spd2010_write_tp_start_cmd(esp_lcd_touch_handle_t tp) { uint8_t sample_data[4]; @@ -255,12 +286,13 @@ static esp_err_t write_tp_start_cmd(esp_lcd_touch_handle_t tp) sample_data[2] = 0x00; sample_data[3] = 0x00; - i2c_write(&sample_data[0], sizeof(sample_data)); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_write_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), &sample_data[2], 2), TAG, "Write start command failed"); + // esp_rom_delay_us(200); + return ESP_OK; } -static esp_err_t write_tp_cpu_start_cmd(esp_lcd_touch_handle_t tp) +static esp_err_t spd2010_write_tp_cpu_start_cmd(esp_lcd_touch_handle_t tp) { uint8_t sample_data[4]; @@ -269,12 +301,13 @@ static esp_err_t write_tp_cpu_start_cmd(esp_lcd_touch_handle_t tp) sample_data[2] = 0x01; sample_data[3] = 0x00; - i2c_write(&sample_data[0], sizeof(sample_data)); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_write_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), &sample_data[2], 2), TAG, "Write start command failed"); + // esp_rom_delay_us(200); + return ESP_OK; } -static esp_err_t write_tp_clear_int_cmd(esp_lcd_touch_handle_t tp) +static esp_err_t spd2010_write_tp_clear_int_cmd(esp_lcd_touch_handle_t tp) { uint8_t sample_data[4]; @@ -283,36 +316,35 @@ static esp_err_t write_tp_clear_int_cmd(esp_lcd_touch_handle_t tp) sample_data[2] = 0x01; sample_data[3] = 0x00; - i2c_write(&sample_data[0], sizeof(sample_data)); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_write_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), &sample_data[2], 2), TAG, "Write clear interrupt command failed"); + // esp_rom_delay_us(200); + return ESP_OK; } -static esp_err_t read_tp_status_length(esp_lcd_touch_handle_t tp, tp_status_t *tp_status) +static esp_err_t spd2010_read_tp_status_length(esp_lcd_touch_handle_t tp, tp_status_t *tp_status) { uint8_t sample_data[4]; - sample_data[0] = 0x20; sample_data[1] = 0x00; - i2c_write(&sample_data[0], 2); - esp_rom_delay_us(200); - i2c_read(&sample_data[0], sizeof(sample_data)); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_read_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), sample_data, 4), TAG, "Read status length failed"); + // esp_rom_delay_us(200); + tp_status->status_low.pt_exist = (sample_data[0] & 0x01); tp_status->status_low.gesture = (sample_data[0] & 0x02); + tp_status->status_low.aux = ((sample_data[0] & 0x08)); // aux, cytang tp_status->status_high.tic_busy = ((sample_data[1] & 0x80) >> 7); tp_status->status_high.tic_in_bios = ((sample_data[1] & 0x40) >> 6); tp_status->status_high.tic_in_cpu = ((sample_data[1] & 0x20) >> 5); tp_status->status_high.tint_low = ((sample_data[1] & 0x10) >> 4); tp_status->status_high.cpu_run = ((sample_data[1] & 0x08) >> 3); - tp_status->status_low.aux = ((sample_data[0] & 0x08)); //aux, cytang - tp_status->read_len = (sample_data[3] << 8 | sample_data[2]); + return ESP_OK; } -static esp_err_t read_tp_hdp(esp_lcd_touch_handle_t tp, tp_status_t *tp_status, tp_touch_t *touch) +static esp_err_t spd2010_read_tp_hdp(esp_lcd_touch_handle_t tp, tp_status_t *tp_status, tp_touch_t *touch) { uint8_t sample_data[4 + (10 * 6)]; // 4 Bytes Header + 10 Finger * 6 Bytes uint8_t i, offset; @@ -321,18 +353,16 @@ static esp_err_t read_tp_hdp(esp_lcd_touch_handle_t tp, tp_status_t *tp_status, sample_data[0] = 0x00; sample_data[1] = 0x03; - i2c_write(&sample_data[0], 2); - esp_rom_delay_us(200); - i2c_read(&sample_data[0], tp_status->read_len); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_read_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), sample_data, tp_status->read_len), TAG, "Read HDP data failed"); check_id = sample_data[4]; - - if ((check_id <= 0x0A) && tp_status->status_low.pt_exist) { + if ((check_id <= 0x0A) && tp_status->status_low.pt_exist) + { touch->touch_num = ((tp_status->read_len - 4) / 6); touch->gesture = 0x00; - for (i = 0; i < touch->touch_num; i++) { + for (i = 0; i < touch->touch_num; i++) + { offset = i * 6; touch->rpt[i].id = sample_data[4 + offset]; touch->rpt[i].x = (((sample_data[7 + offset] & 0xF0) << 4) | sample_data[5 + offset]); @@ -341,12 +371,15 @@ static esp_err_t read_tp_hdp(esp_lcd_touch_handle_t tp, tp_status_t *tp_status, } /* For slide gesture recognize */ - if ((touch->rpt[0].weight != 0) && (touch->down != 1)) { + if ((touch->rpt[0].weight != 0) && (touch->down != 1)) + { touch->down = 1; - touch->up = 0 ; + touch->up = 0; touch->down_x = touch->rpt[0].x; touch->down_y = touch->rpt[0].y; - } else if ((touch->rpt[0].weight == 0) && (touch->down == 1)) { + } + else if ((touch->rpt[0].weight == 0) && (touch->down == 1)) + { touch->up = 1; touch->down = 0; touch->up_x = touch->rpt[0].x; @@ -354,58 +387,57 @@ static esp_err_t read_tp_hdp(esp_lcd_touch_handle_t tp, tp_status_t *tp_status, } /* Dump Log */ - for (uint8_t finger_num = 0; finger_num < touch->touch_num; finger_num++) { - ESP_LOGD(TAG, "ID[%d], X[%d], Y[%d], Weight[%d]\n", - touch->rpt[finger_num].id, - touch->rpt[finger_num].x, - touch->rpt[finger_num].y, - touch->rpt[finger_num].weight); + for (uint8_t finger_num = 0; finger_num < touch->touch_num; finger_num++) + { + ESP_LOGD(TAG, "ID[%d], X[%d], Y[%d], Weight[%d]\n", touch->rpt[finger_num].id, touch->rpt[finger_num].x, touch->rpt[finger_num].y, touch->rpt[finger_num].weight); } - } else if ((check_id == 0xF6) && tp_status->status_low.gesture) { + } + else if ((check_id == 0xF6) && tp_status->status_low.gesture) + { touch->touch_num = 0x00; touch->up = 0; touch->down = 0; touch->gesture = sample_data[6] & 0x07; + ESP_LOGD(TAG, "gesture : 0x%02x\n", touch->gesture); - } else { + } + else + { touch->touch_num = 0x00; touch->gesture = 0x00; } + return ESP_OK; } -static esp_err_t read_tp_hdp_status(esp_lcd_touch_handle_t tp, tp_hdp_status_t *tp_hdp_status) +static esp_err_t spd2010_read_tp_hdp_status(esp_lcd_touch_handle_t tp, tp_hdp_status_t *tp_hdp_status) { uint8_t sample_data[8]; sample_data[0] = 0xFC; sample_data[1] = 0x02; - i2c_write(&sample_data[0], 2); - esp_rom_delay_us(200); - i2c_read(&sample_data[0], sizeof(sample_data)); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_read_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), sample_data, 8), TAG, "Read HDP status failed"); tp_hdp_status->status = sample_data[5]; tp_hdp_status->next_packet_len = (sample_data[2] | sample_data[3] << 8); + return ESP_OK; } -static esp_err_t Read_HDP_REMAIN_DATA(esp_lcd_touch_handle_t tp, tp_hdp_status_t *tp_hdp_status) +static esp_err_t spd2010_read_hdp_remain_data(esp_lcd_touch_handle_t tp, tp_hdp_status_t *tp_hdp_status) { uint8_t sample_data[32]; sample_data[0] = 0x00; sample_data[1] = 0x03; - i2c_write(&sample_data[0], 2); - esp_rom_delay_us(200); - i2c_read(&sample_data[0], tp_hdp_status->next_packet_len); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_read_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), sample_data, tp_hdp_status->next_packet_len), TAG, "Read HDP remain data failed"); + return ESP_OK; } -static esp_err_t read_fw_version(esp_lcd_touch_handle_t tp) +static esp_err_t spd2010_read_fw_version(esp_lcd_touch_handle_t tp) { uint8_t sample_data[18]; uint16_t DVer; @@ -414,67 +446,134 @@ static esp_err_t read_fw_version(esp_lcd_touch_handle_t tp) sample_data[0] = 0x26; sample_data[1] = 0x00; - i2c_write(&sample_data[0], 2); - esp_rom_delay_us(200); - i2c_read(&sample_data[0], 18); - esp_rom_delay_us(200); + ESP_RETURN_ON_ERROR(spd2010_read_reg(tp, (((uint16_t)sample_data[0] << 8) | (sample_data[1])), sample_data, 18), TAG, "Read firmware version failed"); - Dummy = ((sample_data[0] << 24) | (sample_data[1] << 16) | (sample_data[3] << 8) | (sample_data[0])); + Dummy = ((sample_data[0] << 24) | (sample_data[1] << 16) | (sample_data[3] << 8) | (sample_data[0])); // what is this? DVer = ((sample_data[5] << 8) | (sample_data[4])); PID = ((sample_data[9] << 24) | (sample_data[8] << 16) | (sample_data[7] << 8) | (sample_data[6])); - ICName_L = ((sample_data[13] << 24) | (sample_data[12] << 16) | (sample_data[11] << 8) | (sample_data[10])); // "2010" - ICName_H = ((sample_data[17] << 24) | (sample_data[16] << 16) | (sample_data[15] << 8) | (sample_data[14])); // "SPD" + ICName_L = ((sample_data[13] << 24) | (sample_data[12] << 16) | (sample_data[11] << 8) | (sample_data[10])); // "2010" + ICName_H = ((sample_data[17] << 24) | (sample_data[16] << 16) | (sample_data[15] << 8) | (sample_data[14])); // "SPD" - ESP_LOGD(TAG, "Dummy[%"PRIu32"], DVer[%"PRIu16"], PID[%"PRIu32"], Name[%"PRIu32"-%"PRIu32"]", Dummy, DVer, PID, ICName_H, ICName_L); + ESP_LOGD(TAG, "Dummy[%" PRIu32 "], DVer[%" PRIu16 "], PID[%" PRIu32 "], Name[%" PRIu32 "-%" PRIu32 "]", Dummy, DVer, PID, ICName_H, ICName_L); return ESP_OK; } -static esp_err_t tp_read_data(esp_lcd_touch_handle_t tp, tp_touch_t *touch) +static esp_err_t spd2010_tp_read_data(esp_lcd_touch_handle_t tp, tp_touch_t *touch) { tp_status_t tp_status = {0}; tp_hdp_status_t tp_hdp_status = {0}; - ESP_RETURN_ON_ERROR(read_tp_status_length(tp, &tp_status), TAG, "Read status length failed"); + ESP_RETURN_ON_ERROR(spd2010_read_tp_status_length(tp, &tp_status), TAG, "Read status length failed"); - if (tp_status.status_high.tic_in_bios) { + if (tp_status.status_high.tic_in_bios) + { /* Write Clear TINT Command */ - ESP_RETURN_ON_ERROR(write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); - + ESP_RETURN_ON_ERROR(spd2010_write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); /* Write CPU Start Command */ - ESP_RETURN_ON_ERROR(write_tp_cpu_start_cmd(tp), TAG, "Write cpu start cmd failed"); - - } else if (tp_status.status_high.tic_in_cpu) { + ESP_RETURN_ON_ERROR(spd2010_write_tp_cpu_start_cmd(tp), TAG, "Write cpu start cmd failed"); + } + else if (tp_status.status_high.tic_in_cpu) + { /* Write Touch Change Command */ - ESP_RETURN_ON_ERROR(write_tp_point_mode_cmd(tp), TAG, "Write point mode cmd failed"); - + ESP_RETURN_ON_ERROR(spd2010_write_tp_point_mode_cmd(tp), TAG, "Write point mode cmd failed"); /* Write Touch Start Command */ - ESP_RETURN_ON_ERROR(write_tp_start_cmd(tp), TAG, "Write start cmd failed"); - + ESP_RETURN_ON_ERROR(spd2010_write_tp_start_cmd(tp), TAG, "Write start cmd failed"); /* Write Clear TINT Command */ - ESP_RETURN_ON_ERROR(write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); - - } else if (tp_status.status_high.cpu_run && tp_status.read_len == 0) { - ESP_RETURN_ON_ERROR(write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); - } else if (tp_status.status_low.pt_exist || tp_status.status_low.gesture) { + ESP_RETURN_ON_ERROR(spd2010_write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); + } + else if (tp_status.status_high.cpu_run && tp_status.read_len == 0) + { + ESP_RETURN_ON_ERROR(spd2010_write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); + } + else if (tp_status.status_low.pt_exist || tp_status.status_low.gesture) + { /* Read HDP */ - ESP_RETURN_ON_ERROR(read_tp_hdp(tp, &tp_status, touch), TAG, "Read hdp failed"); - -hdp_done_check: + ESP_RETURN_ON_ERROR(spd2010_read_tp_hdp(tp, &tp_status, touch), TAG, "Read hdp failed"); + hdp_done_check: /* Read HDP Status */ - ESP_RETURN_ON_ERROR(read_tp_hdp_status(tp, &tp_hdp_status), TAG, "Read hdp status failed"); - - if (tp_hdp_status.status == 0x82) { + ESP_RETURN_ON_ERROR(spd2010_read_tp_hdp_status(tp, &tp_hdp_status), TAG, "Read hdp status failed"); + if (tp_hdp_status.status == 0x82) + { /* Clear INT */ - ESP_RETURN_ON_ERROR(write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); - } else if (tp_hdp_status.status == 0x00) { + ESP_RETURN_ON_ERROR(spd2010_write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); + } + else if (tp_hdp_status.status == 0x00) + { /* Read HDP Remain Data */ - ESP_RETURN_ON_ERROR(Read_HDP_REMAIN_DATA(tp, &tp_hdp_status), TAG, "Read hdp remain data failed"); + ESP_RETURN_ON_ERROR(spd2010_read_hdp_remain_data(tp, &tp_hdp_status), TAG, "Read hdp remain data failed"); goto hdp_done_check; } - } else if (tp_status.status_high.cpu_run && tp_status.status_low.aux) { - ESP_RETURN_ON_ERROR(write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); } - + else if (tp_status.status_high.cpu_run && tp_status.status_low.aux) + { + ESP_RETURN_ON_ERROR(spd2010_write_tp_clear_int_cmd(tp), TAG, "Write clear int cmd failed"); + } return ESP_OK; } + +static esp_err_t spd2010_read_reg(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, size_t len) +{ + uint8_t reg_buf[2] = {reg >> 8, reg}; + const int max_retries = 5; + esp_err_t ret; + + for (int retry = 0; retry < max_retries; retry++) + { + ret = esp_lcd_panel_io_tx_param(tp->io, reg_buf[0], ®_buf[1], 1); + if (ret != ESP_OK) + { + ESP_LOGD(TAG, "TX failed, retry %d", retry); + vTaskDelay(pdMS_TO_TICKS(3)); + continue; + } + + vTaskDelay(pdMS_TO_TICKS(2)); + + ret = esp_lcd_panel_io_rx_param(tp->io, -1, data, len); + if (ret == ESP_OK) + { + return ESP_OK; + } + + ESP_LOGD(TAG, "RX failed, retry %d", retry); + vTaskDelay(pdMS_TO_TICKS(3)); + } + + if (tp->config.rst_gpio_num != GPIO_NUM_NC) + { + ESP_LOGW(TAG, "Trigger hardware reset"); + gpio_set_level(tp->config.rst_gpio_num, 0); + vTaskDelay(pdMS_TO_TICKS(10)); + gpio_set_level(tp->config.rst_gpio_num, 1); + vTaskDelay(pdMS_TO_TICKS(100)); + } + + return ESP_FAIL; +} + +static esp_err_t spd2010_write_reg(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, size_t len) +{ + uint8_t reg_buf[len + 2]; + reg_buf[0] = reg >> 8; + reg_buf[1] = reg & 0xFF; + + memcpy(®_buf[2], data, len); + + const int max_retries = 5; + esp_err_t ret; + + for (int retry = 0; retry < max_retries; retry++) + { + ret = esp_lcd_panel_io_tx_param(tp->io, reg_buf[0], ®_buf[1], len + 1); + if (ret == ESP_OK) + { + return ESP_OK; + } + + ESP_LOGD(TAG, "Data TX failed, retry %d", retry); + vTaskDelay(pdMS_TO_TICKS(3)); + } + + return ESP_FAIL; +} diff --git a/components/display/lcd_touch/esp_lcd_touch_spd2010/idf_component.yml b/components/display/lcd_touch/esp_lcd_touch_spd2010/idf_component.yml index 9c50b0d725..8641a4b387 100644 --- a/components/display/lcd_touch/esp_lcd_touch_spd2010/idf_component.yml +++ b/components/display/lcd_touch/esp_lcd_touch_spd2010/idf_component.yml @@ -1,4 +1,4 @@ -version: "1.0.0" +version: "1.1.0" description: ESP LCD Touch SPD2010 - touch controller SPD2010 url: https://github.com/espressif/esp-iot-solution/tree/master/components/display/lcd_touch/esp_lcd_touch_spd2010 repository: https://github.com/espressif/esp-iot-solution.git diff --git a/components/display/lcd_touch/esp_lcd_touch_spd2010/include/esp_lcd_touch_spd2010.h b/components/display/lcd_touch/esp_lcd_touch_spd2010/include/esp_lcd_touch_spd2010.h index c9211d2c5b..3e003d64e3 100644 --- a/components/display/lcd_touch/esp_lcd_touch_spd2010/include/esp_lcd_touch_spd2010.h +++ b/components/display/lcd_touch/esp_lcd_touch_spd2010/include/esp_lcd_touch_spd2010.h @@ -8,43 +8,43 @@ #include "esp_lcd_touch.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/** - * @brief Create a new SPD2010 touch driver - * - * @note The I2C communication should be initialized before use this function. - * - * @param io LCD panel IO handle, it should be created by `esp_lcd_new_panel_io_i2c()` - * @param config Touch panel configuration - * @param tp Touch panel handle - * @return - * - ESP_OK: on success - */ -esp_err_t esp_lcd_touch_new_i2c_spd2010(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp); + /** + * @brief Create a new SPD2010 touch driver + * + * @note The I2C communication should be initialized before use this function. + * + * @param io LCD panel IO handle, it should be created by `esp_lcd_new_panel_io_i2c()` + * @param config Touch panel configuration + * @param tp Touch panel handle + * @return + * - ESP_OK: on success + */ + esp_err_t esp_lcd_touch_new_i2c_spd2010(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp); /** * @brief I2C address of the SPD2010 controller * */ -#define ESP_LCD_TOUCH_IO_I2C_SPD2010_ADDRESS (0x53) +#define ESP_LCD_TOUCH_IO_I2C_SPD2010_ADDRESS (0x53) /** * @brief Touch IO configuration structure * */ -#define ESP_LCD_TOUCH_IO_I2C_SPD2010_CONFIG() \ - { \ - .dev_addr = ESP_LCD_TOUCH_IO_I2C_SPD2010_ADDRESS, \ - .control_phase_bytes = 1, \ - .dc_bit_offset = 0, \ - .lcd_cmd_bits = 0, \ - .flags = \ - { \ - .disable_control_phase = 1, \ - } \ - } +#define ESP_LCD_TOUCH_IO_I2C_SPD2010_CONFIG() \ + { \ + .dev_addr = ESP_LCD_TOUCH_IO_I2C_SPD2010_ADDRESS, \ + .control_phase_bytes = 1, \ + .dc_bit_offset = 0, \ + .lcd_cmd_bits = 8, \ + .flags = { \ + .disable_control_phase = 1, \ + }, \ + .scl_speed_hz = 100000} #ifdef __cplusplus }