1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-31 07:03:55 +00:00

Merge branch 'integration' into memory_api

This commit is contained in:
J. Nick Koston
2025-09-04 14:40:26 -05:00
10 changed files with 90 additions and 33 deletions

View File

@@ -70,7 +70,7 @@ jobs:
pip3 install build pip3 install build
python3 -m build python3 -m build
- name: Publish - name: Publish
uses: pypa/gh-action-pypi-publish@v1.12.4 uses: pypa/gh-action-pypi-publish@v1.13.0
with: with:
skip-existing: true skip-existing: true

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;
} }
void MCP23016::digital_write(uint8_t pin, bool value) {
// 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;
}
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);
} }
@@ -41,7 +56,7 @@ void MCP23016::pin_mode(uint8_t pin, gpio::Flags flags) {
this->update_reg_(pin, false, iodir); this->update_reg_(pin, false, iodir);
} }
} }
float MCP23016::get_setup_priority() const { return setup_priority::HARDWARE; } float MCP23016::get_setup_priority() const { return setup_priority::IO; }
bool MCP23016::read_reg_(uint8_t reg, uint8_t *value) { bool MCP23016::read_reg_(uint8_t reg, uint8_t *value) {
if (this->is_failed()) if (this->is_failed())
return false; return false;

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 {

View File

@@ -14,6 +14,7 @@ from esphome.const import (
CODEOWNERS = ["@Mat931"] CODEOWNERS = ["@Mat931"]
DEPENDENCIES = ["i2c"] DEPENDENCIES = ["i2c"]
AUTO_LOAD = ["gpio_expander"]
MULTI_CONF = True MULTI_CONF = True
pca6416a_ns = cg.esphome_ns.namespace("pca6416a") pca6416a_ns = cg.esphome_ns.namespace("pca6416a")

View File

@@ -51,6 +51,11 @@ void PCA6416AComponent::setup() {
this->status_has_error()); this->status_has_error());
} }
void PCA6416AComponent::loop() {
// Invalidate cache at the start of each loop
this->reset_pin_cache_();
}
void PCA6416AComponent::dump_config() { void PCA6416AComponent::dump_config() {
if (this->has_pullup_) { if (this->has_pullup_) {
ESP_LOGCONFIG(TAG, "PCAL6416A:"); ESP_LOGCONFIG(TAG, "PCAL6416A:");
@@ -63,15 +68,25 @@ void PCA6416AComponent::dump_config() {
} }
} }
bool PCA6416AComponent::digital_read(uint8_t pin) { bool PCA6416AComponent::digital_read_hw(uint8_t pin) {
uint8_t bit = pin % 8;
uint8_t reg_addr = pin < 8 ? PCA6416A_INPUT0 : PCA6416A_INPUT1; uint8_t reg_addr = pin < 8 ? PCA6416A_INPUT0 : PCA6416A_INPUT1;
uint8_t value = 0; uint8_t value = 0;
this->read_register_(reg_addr, &value); if (!this->read_register_(reg_addr, &value)) {
return value & (1 << bit); return false;
} }
void PCA6416AComponent::digital_write(uint8_t pin, bool value) { // 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;
}
bool PCA6416AComponent::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
void PCA6416AComponent::digital_write_hw(uint8_t pin, bool value) {
uint8_t reg_addr = pin < 8 ? PCA6416A_OUTPUT0 : PCA6416A_OUTPUT1; uint8_t reg_addr = pin < 8 ? PCA6416A_OUTPUT0 : PCA6416A_OUTPUT1;
this->update_register_(pin, value, reg_addr); this->update_register_(pin, value, reg_addr);
} }

View File

@@ -3,20 +3,20 @@
#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 pca6416a { namespace pca6416a {
class PCA6416AComponent : public Component, public i2c::I2CDevice { class PCA6416AComponent : public Component,
public i2c::I2CDevice,
public gpio_expander::CachedGpioExpander<uint8_t, 16> {
public: public:
PCA6416AComponent() = default; PCA6416AComponent() = default;
/// Check i2c availability and setup masks /// Check i2c availability and setup masks
void setup() override; void setup() override;
/// Helper function to read the value of a pin. void loop() override;
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);
@@ -25,6 +25,11 @@ class PCA6416AComponent : public Component, public i2c::I2CDevice {
void dump_config() override; void dump_config() 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;
bool read_register_(uint8_t reg, uint8_t *value); bool read_register_(uint8_t reg, uint8_t *value);
bool write_register_(uint8_t reg, uint8_t value); bool write_register_(uint8_t reg, uint8_t value);
void update_register_(uint8_t pin, bool pin_value, uint8_t reg_addr); void update_register_(uint8_t pin, bool pin_value, uint8_t reg_addr);
@@ -32,6 +37,8 @@ class PCA6416AComponent : public Component, public i2c::I2CDevice {
/// The mask to write as output state - 1 means HIGH, 0 means LOW /// The mask to write as output state - 1 means HIGH, 0 means LOW
uint8_t output_0_{0x00}; uint8_t output_0_{0x00};
uint8_t output_1_{0x00}; uint8_t output_1_{0x00};
/// Cache for input values (16-bit combined for both banks)
uint16_t input_mask_{0x00};
/// Storage for last I2C error seen /// Storage for last I2C error seen
esphome::i2c::ErrorCode last_error_; esphome::i2c::ErrorCode last_error_;
/// Only the PCAL6416A has pull-up resistors /// Only the PCAL6416A has pull-up resistors

View File

@@ -25,7 +25,7 @@ CONF_SCAN_TIME = "scan_time"
CONF_DEBOUNCE_TIME = "debounce_time" CONF_DEBOUNCE_TIME = "debounce_time"
CONF_SX1509_ID = "sx1509_id" CONF_SX1509_ID = "sx1509_id"
AUTO_LOAD = ["key_provider"] AUTO_LOAD = ["key_provider", "gpio_expander"]
DEPENDENCIES = ["i2c"] DEPENDENCIES = ["i2c"]
MULTI_CONF = True MULTI_CONF = True

View File

@@ -39,6 +39,9 @@ void SX1509Component::dump_config() {
} }
void SX1509Component::loop() { void SX1509Component::loop() {
// Reset cache at the start of each loop
this->reset_pin_cache_();
if (this->has_keypad_) { if (this->has_keypad_) {
if (millis() - this->last_loop_timestamp_ < min_loop_period_) if (millis() - this->last_loop_timestamp_ < min_loop_period_)
return; return;
@@ -73,18 +76,20 @@ void SX1509Component::loop() {
} }
} }
bool SX1509Component::digital_read(uint8_t pin) { bool SX1509Component::digital_read_hw(uint8_t pin) {
// Always read all pins when any input pin is accessed
return this->read_byte_16(REG_DATA_B, &this->input_mask_);
}
bool SX1509Component::digital_read_cache(uint8_t pin) {
// Return cached value for input pins, false for output pins
if (this->ddr_mask_ & (1 << pin)) { if (this->ddr_mask_ & (1 << pin)) {
uint16_t temp_reg_data; return this->input_mask_ & (1 << pin);
if (!this->read_byte_16(REG_DATA_B, &temp_reg_data))
return false;
if (temp_reg_data & (1 << pin))
return true;
} }
return false; return false;
} }
void SX1509Component::digital_write(uint8_t pin, bool bit_value) { void SX1509Component::digital_write_hw(uint8_t pin, bool bit_value) {
if ((~this->ddr_mask_) & (1 << pin)) { if ((~this->ddr_mask_) & (1 << pin)) {
// If the pin is an output, write high/low // If the pin is an output, write high/low
uint16_t temp_reg_data = 0; uint16_t temp_reg_data = 0;

View File

@@ -2,6 +2,7 @@
#include "esphome/components/i2c/i2c.h" #include "esphome/components/i2c/i2c.h"
#include "esphome/components/key_provider/key_provider.h" #include "esphome/components/key_provider/key_provider.h"
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/core/hal.h" #include "esphome/core/hal.h"
#include "sx1509_gpio_pin.h" #include "sx1509_gpio_pin.h"
@@ -30,7 +31,10 @@ class SX1509Processor {
class SX1509KeyTrigger : public Trigger<uint8_t> {}; class SX1509KeyTrigger : public Trigger<uint8_t> {};
class SX1509Component : public Component, public i2c::I2CDevice, public key_provider::KeyProvider { class SX1509Component : public Component,
public i2c::I2CDevice,
public gpio_expander::CachedGpioExpander<uint16_t, 16>,
public key_provider::KeyProvider {
public: public:
SX1509Component() = default; SX1509Component() = default;
@@ -39,11 +43,9 @@ class SX1509Component : public Component, public i2c::I2CDevice, public key_prov
float get_setup_priority() const override { return setup_priority::HARDWARE; } float get_setup_priority() const override { return setup_priority::HARDWARE; }
void loop() override; void loop() override;
bool digital_read(uint8_t pin);
uint16_t read_key_data(); uint16_t read_key_data();
void set_pin_value(uint8_t pin, uint8_t i_on) { this->write_byte(REG_I_ON[pin], i_on); }; void set_pin_value(uint8_t pin, uint8_t i_on) { this->write_byte(REG_I_ON[pin], i_on); };
void pin_mode(uint8_t pin, gpio::Flags flags); void pin_mode(uint8_t pin, gpio::Flags flags);
void digital_write(uint8_t pin, bool bit_value);
uint32_t get_clock() { return this->clk_x_; }; uint32_t get_clock() { return this->clk_x_; };
void set_rows_cols(uint8_t rows, uint8_t cols) { void set_rows_cols(uint8_t rows, uint8_t cols) {
this->rows_ = rows; this->rows_ = rows;
@@ -61,10 +63,15 @@ class SX1509Component : public Component, public i2c::I2CDevice, public key_prov
void setup_led_driver(uint8_t pin); void setup_led_driver(uint8_t pin);
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;
uint32_t clk_x_ = 2000000; uint32_t clk_x_ = 2000000;
uint8_t frequency_ = 0; uint8_t frequency_ = 0;
uint16_t ddr_mask_ = 0x00; uint16_t ddr_mask_ = 0x00;
uint16_t input_mask_ = 0x00; uint16_t input_mask_ = 0x00; // Cache for input values (16-bit for all pins)
uint16_t port_mask_ = 0x00; uint16_t port_mask_ = 0x00;
uint16_t output_state_ = 0x00; uint16_t output_state_ = 0x00;
bool has_keypad_ = false; bool has_keypad_ = false;