#include "touch.h" #include "board_config.h" #include "driver/gpio.h" #include "driver/i2c_master.h" #include "esp_lcd_io_i2c.h" #include "esp_lcd_panel_io.h" #include "esp_lcd_touch.h" #include "esp_lcd_touch_cst816s.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "freertos/task.h" static const char *TAG = "touch"; #if BOARD_TOUCH_ENABLED static i2c_master_bus_handle_t s_touch_i2c_bus; static esp_lcd_touch_handle_t s_touch_handle; static SemaphoreHandle_t s_touch_mux; static void touch_isr_cb(esp_lcd_touch_handle_t tp) { BaseType_t task_woken = pdFALSE; (void)tp; xSemaphoreGiveFromISR(s_touch_mux, &task_woken); if (task_woken) { portYIELD_FROM_ISR(); } } static void lvgl_touch_read_cb(lv_indev_t *indev, lv_indev_data_t *data) { esp_lcd_touch_handle_t tp = lv_indev_get_user_data(indev); if (xSemaphoreTake(s_touch_mux, 0) == pdTRUE) { esp_lcd_touch_read_data(tp); } esp_lcd_touch_point_data_t points[1]; uint8_t point_cnt = 0; if (esp_lcd_touch_get_data(tp, points, &point_cnt, 1) == ESP_OK && point_cnt > 0) { data->point.x = points[0].x; data->point.y = points[0].y; data->state = LV_INDEV_STATE_PRESSED; } else { data->state = LV_INDEV_STATE_RELEASED; } } esp_err_t touch_init(lv_display_t *display) { ESP_LOGI(TAG, "Initialize I2C for touch"); i2c_master_bus_config_t bus_config = { .clk_source = I2C_CLK_SRC_DEFAULT, .i2c_port = BOARD_TOUCH_I2C_NUM, .sda_io_num = BOARD_PIN_TOUCH_SDA, .scl_io_num = BOARD_PIN_TOUCH_SCL, .glitch_ignore_cnt = 7, .flags.enable_internal_pullup = true, }; ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &s_touch_i2c_bus)); s_touch_mux = xSemaphoreCreateBinary(); if (s_touch_mux == NULL) { ESP_LOGE(TAG, "Failed to create touch semaphore"); return ESP_ERR_NO_MEM; } ESP_LOGI(TAG, "Initialize touch panel IO (CST816S)"); esp_lcd_panel_io_handle_t tp_io_handle = NULL; esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG(); tp_io_config.scl_speed_hz = BOARD_TOUCH_I2C_FREQ_HZ; ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(s_touch_i2c_bus, &tp_io_config, &tp_io_handle)); ESP_LOGI(TAG, "Initialize touch controller CST816S"); esp_lcd_touch_config_t tp_cfg = { .x_max = BOARD_LCD_H_RES, .y_max = BOARD_LCD_V_RES, .rst_gpio_num = BOARD_PIN_TOUCH_RST, .int_gpio_num = BOARD_PIN_TOUCH_INT, .levels = { .reset = 0, .interrupt = 0, }, .flags = { .swap_xy = BOARD_TOUCH_SWAP_XY, .mirror_x = BOARD_TOUCH_MIRROR_X, .mirror_y = BOARD_TOUCH_MIRROR_Y, }, .interrupt_callback = touch_isr_cb, }; ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &s_touch_handle)); lv_indev_t *indev = lv_indev_create(); lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); lv_indev_set_display(indev, display); lv_indev_set_user_data(indev, s_touch_handle); lv_indev_set_read_cb(indev, lvgl_touch_read_cb); return ESP_OK; } i2c_master_bus_handle_t touch_get_i2c_bus(void) { return s_touch_i2c_bus; } #else esp_err_t touch_init(lv_display_t *display) { (void)display; return ESP_OK; } i2c_master_bus_handle_t touch_get_i2c_bus(void) { return NULL; } #endif