ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
gsl3670_touchscreen.cpp
Go to the documentation of this file.
2#include "esphome/core/log.h"
3#include "esphome/core/hal.h"
4
5namespace esphome::gsl3670 {
6
7static const char *const TAG = "gsl3670.touchscreen";
8static const size_t MAX_TOUCHES = 3;
9// ---------------------------------------------------------------------------
10// setup() – mirrors esp_lcd_touch_gsl3670_init() in the Seeed BSP:
11// clear_reg → reset → load_fw → startup_chip → reset → startup_chip
12// ---------------------------------------------------------------------------
14 ESP_LOGCONFIG(TAG, "Setting up GSL3670 touchscreen...");
15
16 if (this->reset_pin_ != nullptr) {
17 this->reset_pin_->setup();
18 this->reset_pin_->digital_write(true);
19 }
20
21 if (this->interrupt_pin_ != nullptr) {
22 this->interrupt_pin_->setup();
23 this->attach_interrupt_(this->interrupt_pin_, gpio::INTERRUPT_FALLING_EDGE);
24 }
25
26 if (this->x_raw_max_ == this->x_raw_min_) {
27 this->x_raw_max_ = this->display_->get_native_width();
28 }
29 if (this->y_raw_max_ == this->y_raw_min_) {
30 this->y_raw_max_ = this->display_->get_native_height();
31 }
32
33 this->clear_reg_();
34 this->reset_();
35 this->load_firmware_();
36 this->startup_chip_();
37 this->reset_();
38 this->startup_chip_();
39
40 ESP_LOGCONFIG(TAG, "GSL3670 initialised OK");
41}
42
44 ESP_LOGCONFIG(TAG,
45 "GSL3670 Touchscreen:\n"
46 " X-raw-max: %d\n"
47 " Y-raw-max: %d\n",
48 this->x_raw_max_, this->y_raw_max_);
49 LOG_I2C_DEVICE(this);
50 LOG_PIN(" Reset Pin: ", this->reset_pin_);
51 LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
52 ESP_LOGCONFIG(TAG, " Firmware records: %zu", this->firmware_len_);
53}
54
55// ---------------------------------------------------------------------------
56// update_touches() – mirrors esp_lcd_touch_gsl3670_read_data() in Seeed BSP
57// ---------------------------------------------------------------------------
59 uint8_t buf[44] = {};
60 auto err = this->read_register(0x80, buf, sizeof(buf));
61 if (err != i2c::ERROR_OK) {
62 ESP_LOGW(TAG, "I2C read failed (%d)", err);
63 return;
64 }
65 uint8_t finger_num = clamp_at_most(buf[0], MAX_TOUCHES);
66
67 // Build gsl_touch_info exactly as the Seeed driver does
68 for (uint8_t j = 0; j != finger_num; j++) {
69 // buf[(j+1)*4 + 0..3]: byte0=y_lo, byte1=y_hi, byte2=x_lo, byte3=id|x_hi
70 auto x = (uint16_t) (((buf[(j + 1) * 4 + 3] & 0x0f) << 8) | buf[(j + 1) * 4 + 2]);
71 auto y = (uint16_t) ((buf[(j + 1) * 4 + 1] << 8) | buf[(j + 1) * 4 + 0]);
72 auto id = (buf[(j + 1) * 4 + 3] >> 4) & 0x0f;
73 ESP_LOGV(TAG, "Touch id=%u, x=%u y=%u", id, x, y);
74 if (x <= 8192 && y <= 8192)
75 this->add_raw_touch_position_(id, x, y);
76 }
77}
78
79// ---------------------------------------------------------------------------
80// clear_reg_() – mirrors esp_lcd_touch_gsl3670_clear_reg()
81// GPIO reset → write 0x01 to 0x88 → write 0x04 to 0xe4 → write 0x00 to 0xe0
82// ---------------------------------------------------------------------------
83void GSL3670Touchscreen::clear_reg_() {
84 ESP_LOGD(TAG, "clear_reg");
85
86 // GPIO reset pulse
87 if (this->reset_pin_ != nullptr) {
88 this->reset_pin_->digital_write(false);
89 delay(1);
90 this->reset_pin_->digital_write(true);
91 delay(5);
92 }
93
94 this->write_reg8_(0x88, 0x01);
95 // delay(5);
96 this->write_reg8_(0xe4, 0x04);
97 // delay(5);
98 this->write_reg8_(0xe0, 0x00);
99 // delay(5);
100}
101
102// ---------------------------------------------------------------------------
103// reset_() – mirrors touch_gsl3670_reset()
104// GPIO reset → write 0x04 to 0xe4 → write 4×0x00 to 0xbc
105// ---------------------------------------------------------------------------
106void GSL3670Touchscreen::reset_() {
107 ESP_LOGD(TAG, "reset");
108
109 if (this->reset_pin_ != nullptr) {
110 this->reset_pin_->digital_write(false);
111 delay(1);
112 this->reset_pin_->digital_write(true);
113 delay(5);
114 }
115
116 this->write_reg8_(0xe4, 0x04);
117
118 uint8_t zeros[4] = {0, 0, 0, 0};
119 this->write_reg_(0xbc, zeros, 4);
120}
121
122void GSL3670Touchscreen::load_firmware_() {
123 if (firmware_ == nullptr || firmware_len_ == 0) {
124 ESP_LOGW(TAG, "No firmware supplied – skipping");
125 return;
126 }
127
128 ESP_LOGD(TAG, "Loading firmware (%zu blocks)...", firmware_len_);
129
130 static constexpr size_t FW_BLK_SIZE = 128 + 4;
131
132 for (size_t i = 0; i != this->firmware_len_; i++) {
133 auto offset = i * FW_BLK_SIZE;
134 uint8_t val = this->firmware_[offset + 0];
135 ESP_LOGV(TAG, "Firmware address 0x%02X", val);
136 this->write_reg_(0xf0, &val, 1);
137 this->write_reg_(0, this->firmware_ + offset + 4, 128);
138 }
139 ESP_LOGD(TAG, "Firmware load complete");
140}
141
142// ---------------------------------------------------------------------------
143// startup_chip_() – mirrors esp_lcd_touch_gsl3670_startup_chip()
144// write 0x00 to 0xe0
145// ---------------------------------------------------------------------------
146void GSL3670Touchscreen::startup_chip_() {
147 ESP_LOGD(TAG, "startup_chip");
148 this->write_reg8_(0xe0, 0x00);
149 delay(5);
150}
151
152// ---------------------------------------------------------------------------
153// I2C helpers
154// ---------------------------------------------------------------------------
155
156bool GSL3670Touchscreen::write_reg_(uint8_t reg, const uint8_t *data, size_t len) {
157 auto err = this->write_register(reg, data, len);
158 if (err != i2c::ERROR_OK) {
159 ESP_LOGW(TAG, "I2C write reg 0x%02X len %zu failed (%d)", reg, len, err);
160 return false;
161 }
162 return true;
163}
164
165bool GSL3670Touchscreen::write_reg8_(uint8_t reg, uint8_t val) { return write_reg_(reg, &val, 1); }
166
167} // namespace esphome::gsl3670
virtual void setup()=0
virtual void digital_write(bool value)=0
int get_native_width()
Get the native (original) width of the display in pixels.
Definition display.h:330
int get_native_height()
Get the native (original) height of the display in pixels.
Definition display.h:332
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len) const
writes an array of bytes to a specific register in the I²C device
Definition i2c.cpp:34
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition i2c.h:152
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len)
reads an array of bytes from a specific register in the I²C device
Definition i2c.cpp:25
void attach_interrupt_(InternalGPIOPin *irq_pin, esphome::gpio::InterruptType type)
Call this function to send touch points to the on_touch listener and the binary_sensors.
void add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw=0)
mopeka_std_values val[3]
@ INTERRUPT_FALLING_EDGE
Definition gpio.h:49
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:14
T clamp_at_most(T value, U max)
Definition helpers.h:2205
const void size_t len
Definition hal.h:64
void HOT delay(uint32_t ms)
Definition hal.cpp:85
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6