Add touch_probe and touch_reset actions to the Elecrow for a diagnosis over the API (0.2.97, firmware 0.2.83)
CI / checks (push) Has been cancelled
CI / firmware (add-on) (push) Has been cancelled
CI / firmware (min_version) (push) Has been cancelled

This commit is contained in:
Xandrossian
2026-09-21 14:03:05 -07:00
parent 4ec8c7a935
commit 6910f30d4c
8 changed files with 90 additions and 20 deletions
+48 -12
View File
@@ -7,6 +7,10 @@
// (setup priority 700, between the bus's 1000 and the driver's 600), so the driver finds it at 0x5D. A V2.0 board
// has no expander: the writes fail, the log says so, and the GT911 boots by its pull-up as before.
//
// probe() and reset() are the touch_probe and touch_reset actions of the board file (firmware 0.2.83): the expander's
// registers and whether a GT911 answers at 0x5D or 0x14 (its product id, "911"), and the same sequence with values of
// one's own, for a diagnosis over the API without a new build.
//
// Only the Elecrow's board file builds this (`smart_display: elecrow_touch_reset:`, which sets the flag), so the
// header adds nothing to a CYD, which has no I2C at all.
#if defined(ESP_SCREENS_ELECROW_TOUCH_RESET) && ESP_SCREENS_ELECROW_TOUCH_RESET
@@ -19,22 +23,54 @@ namespace elecrow {
class TouchReset : public esphome::Component, public esphome::i2c::I2CDevice {
public:
float get_setup_priority() const override { return 700.0f; }
void setup() override {
auto write = [this](uint8_t reg, uint8_t value) {
const uint8_t data[2] = {reg, value};
return this->write(data, sizeof(data)) == esphome::i2c::ERROR_OK;
};
bool ok = write(0x03, 0x00); // configuration: every pin an output
ok = write(0x01, 0x00) && ok; // output: reset low, interrupt low (address 0x5D), the rest low
esphome::delay(20);
ok = write(0x01, 0x01) && ok; // reset released, the interrupt line still low
esphome::delay(100);
ok = write(0x03, 0x02) && ok; // the interrupt line an input again; the GT911 drives it from here
void setup() override { this->reset(0x00, 0x00, 0x01, 20, 100, 0x02); }
// Elecrow's sequence with its values: `config` the expander's configuration register during the reset (0 = every
// pin an output), `low` its output register while the reset is held, `high` after the release, `final_config`
// afterwards; then the probe.
void reset(int config, int low, int high, int hold_ms, int wait_ms, int final_config) {
bool ok = this->write_reg_(0x03, config);
ok = this->write_reg_(0x01, low) && ok;
esphome::delay(hold_ms);
ok = this->write_reg_(0x01, high) && ok;
esphome::delay(wait_ms);
ok = this->write_reg_(0x03, final_config) && ok;
if (ok) {
ESP_LOGI("touch", "GT911 reset through the PCA9557 at 0x%02X", this->address_);
ESP_LOGI("touch", "GT911 reset through the PCA9557 at 0x%02X: config 0x%02X, out 0x%02X -> 0x%02X, %d + %d ms, config 0x%02X",
this->address_, config, low, high, hold_ms, wait_ms, final_config);
} else {
ESP_LOGW("touch", "No PCA9557 at 0x%02X: the GT911 was not reset (a V2.0 board boots it by its pull-up)", this->address_);
}
this->probe();
}
// The expander's four registers and the GT911's answer at both addresses.
void probe() {
uint8_t regs[4] = {0, 0, 0, 0};
bool ok = true;
for (uint8_t reg = 0; reg < 4; ++reg) {
ok = this->write(&reg, 1) == esphome::i2c::ERROR_OK && this->read(&regs[reg], 1) == esphome::i2c::ERROR_OK && ok;
}
ESP_LOGI("touch", "PCA9557 at 0x%02X: %s input 0x%02X output 0x%02X polarity 0x%02X config 0x%02X", this->address_,
ok ? "answers," : "no answer;", regs[0], regs[1], regs[2], regs[3]);
for (uint8_t address : {0x5D, 0x14}) {
esphome::i2c::I2CDevice chip;
chip.set_i2c_bus(this->bus_);
chip.set_i2c_address(address);
const uint8_t product_id[2] = {0x81, 0x40};
uint8_t id[4] = {0, 0, 0, 0};
const bool written = chip.write(product_id, sizeof(product_id)) == esphome::i2c::ERROR_OK;
const bool read = written && chip.read(id, sizeof(id)) == esphome::i2c::ERROR_OK;
ESP_LOGI("touch", "GT911 at 0x%02X: %s%s product id %02X %02X %02X %02X (\"%c%c%c\")", address,
written ? "write ok, " : "no write ack, ", read ? "read ok," : "no read,", id[0], id[1], id[2], id[3],
id[0] >= 32 && id[0] < 127 ? id[0] : '.', id[1] >= 32 && id[1] < 127 ? id[1] : '.', id[2] >= 32 && id[2] < 127 ? id[2] : '.');
}
}
protected:
bool write_reg_(uint8_t reg, int value) {
const uint8_t data[2] = {reg, static_cast<uint8_t>(value)};
return this->write(data, sizeof(data)) == esphome::i2c::ERROR_OK;
}
};
} // namespace elecrow