ESPHome  2024.5.0
gt911_touchscreen.cpp
Go to the documentation of this file.
1 #include "gt911_touchscreen.h"
2 
3 #include "esphome/core/helpers.h"
4 #include "esphome/core/log.h"
5 
6 namespace esphome {
7 namespace gt911 {
8 
9 static const char *const TAG = "gt911.touchscreen";
10 
11 static const uint8_t GET_TOUCH_STATE[2] = {0x81, 0x4E};
12 static const uint8_t CLEAR_TOUCH_STATE[3] = {0x81, 0x4E, 0x00};
13 static const uint8_t GET_TOUCHES[2] = {0x81, 0x4F};
14 static const uint8_t GET_SWITCHES[2] = {0x80, 0x4D};
15 static const uint8_t GET_MAX_VALUES[2] = {0x80, 0x48};
16 static const size_t MAX_TOUCHES = 5; // max number of possible touches reported
17 static const size_t MAX_BUTTONS = 4; // max number of buttons scanned
18 
19 #define ERROR_CHECK(err) \
20  if ((err) != i2c::ERROR_OK) { \
21  ESP_LOGE(TAG, "Failed to communicate!"); \
22  this->status_set_warning(); \
23  return; \
24  }
25 
27  i2c::ErrorCode err;
28  ESP_LOGCONFIG(TAG, "Setting up GT911 Touchscreen...");
29 
30  // check the configuration of the int line.
31  uint8_t data[4];
32  err = this->write(GET_SWITCHES, 2);
33  if (err == i2c::ERROR_OK) {
34  err = this->read(data, 1);
35  if (err == i2c::ERROR_OK) {
36  ESP_LOGD(TAG, "Read from switches: 0x%02X", data[0]);
37  if (this->interrupt_pin_ != nullptr) {
38  // datasheet says NOT to use pullup/down on the int line.
40  this->interrupt_pin_->setup();
43  }
44  }
45  }
46  if (err == i2c::ERROR_OK) {
47  err = this->write(GET_MAX_VALUES, 2);
48  if (err == i2c::ERROR_OK) {
49  err = this->read(data, sizeof(data));
50  if (err == i2c::ERROR_OK) {
51  if (this->x_raw_max_ == this->x_raw_min_) {
52  this->x_raw_max_ = encode_uint16(data[1], data[0]);
53  }
54  if (this->y_raw_max_ == this->y_raw_min_) {
55  this->y_raw_max_ = encode_uint16(data[3], data[2]);
56  }
57  esph_log_d(TAG, "calibration max_x/max_y %d/%d", this->x_raw_max_, this->y_raw_max_);
58  }
59  }
60  }
61  if (err != i2c::ERROR_OK) {
62  ESP_LOGE(TAG, "Failed to communicate!");
63  this->mark_failed();
64  return;
65  }
66 
67  ESP_LOGCONFIG(TAG, "GT911 Touchscreen setup complete");
68 }
69 
71  i2c::ErrorCode err;
72  uint8_t touch_state = 0;
73  uint8_t data[MAX_TOUCHES + 1][8]; // 8 bytes each for each point, plus extra space for the key byte
74 
75  err = this->write(GET_TOUCH_STATE, sizeof(GET_TOUCH_STATE), false);
76  ERROR_CHECK(err);
77  err = this->read(&touch_state, 1);
78  ERROR_CHECK(err);
79  this->write(CLEAR_TOUCH_STATE, sizeof(CLEAR_TOUCH_STATE));
80  uint8_t num_of_touches = touch_state & 0x07;
81 
82  if ((touch_state & 0x80) == 0 || num_of_touches > MAX_TOUCHES) {
83  this->skip_update_ = true; // skip send touch events, touchscreen is not ready yet.
84  return;
85  }
86 
87  err = this->write(GET_TOUCHES, sizeof(GET_TOUCHES), false);
88  ERROR_CHECK(err);
89  // num_of_touches is guaranteed to be 0..5. Also read the key data
90  err = this->read(data[0], sizeof(data[0]) * num_of_touches + 1);
91  ERROR_CHECK(err);
92 
93  for (uint8_t i = 0; i != num_of_touches; i++) {
94  uint16_t id = data[i][0];
95  uint16_t x = encode_uint16(data[i][2], data[i][1]);
96  uint16_t y = encode_uint16(data[i][4], data[i][3]);
97  this->add_raw_touch_position_(id, x, y);
98  }
99  auto keys = data[num_of_touches][0] & ((1 << MAX_BUTTONS) - 1);
100  if (keys != this->button_state_) {
101  this->button_state_ = keys;
102  for (size_t i = 0; i != MAX_BUTTONS; i++) {
103  for (auto *listener : this->button_listeners_)
104  listener->update_button(i, (keys & (1 << i)) != 0);
105  }
106  }
107 }
108 
110  ESP_LOGCONFIG(TAG, "GT911 Touchscreen:");
111  LOG_I2C_DEVICE(this);
112  LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
113 }
114 
115 } // namespace gt911
116 } // namespace esphome
uint16_t x
Definition: tt21100.cpp:17
ErrorCode read(uint8_t *data, size_t len)
reads an array of bytes from the device using an I2CBus
Definition: i2c.h:160
virtual void pin_mode(gpio::Flags flags)=0
virtual void setup()=0
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:186
uint16_t y
Definition: tt21100.cpp:18
std::vector< GT911ButtonListener * > button_listeners_
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.
Definition: touchscreen.cpp:12
No error found during execution of method.
Definition: i2c_bus.h:13
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:182
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
void add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw=0)
Definition: touchscreen.cpp:74
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
ErrorCode
Error codes returned by I2CBus and I2CDevice methods.
Definition: i2c_bus.h:11