[gt911] Support for interrupt signal via IO Expander (#14358)

This commit is contained in:
Raymond Richmond
2026-02-28 00:26:06 -07:00
committed by GitHub
parent 49cc389bf0
commit 6c0998f220
3 changed files with 27 additions and 10 deletions

View File

@@ -16,7 +16,7 @@ GT911Touchscreen = gt911_ns.class_(
CONFIG_SCHEMA = touchscreen.TOUCHSCREEN_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(GT911Touchscreen),
cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
cv.Optional(CONF_INTERRUPT_PIN): pins.gpio_output_pin_schema,
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
}
).extend(i2c.i2c_device_schema(0x5D))

View File

@@ -2,6 +2,7 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/gpio.h"
namespace esphome {
namespace gt911 {
@@ -26,15 +27,17 @@ static const size_t MAX_BUTTONS = 4; // max number of buttons scanned
void GT911Touchscreen::setup() {
if (this->reset_pin_ != nullptr) {
// temporarily set the interrupt pin to output to control address selection
this->reset_pin_->setup();
this->reset_pin_->digital_write(false);
if (this->interrupt_pin_ != nullptr) {
// temporarily set the interrupt pin to output to control address selection
this->interrupt_pin_->setup();
this->interrupt_pin_->pin_mode(gpio::FLAG_OUTPUT);
this->interrupt_pin_->digital_write(false);
}
delay(2);
this->reset_pin_->digital_write(true); // wait at least T3+T4 ms as per the datasheet
this->reset_pin_->digital_write(true);
// wait at least T3+T4 ms as per the datasheet
this->set_timeout(5 + 50 + 1, [this] { this->setup_internal_(); });
return;
}
@@ -43,11 +46,10 @@ void GT911Touchscreen::setup() {
void GT911Touchscreen::setup_internal_() {
if (this->interrupt_pin_ != nullptr) {
// set pre-configured input mode
this->interrupt_pin_->setup();
if (this->interrupt_pin_->is_internal())
this->interrupt_pin_->pin_mode(gpio::FLAG_INPUT);
}
// check the configuration of the int line.
uint8_t data[4];
i2c::ErrorCode err = this->write(GET_SWITCHES, sizeof(GET_SWITCHES));
if (err != i2c::ERROR_OK && this->address_ == PRIMARY_ADDRESS) {
@@ -58,12 +60,25 @@ void GT911Touchscreen::setup_internal_() {
err = this->read(data, 1);
if (err == i2c::ERROR_OK) {
ESP_LOGD(TAG, "Switches ADDR: 0x%02X DATA: 0x%02X", this->address_, data[0]);
// data[0] & 1 == 1 => controller uses falling edge => active-low
// data[0] & 1 == 0 => controller uses rising edge => active-high
bool active_high = !(data[0] & 1);
if (this->interrupt_pin_ != nullptr) {
this->attach_interrupt_(this->interrupt_pin_,
(data[0] & 1) ? gpio::INTERRUPT_FALLING_EDGE : gpio::INTERRUPT_RISING_EDGE);
if (this->interrupt_pin_->is_internal()) {
// Direct MCU pin: attach a hardware interrupt, no polling needed.
this->attach_interrupt_(static_cast<InternalGPIOPin *>(this->interrupt_pin_),
active_high ? gpio::INTERRUPT_RISING_EDGE : gpio::INTERRUPT_FALLING_EDGE);
ESP_LOGD(TAG, "Interrupt pin: hardware interrupt, active %s", active_high ? "HIGH" : "LOW");
} else {
// IO expander pin: leave as output for configuration only.
ESP_LOGD(TAG, "Interrupt pin: IO expander polling mode, active %s", active_high ? "HIGH" : "LOW");
}
}
}
}
if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) {
// no calibration? Attempt to read the max values from the touchscreen.
if (err == i2c::ERROR_OK) {

View File

@@ -30,7 +30,9 @@ class GT911Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
void dump_config() override;
bool can_proceed() override { return this->setup_done_; }
void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
/// Set a interrupt pin (supports hardware interrupts or expander connected).
void set_interrupt_pin(GPIOPin *pin) { this->interrupt_pin_ = pin; }
void set_reset_pin(GPIOPin *pin) { this->reset_pin_ = pin; }
void register_button_listener(GT911ButtonListener *listener) { this->button_listeners_.push_back(listener); }
@@ -49,7 +51,7 @@ class GT911Touchscreen : public touchscreen::Touchscreen, public i2c::I2CDevice
/// @brief True if the touchscreen setup has completed successfully.
bool setup_done_{false};
InternalGPIOPin *interrupt_pin_{nullptr};
GPIOPin *interrupt_pin_{nullptr};
GPIOPin *reset_pin_{nullptr};
std::vector<GT911ButtonListener *> button_listeners_;
uint8_t button_state_{0xFF}; // last button state. Initial FF guarantees first update.