# esp_lcd_touch_gsl3680
([English](README.md) | 中文 | [日本語](README_ja.md))
Silead GSL3680 电容触摸驱动,实现 ESP-IDF 的
[`esp_lcd_touch`](https://components.espressif.com/components/espressif/esp_lcd_touch)
接口。
## 安装
```bash
idf.py add-dependency "mangoo1/esp_lcd_touch_gsl3680^1.0.0"
```
或写进 `main/idf_component.yml`:
```yaml
dependencies:
mangoo1/esp_lcd_touch_gsl3680: "^1.0.0"
```
## 用法
芯片挂在 I2C 上,地址 `0x40`。复位和中断都是**低电平有效**。
```c
#include "esp_lcd_gsl3680.h"
// 1. 触摸复用已有的 I2C 主机总线
esp_lcd_panel_io_i2c_config_t io_cfg = ESP_LCD_TOUCH_IO_I2C_GSL3680_CONFIG();
io_cfg.scl_speed_hz = 400 * 1000;
esp_lcd_panel_io_handle_t io = NULL;
ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus, &io_cfg, &io));
// 2. x_max/y_max 要填屏幕的原生分辨率
esp_lcd_touch_config_t tp_cfg = {
.x_max = 800,
.y_max = 1280,
.rst_gpio_num = GPIO_NUM_22,
.int_gpio_num = GPIO_NUM_21,
.levels = {
.reset = 0, // 低电平有效
.interrupt = 0, // 低电平有效
},
.flags = {
.swap_xy = 0,
.mirror_x = 0,
.mirror_y = 1,
},
};
esp_lcd_touch_handle_t tp = NULL;
ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gsl3680(io, &tp_cfg, &tp));
```
### 读坐标
```c
uint16_t x[1], y[1], strength[1];
uint8_t count = 0;
esp_lcd_touch_read_data(tp);
if (esp_lcd_touch_get_coordinates(tp, x, y, strength, &count, 1)) {
printf("触摸位置 %d,%d\n", x[0], y[0]);
}
```
### 配合 LVGL
```c
#include <esp_lvgl_port.h>
const lvgl_port_touch_cfg_t touch_cfg = {
.disp = lv_display_get_default(),
.handle = tp,
};
lvgl_port_add_touch(&touch_cfg);
```
### 方向
`swap_xy` / `mirror_x` / `mirror_y` 必须跟你显示屏的方向设置一致,否则**触摸坐标会和画面对不上**。也可以运行时改:
```c
esp_lcd_touch_set_mirror_y(tp, true);
```
### 触摸可选
如果这块板子可能没装触摸屏,先探测地址,让没有触摸的板子也能正常启动:
```c
if (i2c_master_probe(i2c_bus, ESP_LCD_TOUCH_IO_I2C_GSL3680_ADDRESS, 100) != ESP_OK) {
ESP_LOGW(TAG, "未检测到触摸控制器,跳过");
return;
}
```
## 启动耗时
初始化时驱动会向芯片上传固件,**约 800ms**。安排启动流程时要预留这段时间,也不要在看门狗超时很短的上下文里调用。
## 已知问题
固件上传完成后,驱动会打印:
```
gsl3680 startup_chip failed read 0xb0 = 5a,5a,5a,5a
```
然后照常报告成功并继续。`5a5a5a5a` 是占位模式,说明芯片没有返回真实的启动状态。固件上传本身是成功的,芯片也能在 I2C 上响应,但这条路径**尚未定位到根因**。
## 相对厂商源码的修复
手势判断路径上的两个整数类型 bug:
**`chazhi` 原本是 `uint16_t`。** 它存的是 `distance - pre_distance`,一个**有符号**差值,所以 `chazhi < -900` 这个缩小分支永远进不去,**双指缩小手势从来不会触发**。现已改为 `int32_t`。
**`distance` 原本也是 `uint16_t`。** 它存的是距离的**平方** `(x1-x2)² + (y1-y2)²`,在 800×1280 屏上最大可达 2278400,**必然溢出**。而 `pre_distance` 本身却是 `uint32_t`,两者类型不一致。现在都是 `uint32_t`。
## 实测环境
晶彩 JC8012P4A1C —— ESP32-P4,10.1" 800×1280 JD9365 屏,ESP-IDF v6.0.2。
固件上传和控制器初始化已确认正常。**坐标上报未经系统性验证。**
## 许可证
**GPL-2.0-or-later。**
`gsl_point_id.c` 是 Silead 的触摸跟踪算法,源自 Linux 内核驱动
`drivers/input/touchscreen/mediatek/gslX680/`(© 2010–2016 Silead Inc.)。它和其余代码链接进同一个库,因此**整个组件都是 GPL-2.0-or-later**。
**如果你的项目是 MIT 或 Apache 许可**,不要把这些源码直接拷进你的代码树 —— 那会让你**整个项目被迫变成 GPL**。请以组件方式依赖它,这样许可证边界才是清晰的。
`esp_lcd_gsl3680.c` 和头文件来自晶彩 JC8012P4A1C 的厂商 SDK,原文件没有许可证声明,此处按相同条款分发。
idf.py add-dependency "mangoo1/esp_lcd_touch_gsl3680^1.0.0"