ESPHome 2026.8.0-dev
Loading...
Searching...
No Matches
cst9220_touchscreen.cpp
Go to the documentation of this file.
3
4#include <cinttypes>
5
6namespace esphome::cst9220 {
7
9 if (this->reset_pin_ != nullptr) {
10 this->reset_pin_->setup();
11 this->reset_pin_->digital_write(true);
12 delay(5);
13 this->reset_pin_->digital_write(false);
14 delay(10);
15 this->reset_pin_->digital_write(true);
16 }
17 // Wait for the controller to leave its bootloader before talking to it.
18 this->set_timeout(30, [this] { this->continue_setup_(); });
19}
20
22 uint8_t buffer[4];
23
24 if (this->interrupt_pin_ != nullptr) {
25 this->interrupt_pin_->setup();
27 }
28
29 // Enter command mode so the configuration registers can be read.
30 if (this->write_register16(REG_CMD_MODE, buffer, 0) != i2c::ERROR_OK) {
31 this->status_set_error(LOG_STR("Failed to enter command mode"));
32 this->mark_failed();
33 return;
34 }
35 delay(10);
36
37 // The firmware check code confirms that valid firmware is loaded.
38 if (this->read_register16(REG_CHECKCODE, buffer, 4) != i2c::ERROR_OK) {
39 this->status_set_error(LOG_STR("Failed to read check code"));
40 this->mark_failed();
41 return;
42 }
43 uint32_t checkcode = encode_uint32(buffer[3], buffer[2], buffer[1], buffer[0]);
44 if ((checkcode & 0xFFFF0000) != 0xCACA0000) {
45 ESP_LOGE(TAG, "Invalid firmware check code: 0x%08" PRIX32, checkcode);
46 this->status_set_error(LOG_STR("Invalid firmware check code"));
47 this->mark_failed();
48 return;
49 }
50
51 // Read the panel resolution unless the user supplied calibration values.
52 if (this->read_register16(REG_RESOLUTION, buffer, 4) == i2c::ERROR_OK) {
53 if (this->x_raw_max_ == this->x_raw_min_)
54 this->x_raw_max_ = encode_uint16(buffer[1], buffer[0]);
55 if (this->y_raw_max_ == this->y_raw_min_)
56 this->y_raw_max_ = encode_uint16(buffer[3], buffer[2]);
57 }
58
59 // Read the chip type and project id and validate the controller.
60 if (this->read_register16(REG_CHIP_INFO, buffer, 4) != i2c::ERROR_OK) {
61 this->status_set_error(LOG_STR("Failed to read chip ID"));
62 this->mark_failed();
63 return;
64 }
65 this->chip_id_ = encode_uint16(buffer[3], buffer[2]);
66 this->project_id_ = encode_uint16(buffer[1], buffer[0]);
67 if (this->chip_id_ != CST9220_CHIP_ID && this->chip_id_ != CST9217_CHIP_ID) {
68 ESP_LOGE(TAG, "Unknown chip ID: 0x%04X", this->chip_id_);
69 this->status_set_error(LOG_STR("Unknown chip ID"));
70 this->mark_failed();
71 return;
72 }
73
74 // Fall back to the display dimensions if the resolution read failed.
75 if (this->x_raw_max_ == this->x_raw_min_)
76 this->x_raw_max_ = this->display_->get_native_width();
77 if (this->y_raw_max_ == this->y_raw_min_)
78 this->y_raw_max_ = this->display_->get_native_height();
79
80 this->setup_complete_ = true;
81}
82
84 if (!this->setup_complete_)
85 return;
86 uint8_t data[CST9220_DATA_LENGTH];
87 // Only an actual I2C failure should skip the update; a successful read with no
88 // touches is a real "all fingers lifted" state that must flow through so the
89 // base class can generate the release event.
90 if (this->read_register16(REG_TOUCH_DATA, data, sizeof(data)) != i2c::ERROR_OK) {
91 this->status_set_warning();
92 this->skip_update_ = true;
93 return;
94 }
96
97 // Acknowledge the report so the controller can prepare the next one.
98 uint8_t ack = TOUCH_ACK;
99 this->write_register16(REG_TOUCH_DATA, &ack, 1);
100
101 // A valid report carries the ACK marker at offset 6; offset 0 holds the first
102 // point and must be neither the ACK marker nor empty. Anything else means no
103 // valid touch data this cycle, which we report as zero touches (not a skip).
104 if (data[0] == TOUCH_ACK || data[0] == 0x00 || data[6] != TOUCH_ACK)
105 return;
106
107 uint8_t num_touches = data[5] & 0x7F;
108 if (num_touches > CST9220_MAX_TOUCHES)
109 num_touches = CST9220_MAX_TOUCHES;
110
111 for (uint8_t i = 0; i < num_touches; i++) {
112 // The first point starts at offset 0; subsequent points are offset by the
113 // two status bytes that follow it.
114 const uint8_t *p = data + i * 5 + (i == 0 ? 0 : 2);
115 uint8_t id = p[0] >> 4;
116 uint8_t event = p[0] & 0x0F;
117 if (event != TOUCH_EVENT_DOWN)
118 continue;
119 // p[3] is shared: high nibble holds the X LSBs, low nibble the Y LSBs.
120 uint16_t x = (p[1] << 4) | (p[3] >> 4);
121 uint16_t y = (p[2] << 4) | (p[3] & 0x0F);
122 ESP_LOGV(TAG, "Read touch %d: %d/%d", id, x, y);
123 this->add_raw_touch_position_(id, x, y);
124 }
125}
126
128 ESP_LOGCONFIG(TAG,
129 "CST9220 Touchscreen:\n"
130 " Chip ID: 0x%04X\n"
131 " Project ID: 0x%04X\n"
132 " X Raw Min: %d, X Raw Max: %d\n"
133 " Y Raw Min: %d, Y Raw Max: %d",
134 this->chip_id_, this->project_id_, this->x_raw_min_, this->x_raw_max_, this->y_raw_min_,
135 this->y_raw_max_);
136 LOG_I2C_DEVICE(this);
137 LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
138 LOG_PIN(" Reset Pin: ", this->reset_pin_);
139}
140
141} // namespace esphome::cst9220
void mark_failed()
Mark this component as failed.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
Definition component.cpp:96
void status_clear_warning()
Definition component.h:289
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_register16(uint16_t a_register, const uint8_t *data, size_t len) const
write an array of bytes to a specific register in the I²C device
Definition i2c.cpp:43
ErrorCode read_register16(uint16_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:29
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:49
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:14
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
Definition helpers.h:881
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:873
void HOT delay(uint32_t ms)
Definition hal.cpp:85
static void uint32_t
uint8_t ack
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6