MCP23XXXGPIOPin::setup() calls pin_interrupt_mode(pin, NO_INTERRUPT)
after pin_mode() already auto-enabled CHANGE, undoing the auto-enable.
Skip the explicit pin_interrupt_mode call when interrupt_pin is
configured and the user didn't override the default.
- MCP23017/MCP23S17: Enable MIRROR bit in IOCON when interrupt_pin is
configured so INTA and INTB are ORed together, allowing a single
interrupt wire to catch changes on all 16 pins
- All MCP23xxx variants: Log interrupt_pin in dump_config for debugging
- PI4IOE5V6408: Read interrupt status register during setup to clear
any latched state that could hold INT line low
- MCP23XXXBase: Move setup_interrupt_pin_() to protected visibility
- MCP23x08/x17: auto-enable CHANGE interrupt mode in pin_mode() when
interrupt_pin is configured, so users don't need to manually set
interrupt: CHANGE on every pin
- PI4IOE5V6408: write interrupt enable mask for input pins in
write_gpio_modes_() when interrupt_pin is configured
Extend interrupt_pin support to MCP23008, MCP23017, MCP23S08, MCP23S17,
and PI4IOE5V6408 GPIO expander components. Same approach as PCF8574/PCA9554:
when configured, the component disables its loop and only wakes on interrupt,
and the cache stays valid between interrupts so binary sensors return from
cache instead of doing I2C/SPI reads every loop iteration.
For MCP23xxx, the interrupt_pin config and C++ logic lives in the shared
MCP23XXXBase template class, so all four variants (I2C 8/16-pin, SPI
8/16-pin) inherit it automatically.
Inspired by jesserockz's work in #11959 which proposed a more comprehensive
interrupt-driven approach with per-pin interrupt status register reading.
This implementation takes a simpler path by leveraging the existing
CachedGpioExpander cache invalidation mechanism.
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.
When interrupt_driven_ is set, digital_read() no longer self-invalidates
each pin's cache entry. The cache stays valid until reset_pin_cache_()
is called from loop() when an interrupt fires. This eliminates I2C reads
on every binary sensor loop iteration — only reading when pins actually
change.
Add interrupt_pin config option to PCF8574 and PCA9554 GPIO expander
components. When configured, the component disables its loop and only
wakes on interrupt, eliminating continuous I2C polling when no pins
have changed state.
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick+github@koston.org>
Co-authored-by: J. Nick Koston <nick@koston.org>