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

[mcp23016] Migrate to CachedGpioExpander to reduce I2C bus usage (#10581)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
J. Nick Koston
2025-09-07 18:26:49 -05:00
committed by GitHub
parent 6e2bcabbc9
commit 0ff08bbc09
3 changed files with 31 additions and 9 deletions

View File

@@ -11,6 +11,7 @@ from esphome.const import (
CONF_OUTPUT, CONF_OUTPUT,
) )
AUTO_LOAD = ["gpio_expander"]
DEPENDENCIES = ["i2c"] DEPENDENCIES = ["i2c"]
MULTI_CONF = True MULTI_CONF = True

View File

@@ -22,14 +22,29 @@ void MCP23016::setup() {
this->write_reg_(MCP23016_IODIR0, 0xFF); this->write_reg_(MCP23016_IODIR0, 0xFF);
this->write_reg_(MCP23016_IODIR1, 0xFF); this->write_reg_(MCP23016_IODIR1, 0xFF);
} }
bool MCP23016::digital_read(uint8_t pin) {
uint8_t bit = pin % 8; void MCP23016::loop() {
// Invalidate cache at the start of each loop
this->reset_pin_cache_();
}
bool MCP23016::digital_read_hw(uint8_t pin) {
uint8_t reg_addr = pin < 8 ? MCP23016_GP0 : MCP23016_GP1; uint8_t reg_addr = pin < 8 ? MCP23016_GP0 : MCP23016_GP1;
uint8_t value = 0; uint8_t value = 0;
this->read_reg_(reg_addr, &value); if (!this->read_reg_(reg_addr, &value)) {
return value & (1 << bit); return false;
}
// Update the appropriate part of input_mask_
if (pin < 8) {
this->input_mask_ = (this->input_mask_ & 0xFF00) | value;
} else {
this->input_mask_ = (this->input_mask_ & 0x00FF) | (uint16_t(value) << 8);
}
return true;
} }
void MCP23016::digital_write(uint8_t pin, bool value) {
bool MCP23016::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
void MCP23016::digital_write_hw(uint8_t pin, bool value) {
uint8_t reg_addr = pin < 8 ? MCP23016_OLAT0 : MCP23016_OLAT1; uint8_t reg_addr = pin < 8 ? MCP23016_OLAT0 : MCP23016_OLAT1;
this->update_reg_(pin, value, reg_addr); this->update_reg_(pin, value, reg_addr);
} }

View File

@@ -3,6 +3,7 @@
#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 mcp23016 { namespace mcp23016 {
@@ -24,19 +25,22 @@ enum MCP23016GPIORegisters {
MCP23016_IOCON1 = 0x0B, MCP23016_IOCON1 = 0x0B,
}; };
class MCP23016 : public Component, public i2c::I2CDevice { class MCP23016 : public Component, public i2c::I2CDevice, public gpio_expander::CachedGpioExpander<uint8_t, 16> {
public: public:
MCP23016() = default; MCP23016() = default;
void setup() override; void setup() override;
void loop() override;
bool digital_read(uint8_t pin);
void digital_write(uint8_t pin, bool value);
void pin_mode(uint8_t pin, gpio::Flags flags); void pin_mode(uint8_t pin, gpio::Flags flags);
float get_setup_priority() const override; float get_setup_priority() const override;
protected: protected:
// Virtual methods from CachedGpioExpander
bool digital_read_hw(uint8_t pin) override;
bool digital_read_cache(uint8_t pin) override;
void digital_write_hw(uint8_t pin, bool value) override;
// read a given register // read a given register
bool read_reg_(uint8_t reg, uint8_t *value); bool read_reg_(uint8_t reg, uint8_t *value);
// write a value to a given register // write a value to a given register
@@ -46,6 +50,8 @@ class MCP23016 : public Component, public i2c::I2CDevice {
uint8_t olat_0_{0x00}; uint8_t olat_0_{0x00};
uint8_t olat_1_{0x00}; uint8_t olat_1_{0x00};
// Cache for input values (16-bit combined for both banks)
uint16_t input_mask_{0x00};
}; };
class MCP23016GPIOPin : public GPIOPin { class MCP23016GPIOPin : public GPIOPin {