15static constexpr uint16_t REG_CLEAR_INTERRUPT = 0x0002;
16static constexpr uint16_t REG_CPU_START = 0x0004;
17static constexpr uint16_t REG_STATUS = 0x0020;
18static constexpr uint16_t REG_VERSION = 0x0026;
19static constexpr uint16_t REG_TOUCH_START = 0x0046;
20static constexpr uint16_t REG_POINT_MODE = 0x0050;
21static constexpr uint16_t REG_HDP_STATUS = 0x02FC;
22static constexpr uint16_t REG_HDP = 0x0300;
25static constexpr uint8_t STATUS_POINT = 0x01;
26static constexpr uint8_t STATUS_GESTURE = 0x02;
27static constexpr uint8_t STATUS_AUX = 0x08;
29static constexpr uint8_t STATUS_BIOS = 0x40;
30static constexpr uint8_t STATUS_CPU = 0x20;
31static constexpr uint8_t STATUS_RUNNING = 0x08;
33static constexpr uint8_t HDP_STATUS_DONE = 0x82;
34static constexpr uint8_t HDP_STATUS_MORE = 0x00;
36static constexpr uint8_t MAX_CONTACT_ID = 0x0A;
37static constexpr uint8_t GESTURE_REPORT_ID = 0xF6;
38static constexpr size_t REPORT_HEADER_LENGTH = 4;
39static constexpr size_t CONTACT_LENGTH = 6;
40static constexpr size_t MAX_REPORT_LENGTH = REPORT_HEADER_LENGTH + 10 * CONTACT_LENGTH;
41static constexpr uint8_t MAX_DRAIN_READS = 8;
43static constexpr uint32_t RESET_PULSE_WIDTH =
45static constexpr uint32_t RESET_DELAY = 20;
48 const uint8_t command[] = {
static_cast<uint8_t
>(
reg),
static_cast<uint8_t
>(
reg >> 8u)};
57 const uint8_t command[]{
58 static_cast<uint8_t
>(
reg),
59 static_cast<uint8_t
>(
reg >> 8u),
60 static_cast<uint8_t
>(value),
61 static_cast<uint8_t
>(value >> 8u),
87 if (!this->
read_register_(REG_VERSION, version,
sizeof(version))) {
88 this->
mark_failed(LOG_STR(
"Failed to read firmware version"));
91 ESP_LOGD(TAG,
"Firmware version: 0x%04X",
encode_uint16(version[5], version[4]));
101 for (uint8_t attempt = 0; attempt != MAX_DRAIN_READS; attempt++) {
105 if (
status[5] == HDP_STATUS_DONE)
110 uint8_t remaining[MAX_REPORT_LENGTH];
114 ESP_LOGW(TAG,
"Invalid or unfinished report");
126 const uint8_t status_low =
status[0];
127 const uint8_t status_high =
status[1];
130 if (status_high & STATUS_BIOS) {
135 if (status_high & STATUS_CPU) {
141 if ((status_high & STATUS_RUNNING) &&
length == 0) {
149 if (!(status_low & (STATUS_POINT | STATUS_GESTURE))) {
150 if ((status_high & STATUS_RUNNING) && (status_low & STATUS_AUX) && !this->
clear_interrupt_()) {
158 (
length - REPORT_HEADER_LENGTH) % CONTACT_LENGTH != 0) {
159 ESP_LOGW(TAG,
"Invalid report length: %u",
length);
164 uint8_t report[MAX_REPORT_LENGTH];
170 if (!(status_low & STATUS_POINT) ||
171 (
length > REPORT_HEADER_LENGTH && report[REPORT_HEADER_LENGTH] == GESTURE_REPORT_ID)) {
176 for (
size_t offset = REPORT_HEADER_LENGTH; offset <
length; offset += CONTACT_LENGTH) {
177 if (report[offset] > MAX_CONTACT_ID) {
182 for (
size_t offset = REPORT_HEADER_LENGTH; offset <
length; offset += CONTACT_LENGTH) {
183 const uint8_t *contact = report + offset;
187 const uint16_t
x = ((contact[3] & 0xF0u) << 4u) | contact[1];
188 const uint16_t
y = ((contact[3] & 0x0Fu) << 8u) | contact[2];
202 "SPD2010 Touchscreen:\n"
203 " Raw X range: %d-%d\n"
204 " Raw Y range: %d-%d",
206 LOG_I2C_DEVICE(
this);
void mark_failed()
Mark this component as failed.
void status_set_warning()
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
void status_clear_warning()
virtual void digital_write(bool value)=0
int get_native_width()
Get the native (original) width of the display in pixels.
int get_native_height()
Get the native (original) height of the display in pixels.
ErrorCode write(const uint8_t *data, size_t len) const
writes an array of bytes to a device using an I2CBus
ErrorCode read(uint8_t *data, size_t len) const
reads an array of bytes from the device using an I2CBus
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
bool read_register_(uint16_t reg, uint8_t *data, size_t length) const
InternalGPIOPin * interrupt_pin_
void update_touches() override
void dump_config() override
bool clear_interrupt_() const
bool write_command_(uint16_t reg, uint16_t value) const
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.
display::Display * display_
void add_raw_touch_position_(uint8_t id, int16_t x_raw, int16_t y_raw, int16_t z_raw=0)
@ ERROR_OK
No error found during execution of method.
ESPHOME_LOG_TAG(TAG, "spd2010.touchscreen")
void delay_microseconds_safe(uint32_t us)
Delay for the given amount of microseconds, possibly yielding to other processes during the wait.
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.