From a2120953b9c07199d95785fe2370746a2d1345a3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 4 Apr 2026 08:43:16 -1000 Subject: [PATCH] [gpio_expander] Rename interrupt_driven_ to invalidate_on_read_ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The base class doesn't need to know about interrupts — it just controls whether digital_read() self-invalidates cache entries. Rename the flag and invert the polarity for clarity. --- .../components/gpio_expander/cached_gpio.h | 24 ++++++++++--------- esphome/components/pca9554/pca9554.cpp | 4 ++-- esphome/components/pcf8574/pcf8574.cpp | 4 ++-- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/esphome/components/gpio_expander/cached_gpio.h b/esphome/components/gpio_expander/cached_gpio.h index 522444e9c9f..dbdc0753fd4 100644 --- a/esphome/components/gpio_expander/cached_gpio.h +++ b/esphome/components/gpio_expander/cached_gpio.h @@ -29,10 +29,10 @@ template 256 class CachedGpioExpander { public: /// @brief Read the state of the given pin. - /// In polling mode (default), each read invalidates the pin's cache entry so - /// the next read of the same pin triggers a fresh hardware read. - /// In interrupt mode, the cache stays valid until explicitly invalidated by - /// reset_pin_cache_() (called from loop() when an interrupt fires). + /// @brief Read the state of the given pin. + /// By default, each read invalidates the pin's cache entry so the next read + /// of the same pin triggers a fresh hardware read. When invalidate_on_read + /// is disabled, the cache stays valid until explicitly cleared via reset_pin_cache_(). /// @param pin Pin number to read /// @return Pin state bool digital_read(P pin) { @@ -40,8 +40,8 @@ class CachedGpioExpander { const T pin_mask = (1 << (pin % BANK_SIZE)); // Check if specific pin cache is valid if (this->read_cache_valid_[bank] & pin_mask) { - if (!this->interrupt_driven_) { - // Polling mode: invalidate pin so next read triggers hardware read + if (this->invalidate_on_read_) { + // Invalidate pin so next read triggers hardware read this->read_cache_valid_[bank] &= ~pin_mask; } } else { @@ -49,8 +49,8 @@ class CachedGpioExpander { if (!this->digital_read_hw(pin)) return false; // Mark bank cache as valid except the pin that is being returned now - // (in interrupt mode, mark all pins including this one as valid) - this->read_cache_valid_[bank] = std::numeric_limits::max() & ~(this->interrupt_driven_ ? 0 : pin_mask); + // (when not invalidating on read, mark all pins including this one as valid) + this->read_cache_valid_[bank] = std::numeric_limits::max() & ~(this->invalidate_on_read_ ? pin_mask : 0); } return this->digital_read_cache(pin); } @@ -78,8 +78,10 @@ class CachedGpioExpander { /// @brief Invalidate cache. This function should be called in component loop(). void reset_pin_cache_() { memset(this->read_cache_valid_, 0x00, CACHE_SIZE_BYTES); } - /// @brief Enable interrupt-driven mode. Cache stays valid until reset_pin_cache_() is called. - void set_interrupt_driven_(bool interrupt_driven) { this->interrupt_driven_ = interrupt_driven; } + /// @brief Control whether digital_read() invalidates the pin's cache entry after reading. + /// When enabled (default), each read self-invalidates so the next read triggers a hardware read. + /// When disabled, cache stays valid until reset_pin_cache_() is explicitly called. + void set_invalidate_on_read_(bool invalidate) { this->invalidate_on_read_ = invalidate; } static constexpr uint16_t BITS_PER_BYTE = 8; static constexpr uint16_t BANK_SIZE = sizeof(T) * BITS_PER_BYTE; @@ -87,7 +89,7 @@ class CachedGpioExpander { static constexpr size_t CACHE_SIZE_BYTES = BANKS * sizeof(T); T read_cache_valid_[BANKS]{0}; - bool interrupt_driven_{false}; + bool invalidate_on_read_{true}; }; } // namespace esphome::gpio_expander diff --git a/esphome/components/pca9554/pca9554.cpp b/esphome/components/pca9554/pca9554.cpp index befb19d9948..9b300eaac28 100644 --- a/esphome/components/pca9554/pca9554.cpp +++ b/esphome/components/pca9554/pca9554.cpp @@ -38,8 +38,8 @@ void PCA9554Component::setup() { if (this->interrupt_pin_ != nullptr) { this->interrupt_pin_->setup(); this->interrupt_pin_->attach_interrupt(&PCA9554Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); - // Cache stays valid until interrupt fires and loop() invalidates it - this->set_interrupt_driven_(true); + // Don't invalidate cache on read — only invalidate when interrupt fires + this->set_invalidate_on_read_(false); // With interrupt pin, only run loop when interrupt fires this->disable_loop(); } diff --git a/esphome/components/pcf8574/pcf8574.cpp b/esphome/components/pcf8574/pcf8574.cpp index 4d078c1620c..1eeef663b0d 100644 --- a/esphome/components/pcf8574/pcf8574.cpp +++ b/esphome/components/pcf8574/pcf8574.cpp @@ -19,8 +19,8 @@ void PCF8574Component::setup() { if (this->interrupt_pin_ != nullptr) { this->interrupt_pin_->setup(); this->interrupt_pin_->attach_interrupt(&PCF8574Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE); - // Cache stays valid until interrupt fires and loop() invalidates it - this->set_interrupt_driven_(true); + // Don't invalidate cache on read — only invalidate when interrupt fires + this->set_invalidate_on_read_(false); // With interrupt pin, only run loop when interrupt fires this->disable_loop(); }