|
| 1 | +/* |
| 2 | + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD |
| 3 | + * |
| 4 | + * SPDX-License-Identifier: Apache-2.0 |
| 5 | + */ |
| 6 | + |
| 7 | +#include "ESP_PanelLog.h" |
| 8 | + |
| 9 | +#include <inttypes.h> |
| 10 | +#include <stdio.h> |
| 11 | +#include <string.h> |
| 12 | +#include "freertos/FreeRTOS.h" |
| 13 | +#include "freertos/task.h" |
| 14 | +#include "driver/gpio.h" |
| 15 | +#include "driver/i2c.h" |
| 16 | +#include "esp_system.h" |
| 17 | +#include "esp_err.h" |
| 18 | +#include "esp_log.h" |
| 19 | +#include "esp_check.h" |
| 20 | +#include "esp_lcd_panel_io.h" |
| 21 | +#include "esp_lcd_touch.h" |
| 22 | + |
| 23 | +#include "esp_lcd_touch_chsc6540.h" |
| 24 | + |
| 25 | +#define POINT_NUM_MAX (1) |
| 26 | + |
| 27 | +#define DATA_START_REG (0x00) |
| 28 | + |
| 29 | +#define CHIP_ID_REG (0xA7) |
| 30 | + |
| 31 | +static const char *TAG = "CHSC6540"; |
| 32 | + |
| 33 | +static esp_err_t read_data(esp_lcd_touch_handle_t tp); |
| 34 | +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); |
| 35 | +static esp_err_t del(esp_lcd_touch_handle_t tp); |
| 36 | + |
| 37 | +static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len); |
| 38 | + |
| 39 | +static esp_err_t reset(esp_lcd_touch_handle_t tp); |
| 40 | +static esp_err_t read_id(esp_lcd_touch_handle_t tp); |
| 41 | + |
| 42 | +esp_err_t esp_lcd_touch_new_i2c_chsc6540(const esp_lcd_panel_io_handle_t io, const esp_lcd_touch_config_t *config, esp_lcd_touch_handle_t *tp) |
| 43 | +{ |
| 44 | + ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_ARG, TAG, "Invalid io"); |
| 45 | + ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Invalid config"); |
| 46 | + ESP_RETURN_ON_FALSE(tp, ESP_ERR_INVALID_ARG, TAG, "Invalid touch handle"); |
| 47 | + |
| 48 | + ESP_PANEL_ENABLE_TAG_DEBUG_LOG(); |
| 49 | + |
| 50 | + /* Prepare main structure */ |
| 51 | + esp_err_t ret = ESP_OK; |
| 52 | + esp_lcd_touch_handle_t chsc6540 = calloc(1, sizeof(esp_lcd_touch_t)); |
| 53 | + ESP_GOTO_ON_FALSE(chsc6540, ESP_ERR_NO_MEM, err, TAG, "Touch handle malloc failed"); |
| 54 | + |
| 55 | + /* Communication interface */ |
| 56 | + chsc6540->io = io; |
| 57 | + /* Only supported callbacks are set */ |
| 58 | + chsc6540->read_data = read_data; |
| 59 | + chsc6540->get_xy = get_xy; |
| 60 | + chsc6540->del = del; |
| 61 | + /* Mutex */ |
| 62 | + chsc6540->data.lock.owner = portMUX_FREE_VAL; |
| 63 | + /* Save config */ |
| 64 | + memcpy(&chsc6540->config, config, sizeof(esp_lcd_touch_config_t)); |
| 65 | + |
| 66 | + /* Prepare pin for touch interrupt */ |
| 67 | + if (chsc6540->config.int_gpio_num != GPIO_NUM_NC) { |
| 68 | + const gpio_config_t int_gpio_config = { |
| 69 | + .mode = GPIO_MODE_INPUT, |
| 70 | + .intr_type = (chsc6540->config.levels.interrupt ? GPIO_INTR_POSEDGE : GPIO_INTR_NEGEDGE), |
| 71 | + .pin_bit_mask = BIT64(chsc6540->config.int_gpio_num) |
| 72 | + }; |
| 73 | + ESP_GOTO_ON_ERROR(gpio_config(&int_gpio_config), err, TAG, "GPIO intr config failed"); |
| 74 | + |
| 75 | + /* Register interrupt callback */ |
| 76 | + if (chsc6540->config.interrupt_callback) { |
| 77 | + esp_lcd_touch_register_interrupt_callback(chsc6540, chsc6540->config.interrupt_callback); |
| 78 | + } |
| 79 | + } |
| 80 | + /* Prepare pin for touch controller reset */ |
| 81 | + if (chsc6540->config.rst_gpio_num != GPIO_NUM_NC) { |
| 82 | + const gpio_config_t rst_gpio_config = { |
| 83 | + .mode = GPIO_MODE_OUTPUT, |
| 84 | + .pin_bit_mask = BIT64(chsc6540->config.rst_gpio_num) |
| 85 | + }; |
| 86 | + ESP_GOTO_ON_ERROR(gpio_config(&rst_gpio_config), err, TAG, "GPIO reset config failed"); |
| 87 | + } |
| 88 | + /* Reset controller */ |
| 89 | + ESP_GOTO_ON_ERROR(reset(chsc6540), err, TAG, "Reset failed"); |
| 90 | + /* Read product id */ |
| 91 | + // ESP_GOTO_ON_ERROR(read_id(chsc6540), err, TAG, "Read version failed"); |
| 92 | + *tp = chsc6540; |
| 93 | + |
| 94 | + ESP_LOGI(TAG, "LCD touch panel create success, version: %d.%d.%d", ESP_LCD_TOUCH_CHSC6540_VER_MAJOR, ESP_LCD_TOUCH_CHSC6540_VER_MINOR, |
| 95 | + ESP_LCD_TOUCH_CHSC6540_VER_PATCH); |
| 96 | + |
| 97 | + return ESP_OK; |
| 98 | +err: |
| 99 | + if (chsc6540) { |
| 100 | + del(chsc6540); |
| 101 | + } |
| 102 | + ESP_LOGE(TAG, "Initialization failed!"); |
| 103 | + return ret; |
| 104 | +} |
| 105 | + |
| 106 | +static esp_err_t read_data(esp_lcd_touch_handle_t tp) |
| 107 | +{ |
| 108 | + typedef struct { |
| 109 | + uint8_t num; |
| 110 | + uint8_t x_h : 4; |
| 111 | + uint8_t : 4; |
| 112 | + uint8_t x_l; |
| 113 | + uint8_t y_h : 4; |
| 114 | + uint8_t : 4; |
| 115 | + uint8_t y_l; |
| 116 | + } data_t; |
| 117 | + |
| 118 | + data_t point; |
| 119 | + |
| 120 | + uint8_t buf[15]={0}; |
| 121 | + uint8_t touch_num=0; |
| 122 | + uint16_t x=0; |
| 123 | + uint16_t y=0; |
| 124 | + uint8_t gc=0;//报点过程 |
| 125 | + ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, DATA_START_REG, buf, sizeof(buf)), TAG, "I2C read failed"); |
| 126 | + |
| 127 | + point.num=buf[2]; |
| 128 | + |
| 129 | + gc=buf[3]>>4; |
| 130 | + |
| 131 | + x= (uint16_t)(((buf[3]&0x0F)<<8)+buf[4]); |
| 132 | + y= (uint16_t)(((buf[5]&0x0F)<<8)+buf[6]); |
| 133 | + |
| 134 | + |
| 135 | + portENTER_CRITICAL(&tp->data.lock); |
| 136 | + point.num = (point.num > POINT_NUM_MAX ? POINT_NUM_MAX : point.num); |
| 137 | + tp->data.points = point.num; |
| 138 | + /* Fill all coordinates */ |
| 139 | + for (int i = 0; i < tp->data.points ; i++) { |
| 140 | + tp->data.coords[i].x = x; |
| 141 | + tp->data.coords[i].y = y; |
| 142 | + } |
| 143 | + portEXIT_CRITICAL(&tp->data.lock); |
| 144 | + |
| 145 | + return ESP_OK; |
| 146 | +} |
| 147 | + |
| 148 | +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) |
| 149 | +{ |
| 150 | + portENTER_CRITICAL(&tp->data.lock); |
| 151 | + /* Count of points */ |
| 152 | + *point_num = (tp->data.points > max_point_num ? max_point_num : tp->data.points); |
| 153 | + for (size_t i = 0; i < *point_num; i++) { |
| 154 | + x[i] = tp->data.coords[i].x; |
| 155 | + y[i] = tp->data.coords[i].y; |
| 156 | + |
| 157 | + if (strength) { |
| 158 | + strength[i] = tp->data.coords[i].strength; |
| 159 | + } |
| 160 | + } |
| 161 | + /* Invalidate */ |
| 162 | + tp->data.points = 0; |
| 163 | + portEXIT_CRITICAL(&tp->data.lock); |
| 164 | + |
| 165 | + return (*point_num > 0); |
| 166 | +} |
| 167 | + |
| 168 | +static esp_err_t del(esp_lcd_touch_handle_t tp) |
| 169 | +{ |
| 170 | + /* Reset GPIO pin settings */ |
| 171 | + if (tp->config.int_gpio_num != GPIO_NUM_NC) { |
| 172 | + gpio_reset_pin(tp->config.int_gpio_num); |
| 173 | + if (tp->config.interrupt_callback) { |
| 174 | + gpio_isr_handler_remove(tp->config.int_gpio_num); |
| 175 | + } |
| 176 | + } |
| 177 | + if (tp->config.rst_gpio_num != GPIO_NUM_NC) { |
| 178 | + gpio_reset_pin(tp->config.rst_gpio_num); |
| 179 | + } |
| 180 | + /* Release memory */ |
| 181 | + free(tp); |
| 182 | + |
| 183 | + return ESP_OK; |
| 184 | +} |
| 185 | + |
| 186 | +static esp_err_t reset(esp_lcd_touch_handle_t tp) |
| 187 | +{ |
| 188 | + if (tp->config.rst_gpio_num != GPIO_NUM_NC) { |
| 189 | + ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, tp->config.levels.reset), TAG, "GPIO set level failed"); |
| 190 | + vTaskDelay(pdMS_TO_TICKS(200)); |
| 191 | + ESP_RETURN_ON_ERROR(gpio_set_level(tp->config.rst_gpio_num, !tp->config.levels.reset), TAG, "GPIO set level failed"); |
| 192 | + vTaskDelay(pdMS_TO_TICKS(200)); |
| 193 | + } |
| 194 | + |
| 195 | + return ESP_OK; |
| 196 | +} |
| 197 | + |
| 198 | +static esp_err_t read_id(esp_lcd_touch_handle_t tp) |
| 199 | +{ |
| 200 | + uint8_t id; |
| 201 | + ESP_RETURN_ON_ERROR(i2c_read_bytes(tp, CHIP_ID_REG, &id, 1), TAG, "I2C read failed"); |
| 202 | + ESP_LOGI(TAG, "IC id: %d", id); |
| 203 | + return ESP_OK; |
| 204 | +} |
| 205 | + |
| 206 | +static esp_err_t i2c_read_bytes(esp_lcd_touch_handle_t tp, uint16_t reg, uint8_t *data, uint8_t len) |
| 207 | +{ |
| 208 | + ESP_RETURN_ON_FALSE(data, ESP_ERR_INVALID_ARG, TAG, "Invalid data"); |
| 209 | + |
| 210 | + return esp_lcd_panel_io_rx_param(tp->io, reg, data, len); |
| 211 | +} |
0 commit comments