From 7961bcc920755c438f4dbd5afcca1b94fe2639b7 Mon Sep 17 00:00:00 2001 From: wanghaolong Date: Fri, 3 Jul 2026 18:55:30 +0800 Subject: [PATCH] Add capacitive touch LCD driver --- CMakeLists.txt | 2 +- README.md | 32 ----- dependencies.lock | 34 +++++ main/CMakeLists.txt | 4 +- main/Kconfig.projbuild | 11 -- main/board_config.h | 18 +++ main/capacitive_touch.c | 292 ++++++++++++++++++++++++++++++++++++++++ main/capacitive_touch.h | 38 ++++++ main/eye_image.c | 2 +- main/eye_image.h | 2 +- main/icon_image.c | 2 +- main/icon_image.h | 2 +- main/idf_component.yml | 2 + main/lcd_reg.c | 37 +++-- main/lcd_reg.h | 3 +- main/main.c | 108 ++++++++++++++- main/upper_app.c | 2 +- main/upper_app.h | 2 +- main/write.c | 2 +- main/write.h | 2 +- 20 files changed, 529 insertions(+), 68 deletions(-) delete mode 100644 README.md create mode 100644 dependencies.lock delete mode 100644 main/Kconfig.projbuild create mode 100644 main/board_config.h create mode 100644 main/capacitive_touch.c create mode 100644 main/capacitive_touch.h create mode 100644 main/idf_component.yml diff --git a/CMakeLists.txt b/CMakeLists.txt index 2eefd12..72a62fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.16) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(lcd) +project(touch) diff --git a/README.md b/README.md deleted file mode 100644 index a7f75e0..0000000 --- a/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# LCD backlight test - -This program only turns on the LCD backlight GPIO. - -It does not initialize SPI. -It does not initialize the LCD controller. -It does not write any pixel data. - -Set `LCD_PIN_BL` to the GPIO connected to the LCD `BLK` pin. -Set `LCD_BL_ACTIVE_HIGH` to match the board. - -Build and flash: - -```powershell -idf.py menuconfig -idf.py build -idf.py -p COMx flash -``` - -Expected result: the LCD backlight turns on and stays on. - -## Update image data - -Use this script to generate `main/eye_image.c` and `main/eye_image.h` from an -image or GIF: - -```powershell -C:\Users\28036\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe D:\esp\Project\lcd\tools\gif_to_eye_image.py D:\esp\Project\lcd\source\eye2.bmp -``` - -For GIF files, use `--max-frames` or `--step` if the generated file is too -large. diff --git a/dependencies.lock b/dependencies.lock new file mode 100644 index 0000000..c63a5ae --- /dev/null +++ b/dependencies.lock @@ -0,0 +1,34 @@ +dependencies: + espressif/esp_lcd_touch: + component_hash: 3f85a7d95af876f1a6ecca8eb90a81614890d0f03a038390804e5a77e2caf862 + dependencies: + - name: idf + require: private + version: '>=4.4.2' + source: + registry_url: https://components.espressif.com + type: service + version: 1.2.1 + espressif/esp_lcd_touch_gt911: + component_hash: 6029febef66eefd0910d527d7f30292779ccbf22a8dedd2bd69466acf0068a7b + dependencies: + - name: espressif/esp_lcd_touch + registry_url: https://components.espressif.com + require: public + version: ^1.2.0 + - name: idf + require: private + version: '>=5.2' + source: + registry_url: https://components.espressif.com/ + type: service + version: 1.2.0~2 + idf: + source: + type: idf + version: 5.5.4 +direct_dependencies: +- espressif/esp_lcd_touch_gt911 +manifest_hash: c9b5e7d651a2702a6915ea7b0d5687b74992dfd8c49d37cec4c5482f8fc7ca3a +target: esp32s3 +version: 2.0.0 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f7de3dd..3eacbf5 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,3 +1,3 @@ -idf_component_register(SRCS "icon_image.c" "upper_app.c" "eye_image.c" "write.c" "lcd_reg.c" "main.c" +idf_component_register(SRCS "icon_image.c" "upper_app.c" "eye_image.c" "write.c" "lcd_reg.c" "capacitive_touch.c" "main.c" INCLUDE_DIRS "." - PRIV_REQUIRES esp_driver_gpio esp_driver_spi freertos) + PRIV_REQUIRES esp_driver_gpio esp_driver_spi esp_driver_i2c esp_lcd esp_lcd_touch esp_lcd_touch_gt911 freertos) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild deleted file mode 100644 index 0669792..0000000 --- a/main/Kconfig.projbuild +++ /dev/null @@ -1,11 +0,0 @@ -menu "LCD backlight test" - - config LCD_PIN_BL - int "LCD BLK/backlight GPIO" - default -1 - - config LCD_BL_ACTIVE_HIGH - bool "Backlight is active high" - default y - -endmenu diff --git a/main/board_config.h b/main/board_config.h new file mode 100644 index 0000000..26b4a0b --- /dev/null +++ b/main/board_config.h @@ -0,0 +1,18 @@ +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +// LCD SPI pins +#define LCD_PIN_CLK 12 +#define LCD_PIN_MOSI 11 +#define LCD_PIN_RES 10 +#define LCD_PIN_DC 9 +#define LCD_PIN_CS 8 +#define LCD_PIN_BLK 1 + +// GT911 capacitive touch pins +#define TOUCH_PIN_RES LCD_PIN_RES +#define TOUCH_PIN_SCL 14 +#define TOUCH_PIN_SDA 13 +#define TOUCH_PIN_INT 2 + +#endif diff --git a/main/capacitive_touch.c b/main/capacitive_touch.c new file mode 100644 index 0000000..ef7f20e --- /dev/null +++ b/main/capacitive_touch.c @@ -0,0 +1,292 @@ +#include "capacitive_touch.h" + +#include "driver/gpio.h" +#include "driver/i2c_master.h" +#include "esp_lcd_panel_io.h" +#include "esp_err.h" +#include "esp_lcd_io_i2c.h" +#include "esp_lcd_touch.h" +#include "esp_lcd_touch_gt911.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define TOUCH_I2C_PORT 0 +#define TOUCH_I2C_TIMEOUT_MS 100 + +static const char *TAG = "gt911_touch"; +static i2c_master_bus_handle_t touch_i2c_bus; +static esp_lcd_panel_io_handle_t touch_io; +static esp_lcd_touch_handle_t touch_handle; +static bool touch_ready; +static bool touch_active; +static uint8_t touch_count; +static uint8_t touch_id; +static uint8_t touch_addr; + +static uint16_t clamp_coord(uint16_t value, uint16_t max) +{ + return value > max ? max : value; +} + +static void transform_touch_coord(uint16_t raw_x, uint16_t raw_y, uint16_t *x, uint16_t *y) +{ + if (TOUCH_SWAP_XY) { + *x = raw_y; + *y = raw_x; + } else { + *x = raw_x; + *y = raw_y; + } + + if (TOUCH_INVERT_X) { + *x = (*x >= TOUCH_WIDTH) ? 0 : (TOUCH_WIDTH - 1 - *x); + } + + if (TOUCH_INVERT_Y) { + *y = (*y >= TOUCH_HEIGHT) ? 0 : (TOUCH_HEIGHT - 1 - *y); + } + + *x = clamp_coord(*x, TOUCH_WIDTH - 1); + *y = clamp_coord(*y, TOUCH_HEIGHT - 1); +} + +static void touch_irq_input_init(void) +{ + gpio_config_t irq_config = { + .pin_bit_mask = 1ULL << TOUCH_PIN_INT, + .mode = GPIO_MODE_INPUT, + .pull_up_en = GPIO_PULLUP_ENABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&irq_config); +} + +static void touch_log_pin_levels(void) +{ + int scl_level = gpio_get_level(TOUCH_PIN_SCL); + int sda_level = gpio_get_level(TOUCH_PIN_SDA); + int int_level = gpio_get_level(TOUCH_PIN_INT); + + ESP_LOGI(TAG, "touch pins: SCL=GPIO%d level=%d, SDA=GPIO%d level=%d, INT=GPIO%d level=%d", + TOUCH_PIN_SCL, scl_level, TOUCH_PIN_SDA, sda_level, TOUCH_PIN_INT, int_level); + + if (scl_level == 0 || sda_level == 0) { + ESP_LOGW(TAG, "I2C bus is not idle, SCL and SDA should both be high before communication"); + } +} + +static void touch_select_i2c_addr(uint8_t dev_addr) +{ + gpio_config_t rst_config = { + .pin_bit_mask = 1ULL << TOUCH_PIN_RES, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config_t int_output_config = { + .pin_bit_mask = 1ULL << TOUCH_PIN_INT, + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_ENABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + + ESP_LOGI(TAG, "select GT911 address 0x%02x", dev_addr); + gpio_config(&rst_config); + gpio_config(&int_output_config); + + gpio_set_level(TOUCH_PIN_RES, 0); + gpio_set_level(TOUCH_PIN_INT, dev_addr == ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP ? 1 : 0); + vTaskDelay(pdMS_TO_TICKS(20)); + gpio_set_level(TOUCH_PIN_RES, 1); + vTaskDelay(pdMS_TO_TICKS(60)); + + touch_irq_input_init(); +} + +static bool touch_i2c_probe_addr(uint8_t dev_addr) +{ + ESP_LOGI(TAG, "probe GT911 at 0x%02x", dev_addr); + esp_err_t err = i2c_master_probe(touch_i2c_bus, dev_addr, TOUCH_I2C_TIMEOUT_MS); + if (err == ESP_OK) { + ESP_LOGI(TAG, "GT911 responds at 0x%02x", dev_addr); + return true; + } + + ESP_LOGW(TAG, "GT911 no ACK at 0x%02x: %s", dev_addr, esp_err_to_name(err)); + return false; +} + +static esp_err_t touch_i2c_init(void) +{ + i2c_master_bus_config_t bus_config = { + .i2c_port = TOUCH_I2C_PORT, + .sda_io_num = TOUCH_PIN_SDA, + .scl_io_num = TOUCH_PIN_SCL, + .clk_source = I2C_CLK_SRC_DEFAULT, + .glitch_ignore_cnt = 7, + .flags.enable_internal_pullup = true, + }; + + esp_err_t err = i2c_new_master_bus(&bus_config, &touch_i2c_bus); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + return err; + } + + return ESP_OK; +} + +static esp_err_t touch_driver_init_at_addr(uint8_t dev_addr) +{ + esp_lcd_panel_io_i2c_config_t io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); + esp_lcd_touch_io_gt911_config_t gt911_config = { + .dev_addr = dev_addr, + }; + esp_lcd_touch_config_t touch_config = { + .x_max = TOUCH_WIDTH, + .y_max = TOUCH_HEIGHT, + .rst_gpio_num = TOUCH_PIN_RES, + .int_gpio_num = TOUCH_PIN_INT, + .levels = { + .reset = 0, + .interrupt = 0, + }, + .flags = { + .swap_xy = false, + .mirror_x = false, + .mirror_y = false, + }, + .driver_data = >911_config, + }; + + io_config.dev_addr = dev_addr; + + esp_err_t err = esp_lcd_new_panel_io_i2c(touch_i2c_bus, &io_config, &touch_io); + if (err != ESP_OK) { + ESP_LOGE(TAG, "touch panel IO init failed at 0x%02x: %s", dev_addr, esp_err_to_name(err)); + return err; + } + + err = esp_lcd_touch_new_i2c_gt911(touch_io, &touch_config, &touch_handle); + if (err != ESP_OK) { + ESP_LOGW(TAG, "GT911 driver init failed at 0x%02x: %s", dev_addr, esp_err_to_name(err)); + esp_lcd_panel_io_del(touch_io); + touch_io = NULL; + touch_handle = NULL; + return err; + } + + touch_addr = dev_addr; + return ESP_OK; +} + +bool capacitive_touch_is_pressed(void) +{ + return touch_active || gpio_get_level(TOUCH_PIN_INT) == 0; +} + +bool capacitive_touch_read_raw(uint16_t *x, uint16_t *y) +{ + esp_lcd_touch_point_data_t point_data[TOUCH_MAX_POINTS] = {0}; + uint8_t point_count = 0; + + if (!x || !y || !touch_ready) { + return false; + } + + if (esp_lcd_touch_read_data(touch_handle) != ESP_OK) { + touch_active = false; + touch_count = 0; + return false; + } + + if (esp_lcd_touch_get_data(touch_handle, point_data, &point_count, TOUCH_MAX_POINTS) != ESP_OK || point_count == 0) { + touch_active = false; + touch_count = 0; + return false; + } + + *x = point_data[0].x; + *y = point_data[0].y; + touch_id = point_data[0].track_id; + touch_count = point_count; + touch_active = true; + return true; +} + +bool capacitive_touch_read(capacitive_touch_point_t *point) +{ + uint16_t raw_x; + uint16_t raw_y; + uint16_t x; + uint16_t y; + + if (!point) { + return false; + } + + point->pressed = false; + point->count = 0; + if (!capacitive_touch_read_raw(&raw_x, &raw_y)) { + return false; + } + + point->raw_x = raw_x; + point->raw_y = raw_y; + point->id = touch_id; + point->count = touch_count; + + transform_touch_coord(raw_x, raw_y, &x, &y); + point->x = x; + point->y = y; + point->pressed = true; + return true; +} + +void capacitive_touch_init(void) +{ + uint8_t detected_addr = 0; + + touch_irq_input_init(); + + ESP_LOGI(TAG, "I2C init start"); + esp_err_t err = touch_i2c_init(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "I2C init failed: %s", esp_err_to_name(err)); + return; + } + ESP_LOGI(TAG, "I2C init done"); + + touch_log_pin_levels(); + + touch_select_i2c_addr(ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS); + touch_log_pin_levels(); + if (touch_i2c_probe_addr(ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS)) { + detected_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS; + } else { + touch_select_i2c_addr(ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP); + touch_log_pin_levels(); + if (touch_i2c_probe_addr(ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP)) { + detected_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP; + } + } + + if (detected_addr == 0) { + ESP_LOGE(TAG, "GT911 not responding at 0x%02x or 0x%02x", + ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS, ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP); + return; + } + + ESP_LOGI(TAG, "GT911 driver init start at 0x%02x", detected_addr); + err = touch_driver_init_at_addr(detected_addr); + if (err != ESP_OK) { + ESP_LOGE(TAG, "GT911 driver init failed at 0x%02x: %s", detected_addr, esp_err_to_name(err)); + return; + } + + touch_ready = true; + ESP_LOGI(TAG, "official GT911 driver started at 0x%02x", touch_addr); +} diff --git a/main/capacitive_touch.h b/main/capacitive_touch.h new file mode 100644 index 0000000..9c74bf0 --- /dev/null +++ b/main/capacitive_touch.h @@ -0,0 +1,38 @@ +#ifndef CAPACITIVE_TOUCH_H +#define CAPACITIVE_TOUCH_H + +#include +#include + +#include "board_config.h" + +#define TOUCH_WIDTH 320 +#define TOUCH_HEIGHT 240 +#define TOUCH_MAX_POINTS 5 + +/* + * GT911 reports this panel as 240x320 in the vendor portrait examples. + * The app keeps the original 320x240 landscape coordinate system. + */ +#define TOUCH_SWAP_XY 1 +#define TOUCH_INVERT_X 1 +#define TOUCH_INVERT_Y 0 + +typedef struct { + uint16_t x; + uint16_t y; + uint16_t raw_x; + uint16_t raw_y; + uint8_t id; + uint8_t count; + bool pressed; +} capacitive_touch_point_t; + +void capacitive_touch_init(void); +bool capacitive_touch_read(capacitive_touch_point_t *point); +bool capacitive_touch_read_raw(uint16_t *x, uint16_t *y); +bool capacitive_touch_is_pressed(void); + +#endif + + diff --git a/main/eye_image.c b/main/eye_image.c index 0279dcb..58141e4 100644 --- a/main/eye_image.c +++ b/main/eye_image.c @@ -1,4 +1,4 @@ -#include "eye_image.h" +#include "eye_image.h" static const rle_structure_t shangshangqian0[]; diff --git a/main/eye_image.h b/main/eye_image.h index fd5b4f5..6ba79c3 100644 --- a/main/eye_image.h +++ b/main/eye_image.h @@ -1,4 +1,4 @@ -#ifndef EYE_IMAGE_H +#ifndef EYE_IMAGE_H #define EYE_IMAGE_H #include diff --git a/main/icon_image.c b/main/icon_image.c index 98d2c41..b11e714 100644 --- a/main/icon_image.c +++ b/main/icon_image.c @@ -1,4 +1,4 @@ -#include "icon_image.h" +#include "icon_image.h" static const rle_structure_t shui0[] = { {0x0000, 73}, {0x1125, 1}, {0x22AD, 1}, {0x22AC, 1}, {0x0905, 1}, {0x0000, 54}, {0x08C3, 1}, {0x561C, 1}, {0x561D, 5}, {0x4D9A, 1}, {0x0882, 1}, {0x0000, 51}, {0x55FC, 1}, {0x561D, 8}, {0x44B6, 1}, {0x0000, 50}, {0x561D, 2}, {0x4496, 1}, {0x0000, 2}, {0x0905, 1}, {0x44F7, 1}, {0x561D, 3}, {0x561C, 1}, {0x0000, 49}, {0x561D, 2}, {0x44D7, 1}, {0x0000, 4}, {0x0062, 1}, {0x55DC, 1}, {0x561D, 3}, {0x1166, 1}, {0x0000, 47}, {0x4DBB, 1}, {0x561D, 2}, {0x0000, 6}, {0x44B6, 1}, {0x561D, 3}, {0x2ACD, 1}, {0x0000, 24}, {0x1A2A, 1}, {0x33D2, 1}, {0x1A2A, 1}, {0x0000, 19}, {0x0904, 1}, {0x561D, 2}, {0x561C, 1}, {0x0020, 1}, {0x0000, 5}, {0x22AC, 1}, {0x561D, 3}, diff --git a/main/icon_image.h b/main/icon_image.h index 01ecd58..bc5f893 100644 --- a/main/icon_image.h +++ b/main/icon_image.h @@ -1,4 +1,4 @@ -#ifndef ICON_IMAGE_H +#ifndef ICON_IMAGE_H #define ICON_IMAGE_H #include diff --git a/main/idf_component.yml b/main/idf_component.yml new file mode 100644 index 0000000..24cfc0e --- /dev/null +++ b/main/idf_component.yml @@ -0,0 +1,2 @@ +dependencies: + espressif/esp_lcd_touch_gt911: "^1" diff --git a/main/lcd_reg.c b/main/lcd_reg.c index 4917543..bb7df8f 100644 --- a/main/lcd_reg.c +++ b/main/lcd_reg.c @@ -1,4 +1,6 @@ -#include "lcd_reg.h" +#include "lcd_reg.h" + +#include "board_config.h" #include "driver/gpio.h" #include "driver/spi_master.h" @@ -8,12 +10,6 @@ #define LCD_SPI_HOST SPI2_HOST -#define LCD_PIN_BL 1 -#define LCD_PIN_CS 8 -#define LCD_PIN_DC 9 -#define LCD_PIN_RES 10 -#define LCD_PIN_SDA 11 -#define LCD_PIN_SCL 12 #define LCD_CMD_SWRESET 0x01 #define LCD_CMD_SLPOUT 0x11 @@ -27,6 +23,7 @@ static spi_device_handle_t lcd_spi; static SemaphoreHandle_t lcd_mutex; +static bool lcd_spi_ready; /* Timing */ @@ -83,7 +80,7 @@ void lcd_write_pixels(const void *data, uint32_t length) static void lcd_gpio_init(void) { gpio_config_t gpio_config_data = { - .pin_bit_mask = (1ULL << LCD_PIN_BL) | (1ULL << LCD_PIN_DC) | (1ULL << LCD_PIN_RES), + .pin_bit_mask = (1ULL << LCD_PIN_BLK) | (1ULL << LCD_PIN_DC) | (1ULL << LCD_PIN_RES), .mode = GPIO_MODE_OUTPUT, .pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, @@ -91,17 +88,21 @@ static void lcd_gpio_init(void) }; gpio_config(&gpio_config_data); - gpio_set_level(LCD_PIN_BL, 1); + gpio_set_level(LCD_PIN_BLK, 1); gpio_set_level(LCD_PIN_DC, 0); gpio_set_level(LCD_PIN_RES, 1); } static void lcd_spi_init(void) { + if (lcd_spi_ready) { + return; + } + spi_bus_config_t bus_config = { - .mosi_io_num = LCD_PIN_SDA, + .mosi_io_num = LCD_PIN_MOSI, .miso_io_num = -1, - .sclk_io_num = LCD_PIN_SCL, + .sclk_io_num = LCD_PIN_CLK, .quadwp_io_num = -1, .quadhd_io_num = -1, .max_transfer_sz = LCD_WIDTH * 40 * 2, @@ -117,6 +118,7 @@ static void lcd_spi_init(void) }; spi_bus_add_device(LCD_SPI_HOST, &device_config, &lcd_spi); + lcd_spi_ready = true; } static void lcd_reset(void) @@ -151,10 +153,21 @@ static void lcd_controller_init(void) void lcd_reg_init(void) { - lcd_mutex = xSemaphoreCreateMutex(); + if (!lcd_mutex) { + lcd_mutex = xSemaphoreCreateMutex(); + } lcd_gpio_init(); lcd_spi_init(); lcd_reset(); lcd_controller_init(); } + +void lcd_reg_restore(void) +{ + lcd_gpio_init(); + lcd_spi_init(); + lcd_controller_init(); +} + + diff --git a/main/lcd_reg.h b/main/lcd_reg.h index 01d0dd5..a47ef3f 100644 --- a/main/lcd_reg.h +++ b/main/lcd_reg.h @@ -1,4 +1,4 @@ -#ifndef LCD_REG_H +#ifndef LCD_REG_H #define LCD_REG_H #include @@ -7,6 +7,7 @@ #define LCD_HEIGHT 240 void lcd_reg_init(void); +void lcd_reg_restore(void); void lcd_set_window(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); void lcd_write_pixels(const void *data, uint32_t length); void lcd_delay_ms(uint32_t ms); diff --git a/main/main.c b/main/main.c index 9f5901c..1aecf15 100644 --- a/main/main.c +++ b/main/main.c @@ -1,8 +1,114 @@ +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "board_config.h" +#include "capacitive_touch.h" #include "lcd_reg.h" #include "upper_app.h" +static const char *TAG = "touch"; + +static void lcd_fill_white(void) +{ + enum { ROWS_PER_TRANSFER = 20 }; + static uint16_t white_buffer[LCD_WIDTH * ROWS_PER_TRANSFER]; + + for (uint32_t i = 0; i < LCD_WIDTH * ROWS_PER_TRANSFER; i++) { + white_buffer[i] = 0xFFFF; + } + + lcd_set_window(0, 0, LCD_WIDTH - 1, LCD_HEIGHT - 1); + for (uint16_t row = 0; row < LCD_HEIGHT; row += ROWS_PER_TRANSFER) { + uint16_t row_count = LCD_HEIGHT - row; + if (row_count > ROWS_PER_TRANSFER) { + row_count = ROWS_PER_TRANSFER; + } + + lcd_write_pixels(white_buffer, (uint32_t)LCD_WIDTH * row_count * 2); + } +} + +static void lcd_draw_touch_marker(uint16_t x, uint16_t y) +{ + enum { MARKER_SIZE = 9 }; + static uint16_t marker[MARKER_SIZE * MARKER_SIZE]; + + for (uint32_t i = 0; i < MARKER_SIZE * MARKER_SIZE; i++) { + marker[i] = 0xF800; + } + + uint16_t half = MARKER_SIZE / 2; + uint16_t x0 = x > half ? x - half : 0; + uint16_t y0 = y > half ? y - half : 0; + uint16_t x1 = x0 + MARKER_SIZE - 1; + uint16_t y1 = y0 + MARKER_SIZE - 1; + + if (x1 >= LCD_WIDTH) { + x1 = LCD_WIDTH - 1; + x0 = x1 - MARKER_SIZE + 1; + } + if (y1 >= LCD_HEIGHT) { + y1 = LCD_HEIGHT - 1; + y0 = y1 - MARKER_SIZE + 1; + } + + lcd_set_window(x0, y0, x1, y1); + lcd_write_pixels(marker, sizeof(marker)); +} + +static void touch_task(void *arg) +{ + bool was_pressed = false; + + (void)arg; + ESP_LOGI(TAG, "touch init started"); + capacitive_touch_init(); + ESP_LOGI(TAG, "touch init done"); + + ESP_LOGI(TAG, "lcd restore started"); + lcd_reg_restore(); + lcd_fill_white(); + ESP_LOGI(TAG, "lcd restore done"); + + ESP_LOGI(TAG, "capacitive touch terminal output started"); + + while (1) { + capacitive_touch_point_t point; + + if (capacitive_touch_read(&point)) { + if (!was_pressed) { + ESP_LOGI(TAG, "TOUCH DOWN"); + } + + ESP_LOGI(TAG, "TOUCH POINT x=%u y=%u raw_x=%u raw_y=%u id=%u count=%u", + point.x, point.y, point.raw_x, point.raw_y, point.id, point.count); + lcd_draw_touch_marker(point.x, point.y); + was_pressed = true; + } else if (was_pressed && !capacitive_touch_is_pressed()) { + ESP_LOGI(TAG, "TOUCH UP"); + was_pressed = false; + } + + vTaskDelay(pdMS_TO_TICKS(50)); + } +} + void app_main(void) { + ESP_LOGI(TAG, "lcd init started"); lcd_reg_init(); - upper_app_run(); + ESP_LOGI(TAG, "lcd init done"); + ESP_LOGI(TAG, "lcd pins: CLK=GPIO%d MOSI=GPIO%d RES=GPIO%d DC=GPIO%d CS=GPIO%d BLK=GPIO%d", + LCD_PIN_CLK, LCD_PIN_MOSI, LCD_PIN_RES, LCD_PIN_DC, LCD_PIN_CS, LCD_PIN_BLK); + + ESP_LOGI(TAG, "white screen test started"); + lcd_fill_white(); + ESP_LOGI(TAG, "white screen test done"); + + xTaskCreate(touch_task, "touch_task", 4096, NULL, 5, NULL); + + while (1) { + vTaskDelay(pdMS_TO_TICKS(1000)); + } } diff --git a/main/upper_app.c b/main/upper_app.c index e528bbf..b59312a 100644 --- a/main/upper_app.c +++ b/main/upper_app.c @@ -1,4 +1,4 @@ -#include "upper_app.h" +#include "upper_app.h" #include "eye_image.h" #include "write.h" diff --git a/main/upper_app.h b/main/upper_app.h index d287064..3da009f 100644 --- a/main/upper_app.h +++ b/main/upper_app.h @@ -1,4 +1,4 @@ -#ifndef UPPER_APP_H +#ifndef UPPER_APP_H #define UPPER_APP_H void upper_app_run(void); diff --git a/main/write.c b/main/write.c index 50f7db4..7ac7545 100644 --- a/main/write.c +++ b/main/write.c @@ -1,4 +1,4 @@ -#include "write.h" +#include "write.h" #include "eye_image.h" #include "icon_image.h" diff --git a/main/write.h b/main/write.h index 63d4bbc..4744f0d 100644 --- a/main/write.h +++ b/main/write.h @@ -1,4 +1,4 @@ -#ifndef WRITE_H +#ifndef WRITE_H #define WRITE_H #include