ESPHome 2025.9.0-dev
Loading...
Searching...
No Matches
gt911_touchscreen.cpp
Go to the documentation of this file.
1#include "gt911_touchscreen.h"
2
4#include "esphome/core/log.h"
5
6namespace esphome {
7namespace gt911 {
8
9static const char *const TAG = "gt911.touchscreen";
10
11static const uint8_t PRIMARY_ADDRESS = 0x5D; // default I2C address for GT911
12static const uint8_t SECONDARY_ADDRESS = 0x14; // secondary I2C address for GT911
13static const uint8_t GET_TOUCH_STATE[2] = {0x81, 0x4E};
14static const uint8_t CLEAR_TOUCH_STATE[3] = {0x81, 0x4E, 0x00};
15static const uint8_t GET_TOUCHES[2] = {0x81, 0x4F};
16static const uint8_t GET_SWITCHES[2] = {0x80, 0x4D};
17static const uint8_t GET_MAX_VALUES[2] = {0x80, 0x48};
18static const size_t MAX_TOUCHES = 5; // max number of possible touches reported
19static const size_t MAX_BUTTONS = 4; // max number of buttons scanned
20
21#define ERROR_CHECK(err) \
22 if ((err) != i2c::ERROR_OK) { \
23 this->status_set_warning(ESP_LOG_MSG_COMM_FAIL); \
24 return; \
25 }
26
28 if (this->reset_pin_ != nullptr) {
29 this->reset_pin_->setup();
30 this->reset_pin_->digital_write(false);
31 if (this->interrupt_pin_ != nullptr) {
32 // temporarily set the interrupt pin to output to control address selection
34 this->interrupt_pin_->digital_write(false);
35 }
36 delay(2);
37 this->reset_pin_->digital_write(true); // wait 50ms after reset
38 this->set_timeout(50, [this] { this->setup_internal_(); });
39 return;
40 }
41 this->setup_internal_();
42}
43
45 if (this->interrupt_pin_ != nullptr) {
46 // set pre-configured input mode
47 this->interrupt_pin_->setup();
48 }
49
50 // check the configuration of the int line.
51 uint8_t data[4];
52 i2c::ErrorCode err = this->write(GET_SWITCHES, sizeof(GET_SWITCHES));
53 if (err != i2c::ERROR_OK && this->address_ == PRIMARY_ADDRESS) {
54 this->address_ = SECONDARY_ADDRESS;
55 err = this->write(GET_SWITCHES, sizeof(GET_SWITCHES));
56 }
57 if (err == i2c::ERROR_OK) {
58 err = this->read(data, 1);
59 if (err == i2c::ERROR_OK) {
60 ESP_LOGD(TAG, "Switches ADDR: 0x%02X DATA: 0x%02X", this->address_, data[0]);
61 if (this->interrupt_pin_ != nullptr) {
64 }
65 }
66 }
67 if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) {
68 // no calibration? Attempt to read the max values from the touchscreen.
69 if (err == i2c::ERROR_OK) {
70 err = this->write(GET_MAX_VALUES, sizeof(GET_MAX_VALUES));
71 if (err == i2c::ERROR_OK) {
72 err = this->read(data, sizeof(data));
73 if (err == i2c::ERROR_OK) {
74 this->x_raw_max_ = encode_uint16(data[1], data[0]);
75 this->y_raw_max_ = encode_uint16(data[3], data[2]);
76 if (this->swap_x_y_)
77 std::swap(this->x_raw_max_, this->y_raw_max_);
78 }
79 }
80 }
81 if (err != i2c::ERROR_OK) {
82 this->mark_failed("Calibration error");
83 return;
84 }
85 }
86
87 if (err != i2c::ERROR_OK) {
88 this->mark_failed(ESP_LOG_MSG_COMM_FAIL);
89 return;
90 }
91 this->setup_done_ = true;
92}
93
95 this->skip_update_ = true; // skip send touch events by default, set to false after successful error checks
96 if (!this->setup_done_) {
97 return;
98 }
99
100 i2c::ErrorCode err;
101 uint8_t touch_state = 0;
102 uint8_t data[MAX_TOUCHES + 1][8]; // 8 bytes each for each point, plus extra space for the key byte
103
104 err = this->write(GET_TOUCH_STATE, sizeof(GET_TOUCH_STATE));
105 ERROR_CHECK(err);
106 err = this->read(&touch_state, 1);
107 ERROR_CHECK(err);
108 this->write(CLEAR_TOUCH_STATE, sizeof(CLEAR_TOUCH_STATE));
109 uint8_t num_of_touches = touch_state & 0x07;
110
111 if ((touch_state & 0x80) == 0 || num_of_touches > MAX_TOUCHES) {
112 return;
113 }
114
115 err = this->write(GET_TOUCHES, sizeof(GET_TOUCHES));
116 ERROR_CHECK(err);
117 // num_of_touches is guaranteed to be 0..5. Also read the key data
118 err = this->read(data[0], sizeof(data[0]) * num_of_touches + 1);
119 ERROR_CHECK(err);
120
121 this->skip_update_ = false; // All error checks passed, send touch events
122 for (uint8_t i = 0; i != num_of_touches; i++) {
123 uint16_t id = data[i][0];
124 uint16_t x = encode_uint16(data[i][2], data[i][1]);
125 uint16_t y = encode_uint16(data[i][4], data[i][3]);
126 this->add_raw_touch_position_(id, x, y);
127 }
128 auto keys = data[num_of_touches][0] & ((1 << MAX_BUTTONS) - 1);
129 if (keys != this->button_state_) {
130 this->button_state_ = keys;
131 for (size_t i = 0; i != MAX_BUTTONS; i++) {
132 for (auto *listener : this->button_listeners_)
133 listener->update_button(i, (keys & (1 << i)) != 0);
134 }
135 }
136}
137
139 ESP_LOGCONFIG(TAG, "GT911 Touchscreen:");
140 LOG_I2C_DEVICE(this);
141 LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
142 LOG_PIN(" Reset Pin: ", this->reset_pin_);
143}
144
145} // namespace gt911
146} // namespace esphome
virtual void mark_failed()
Mark this component as failed.
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
virtual void pin_mode(gpio::Flags flags)=0
virtual void setup()=0
virtual void digital_write(bool value)=0
void setup_internal_()
Perform the internal setup routine for the GT911 touchscreen.
void setup() override
Initialize the GT911 touchscreen.
std::vector< GT911ButtonListener * > button_listeners_
bool setup_done_
True if the touchscreen setup has completed successfully.
ErrorCode write(const uint8_t *data, size_t len, bool stop=true)
writes an array of bytes to a device using an I2CBus
Definition i2c.h:190
uint8_t address_
store the address of the device on the bus
Definition i2c.h:273
ErrorCode read(uint8_t *data, size_t len)
reads an array of bytes from the device using an I2CBus
Definition i2c.h:164
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)
@ INTERRUPT_FALLING_EDGE
Definition gpio.h:42
@ INTERRUPT_RISING_EDGE
Definition gpio.h:41
@ FLAG_OUTPUT
Definition gpio.h:19
ErrorCode
Error codes returned by I2CBus and I2CDevice methods.
Definition i2c_bus.h:11
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:13
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
Definition helpers.h:173
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:29
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6