1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-10 07:12:21 +01:00

Merge branch 'pca9554_loop_churn_fix' into integration

This commit is contained in:
J. Nick Koston
2025-09-04 13:05:04 -05:00
3 changed files with 21 additions and 17 deletions

View File

@@ -12,6 +12,7 @@ from esphome.const import (
) )
CODEOWNERS = ["@hwstar", "@clydebarrow", "@bdraco"] CODEOWNERS = ["@hwstar", "@clydebarrow", "@bdraco"]
AUTO_LOAD = ["gpio_expander"]
DEPENDENCIES = ["i2c"] DEPENDENCIES = ["i2c"]
MULTI_CONF = True MULTI_CONF = True
CONF_PIN_COUNT = "pin_count" CONF_PIN_COUNT = "pin_count"

View File

@@ -38,8 +38,8 @@ void PCA9554Component::setup() {
void PCA9554Component::loop() { void PCA9554Component::loop() {
// Invalidate the cache at the start of each loop. // Invalidate the cache at the start of each loop.
// The actual read will happen on demand in digital_read() // The actual read will happen on demand when digital_read() is called
this->cache_valid_ = false; this->reset_pin_cache_();
} }
void PCA9554Component::dump_config() { void PCA9554Component::dump_config() {
@@ -53,15 +53,17 @@ void PCA9554Component::dump_config() {
} }
} }
bool PCA9554Component::digital_read(uint8_t pin) { bool PCA9554Component::digital_read_hw(uint16_t pin) {
// Read the inputs once per loop on demand and cache the result // Read all pins from hardware into input_mask_
if (!this->cache_valid_ && this->read_inputs_()) { return this->read_inputs_(); // Return true if I2C read succeeded, false on error
this->cache_valid_ = true; }
}
bool PCA9554Component::digital_read_cache(uint16_t pin) {
// Return the cached pin state from input_mask_
return this->input_mask_ & (1 << pin); return this->input_mask_ & (1 << pin);
} }
void PCA9554Component::digital_write(uint8_t pin, bool value) { void PCA9554Component::digital_write_hw(uint16_t pin, bool value) {
if (value) { if (value) {
this->output_mask_ |= (1 << pin); this->output_mask_ |= (1 << pin);
} else { } else {

View File

@@ -3,22 +3,21 @@
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/core/hal.h" #include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h" #include "esphome/components/i2c/i2c.h"
#include "esphome/components/gpio_expander/cached_gpio.h"
namespace esphome { namespace esphome {
namespace pca9554 { namespace pca9554 {
class PCA9554Component : public Component, public i2c::I2CDevice { class PCA9554Component : public Component,
public i2c::I2CDevice,
public gpio_expander::CachedGpioExpander<uint16_t, 16> {
public: public:
PCA9554Component() = default; PCA9554Component() = default;
/// Check i2c availability and setup masks /// Check i2c availability and setup masks
void setup() override; void setup() override;
/// Poll for input changes periodically /// Invalidate cache at start of each loop
void loop() override; void loop() override;
/// Helper function to read the value of a pin.
bool digital_read(uint8_t pin);
/// Helper function to write the value of a pin.
void digital_write(uint8_t pin, bool value);
/// Helper function to set the pin mode of a pin. /// Helper function to set the pin mode of a pin.
void pin_mode(uint8_t pin, gpio::Flags flags); void pin_mode(uint8_t pin, gpio::Flags flags);
@@ -32,9 +31,13 @@ class PCA9554Component : public Component, public i2c::I2CDevice {
protected: protected:
bool read_inputs_(); bool read_inputs_();
bool write_register_(uint8_t reg, uint16_t value); bool write_register_(uint8_t reg, uint16_t value);
// Virtual methods from CachedGpioExpander
bool digital_read_hw(uint16_t pin) override;
bool digital_read_cache(uint16_t pin) override;
void digital_write_hw(uint16_t pin, bool value) override;
/// number of bits the expander has /// number of bits the expander has
size_t pin_count_{8}; size_t pin_count_{8};
/// width of registers /// width of registers
@@ -45,8 +48,6 @@ class PCA9554Component : public Component, public i2c::I2CDevice {
uint16_t output_mask_{0x00}; uint16_t output_mask_{0x00};
/// The state of the actual input pin states - 1 means HIGH, 0 means LOW /// The state of the actual input pin states - 1 means HIGH, 0 means LOW
uint16_t input_mask_{0x00}; uint16_t input_mask_{0x00};
/// Cache validity flag - true if we've read inputs this loop cycle
bool cache_valid_{false};
/// Storage for last I2C error seen /// Storage for last I2C error seen
esphome::i2c::ErrorCode last_error_; esphome::i2c::ErrorCode last_error_;
}; };