mirror of
https://github.com/esphome/esphome.git
synced 2026-06-01 01:19:45 +08:00
[mcp23xxx][pi4ioe5v6408] Add optional interrupt pin to eliminate polling (#15445)
This commit is contained in:
@@ -22,9 +22,14 @@ void MCP23008::setup() {
|
|||||||
// enable open-drain interrupt pins, 3.3V-safe
|
// enable open-drain interrupt pins, 3.3V-safe
|
||||||
this->write_reg(mcp23x08_base::MCP23X08_IOCON, iocon | IOCON_ODR);
|
this->write_reg(mcp23x08_base::MCP23X08_IOCON, iocon | IOCON_ODR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->setup_interrupt_pin_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCP23008::dump_config() { ESP_LOGCONFIG(TAG, "MCP23008:"); }
|
void MCP23008::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "MCP23008:");
|
||||||
|
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
||||||
|
}
|
||||||
|
|
||||||
bool MCP23008::read_reg(uint8_t reg, uint8_t *value) {
|
bool MCP23008::read_reg(uint8_t reg, uint8_t *value) {
|
||||||
if (this->is_failed())
|
if (this->is_failed())
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ namespace mcp23017 {
|
|||||||
|
|
||||||
static const char *const TAG = "mcp23017";
|
static const char *const TAG = "mcp23017";
|
||||||
|
|
||||||
static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin
|
static constexpr uint8_t IOCON_MIRROR = 0x40; // Mirror INTA/INTB pins
|
||||||
|
static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin
|
||||||
|
|
||||||
void MCP23017::setup() {
|
void MCP23017::setup() {
|
||||||
uint8_t iocon;
|
uint8_t iocon;
|
||||||
@@ -19,14 +20,26 @@ void MCP23017::setup() {
|
|||||||
this->read_reg(mcp23x17_base::MCP23X17_OLATA, &this->olat_a_);
|
this->read_reg(mcp23x17_base::MCP23X17_OLATA, &this->olat_a_);
|
||||||
this->read_reg(mcp23x17_base::MCP23X17_OLATB, &this->olat_b_);
|
this->read_reg(mcp23x17_base::MCP23X17_OLATB, &this->olat_b_);
|
||||||
|
|
||||||
|
uint8_t iocon_flags = 0;
|
||||||
if (this->open_drain_ints_) {
|
if (this->open_drain_ints_) {
|
||||||
// enable open-drain interrupt pins, 3.3V-safe
|
iocon_flags |= IOCON_ODR;
|
||||||
this->write_reg(mcp23x17_base::MCP23X17_IOCONA, iocon | IOCON_ODR);
|
|
||||||
this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon | IOCON_ODR);
|
|
||||||
}
|
}
|
||||||
|
if (this->interrupt_pin_ != nullptr) {
|
||||||
|
// Mirror INTA/INTB so either pin fires for changes on any port
|
||||||
|
iocon_flags |= IOCON_MIRROR;
|
||||||
|
}
|
||||||
|
if (iocon_flags != 0) {
|
||||||
|
this->write_reg(mcp23x17_base::MCP23X17_IOCONA, iocon | iocon_flags);
|
||||||
|
this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon | iocon_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setup_interrupt_pin_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCP23017::dump_config() { ESP_LOGCONFIG(TAG, "MCP23017:"); }
|
void MCP23017::dump_config() {
|
||||||
|
ESP_LOGCONFIG(TAG, "MCP23017:");
|
||||||
|
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
||||||
|
}
|
||||||
|
|
||||||
bool MCP23017::read_reg(uint8_t reg, uint8_t *value) {
|
bool MCP23017::read_reg(uint8_t reg, uint8_t *value) {
|
||||||
if (this->is_failed())
|
if (this->is_failed())
|
||||||
|
|||||||
@@ -34,11 +34,14 @@ void MCP23S08::setup() {
|
|||||||
// enable open-drain interrupt pins, 3.3V-safe (addressed, only this chip)
|
// enable open-drain interrupt pins, 3.3V-safe (addressed, only this chip)
|
||||||
this->write_reg(mcp23x08_base::MCP23X08_IOCON, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR);
|
this->write_reg(mcp23x08_base::MCP23X08_IOCON, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->setup_interrupt_pin_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCP23S08::dump_config() {
|
void MCP23S08::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "MCP23S08:");
|
ESP_LOGCONFIG(TAG, "MCP23S08:");
|
||||||
LOG_PIN(" CS Pin: ", this->cs_);
|
LOG_PIN(" CS Pin: ", this->cs_);
|
||||||
|
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MCP23S08::read_reg(uint8_t reg, uint8_t *value) {
|
bool MCP23S08::read_reg(uint8_t reg, uint8_t *value) {
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ namespace mcp23s17 {
|
|||||||
static const char *const TAG = "mcp23s17";
|
static const char *const TAG = "mcp23s17";
|
||||||
|
|
||||||
// IOCON register bits
|
// IOCON register bits
|
||||||
static constexpr uint8_t IOCON_SEQOP = 0x20; // Sequential operation mode
|
static constexpr uint8_t IOCON_SEQOP = 0x20; // Sequential operation mode
|
||||||
static constexpr uint8_t IOCON_HAEN = 0x08; // Hardware address enable
|
static constexpr uint8_t IOCON_MIRROR = 0x40; // Mirror INTA/INTB pins
|
||||||
static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin
|
static constexpr uint8_t IOCON_HAEN = 0x08; // Hardware address enable
|
||||||
|
static constexpr uint8_t IOCON_ODR = 0x04; // Open-drain output for INT pin
|
||||||
|
|
||||||
void MCP23S17::set_device_address(uint8_t device_addr) {
|
void MCP23S17::set_device_address(uint8_t device_addr) {
|
||||||
if (device_addr != 0) {
|
if (device_addr != 0) {
|
||||||
@@ -37,16 +38,26 @@ void MCP23S17::setup() {
|
|||||||
this->read_reg(mcp23x17_base::MCP23X17_OLATA, &this->olat_a_);
|
this->read_reg(mcp23x17_base::MCP23X17_OLATA, &this->olat_a_);
|
||||||
this->read_reg(mcp23x17_base::MCP23X17_OLATB, &this->olat_b_);
|
this->read_reg(mcp23x17_base::MCP23X17_OLATB, &this->olat_b_);
|
||||||
|
|
||||||
|
uint8_t iocon_flags = IOCON_SEQOP | IOCON_HAEN;
|
||||||
if (this->open_drain_ints_) {
|
if (this->open_drain_ints_) {
|
||||||
// enable open-drain interrupt pins, 3.3V-safe (addressed, only this chip)
|
iocon_flags |= IOCON_ODR;
|
||||||
this->write_reg(mcp23x17_base::MCP23X17_IOCONA, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR);
|
|
||||||
this->write_reg(mcp23x17_base::MCP23X17_IOCONB, IOCON_SEQOP | IOCON_HAEN | IOCON_ODR);
|
|
||||||
}
|
}
|
||||||
|
if (this->interrupt_pin_ != nullptr) {
|
||||||
|
// Mirror INTA/INTB so either pin fires for changes on any port
|
||||||
|
iocon_flags |= IOCON_MIRROR;
|
||||||
|
}
|
||||||
|
if (this->open_drain_ints_ || this->interrupt_pin_ != nullptr) {
|
||||||
|
this->write_reg(mcp23x17_base::MCP23X17_IOCONA, iocon_flags);
|
||||||
|
this->write_reg(mcp23x17_base::MCP23X17_IOCONB, iocon_flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->setup_interrupt_pin_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCP23S17::dump_config() {
|
void MCP23S17::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "MCP23S17:");
|
ESP_LOGCONFIG(TAG, "MCP23S17:");
|
||||||
LOG_PIN(" CS Pin: ", this->cs_);
|
LOG_PIN(" CS Pin: ", this->cs_);
|
||||||
|
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MCP23S17::read_reg(uint8_t reg, uint8_t *value) {
|
bool MCP23S17::read_reg(uint8_t reg, uint8_t *value) {
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ void MCP23X08Base::pin_mode(uint8_t pin, gpio::Flags flags) {
|
|||||||
} else if (flags == gpio::FLAG_OUTPUT) {
|
} else if (flags == gpio::FLAG_OUTPUT) {
|
||||||
this->update_reg(pin, false, iodir);
|
this->update_reg(pin, false, iodir);
|
||||||
}
|
}
|
||||||
|
// When interrupt_pin is configured, auto-enable CHANGE interrupt for input pins
|
||||||
|
// so the chip's INT output fires on any input state change
|
||||||
|
if (this->interrupt_pin_ != nullptr && (flags & gpio::FLAG_INPUT)) {
|
||||||
|
this->pin_interrupt_mode(pin, mcp23xxx_base::MCP23XXX_CHANGE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCP23X08Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) {
|
void MCP23X08Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) {
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ void MCP23X17Base::pin_mode(uint8_t pin, gpio::Flags flags) {
|
|||||||
} else if (flags == gpio::FLAG_OUTPUT) {
|
} else if (flags == gpio::FLAG_OUTPUT) {
|
||||||
this->update_reg(pin, false, iodir);
|
this->update_reg(pin, false, iodir);
|
||||||
}
|
}
|
||||||
|
// When interrupt_pin is configured, auto-enable CHANGE interrupt for input pins
|
||||||
|
// so the chip's INT output fires on any input state change
|
||||||
|
if (this->interrupt_pin_ != nullptr && (flags & gpio::FLAG_INPUT)) {
|
||||||
|
this->pin_interrupt_mode(pin, mcp23xxx_base::MCP23XXX_CHANGE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCP23X17Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) {
|
void MCP23X17Base::pin_interrupt_mode(uint8_t pin, mcp23xxx_base::MCP23XXXInterruptMode interrupt_mode) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from esphome.const import (
|
|||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_INPUT,
|
CONF_INPUT,
|
||||||
CONF_INTERRUPT,
|
CONF_INTERRUPT,
|
||||||
|
CONF_INTERRUPT_PIN,
|
||||||
CONF_INVERTED,
|
CONF_INVERTED,
|
||||||
CONF_MODE,
|
CONF_MODE,
|
||||||
CONF_NUMBER,
|
CONF_NUMBER,
|
||||||
@@ -32,6 +33,7 @@ MCP23XXX_INTERRUPT_MODES = {
|
|||||||
MCP23XXX_CONFIG_SCHEMA = cv.Schema(
|
MCP23XXX_CONFIG_SCHEMA = cv.Schema(
|
||||||
{
|
{
|
||||||
cv.Optional(CONF_OPEN_DRAIN_INTERRUPT, default=False): cv.boolean,
|
cv.Optional(CONF_OPEN_DRAIN_INTERRUPT, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
@@ -43,6 +45,8 @@ async def register_mcp23xxx(config, num_pins):
|
|||||||
await cg.register_component(var, config)
|
await cg.register_component(var, config)
|
||||||
CORE.data.setdefault(CONF_MCP23XXX, {})[id.id] = num_pins
|
CORE.data.setdefault(CONF_MCP23XXX, {})[id.id] = num_pins
|
||||||
cg.add(var.set_open_drain_ints(config[CONF_OPEN_DRAIN_INTERRUPT]))
|
cg.add(var.set_open_drain_ints(config[CONF_OPEN_DRAIN_INTERRUPT]))
|
||||||
|
if interrupt_pin := config.get(CONF_INTERRUPT_PIN):
|
||||||
|
cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin)))
|
||||||
return var
|
return var
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,12 @@ namespace mcp23xxx_base {
|
|||||||
|
|
||||||
template<uint8_t N> void MCP23XXXGPIOPin<N>::setup() {
|
template<uint8_t N> void MCP23XXXGPIOPin<N>::setup() {
|
||||||
this->pin_mode(flags_);
|
this->pin_mode(flags_);
|
||||||
this->parent_->pin_interrupt_mode(this->pin_, this->interrupt_mode_);
|
// When interrupt_pin is configured, pin_mode() already auto-enables CHANGE
|
||||||
|
// interrupt for input pins, so skip the explicit call if the user didn't
|
||||||
|
// override the default (NO_INTERRUPT)
|
||||||
|
if (this->interrupt_mode_ != MCP23XXX_NO_INTERRUPT || this->parent_->get_interrupt_pin() == nullptr) {
|
||||||
|
this->parent_->pin_interrupt_mode(this->pin_, this->interrupt_mode_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
template<uint8_t N> void MCP23XXXGPIOPin<N>::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
|
template<uint8_t N> void MCP23XXXGPIOPin<N>::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
|
||||||
template<uint8_t N> bool MCP23XXXGPIOPin<N>::digital_read() {
|
template<uint8_t N> bool MCP23XXXGPIOPin<N>::digital_read() {
|
||||||
|
|||||||
@@ -15,11 +15,31 @@ template<uint8_t N> class MCP23XXXBase : public Component, public gpio_expander:
|
|||||||
virtual void pin_interrupt_mode(uint8_t pin, MCP23XXXInterruptMode interrupt_mode);
|
virtual void pin_interrupt_mode(uint8_t pin, MCP23XXXInterruptMode interrupt_mode);
|
||||||
|
|
||||||
void set_open_drain_ints(const bool value) { this->open_drain_ints_ = value; }
|
void set_open_drain_ints(const bool value) { this->open_drain_ints_ = value; }
|
||||||
|
void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
|
||||||
|
InternalGPIOPin *get_interrupt_pin() const { return this->interrupt_pin_; }
|
||||||
float get_setup_priority() const override { return setup_priority::IO; }
|
float get_setup_priority() const override { return setup_priority::IO; }
|
||||||
|
|
||||||
void loop() override { this->reset_pin_cache_(); }
|
void loop() override {
|
||||||
|
this->reset_pin_cache_();
|
||||||
|
if (this->interrupt_pin_ != nullptr) {
|
||||||
|
this->disable_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// No need to clear latched interrupts before attaching the ISR — if INT is
|
||||||
|
// already low the ISR fires immediately, loop runs, cache invalidates, and
|
||||||
|
// the GPIO read clears the latch. One harmless extra read at most.
|
||||||
|
void setup_interrupt_pin_() {
|
||||||
|
if (this->interrupt_pin_ != nullptr) {
|
||||||
|
this->interrupt_pin_->setup();
|
||||||
|
this->interrupt_pin_->attach_interrupt(&MCP23XXXBase::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE);
|
||||||
|
this->set_invalidate_on_read_(false);
|
||||||
|
this->disable_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void IRAM_ATTR gpio_intr(MCP23XXXBase *arg) { arg->enable_loop_soon_any_context(); }
|
||||||
|
|
||||||
// read a given register
|
// read a given register
|
||||||
virtual bool read_reg(uint8_t reg, uint8_t *value) = 0;
|
virtual bool read_reg(uint8_t reg, uint8_t *value) = 0;
|
||||||
// write a value to a given register
|
// write a value to a given register
|
||||||
@@ -28,6 +48,7 @@ template<uint8_t N> class MCP23XXXBase : public Component, public gpio_expander:
|
|||||||
virtual void update_reg(uint8_t pin, bool pin_value, uint8_t reg_a) = 0;
|
virtual void update_reg(uint8_t pin, bool pin_value, uint8_t reg_a) = 0;
|
||||||
|
|
||||||
bool open_drain_ints_;
|
bool open_drain_ints_;
|
||||||
|
InternalGPIOPin *interrupt_pin_{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<uint8_t N> class MCP23XXXGPIOPin : public GPIOPin {
|
template<uint8_t N> class MCP23XXXGPIOPin : public GPIOPin {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import esphome.config_validation as cv
|
|||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_INPUT,
|
CONF_INPUT,
|
||||||
|
CONF_INTERRUPT_PIN,
|
||||||
CONF_INVERTED,
|
CONF_INVERTED,
|
||||||
CONF_MODE,
|
CONF_MODE,
|
||||||
CONF_NUMBER,
|
CONF_NUMBER,
|
||||||
@@ -33,6 +34,7 @@ CONFIG_SCHEMA = (
|
|||||||
{
|
{
|
||||||
cv.Required(CONF_ID): cv.declare_id(PI4IOE5V6408Component),
|
cv.Required(CONF_ID): cv.declare_id(PI4IOE5V6408Component),
|
||||||
cv.Optional(CONF_RESET, default=True): cv.boolean,
|
cv.Optional(CONF_RESET, default=True): cv.boolean,
|
||||||
|
cv.Optional(CONF_INTERRUPT_PIN): pins.internal_gpio_input_pin_schema,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.COMPONENT_SCHEMA)
|
.extend(cv.COMPONENT_SCHEMA)
|
||||||
@@ -46,6 +48,8 @@ async def to_code(config):
|
|||||||
await i2c.register_i2c_device(var, config)
|
await i2c.register_i2c_device(var, config)
|
||||||
|
|
||||||
cg.add(var.set_reset(config[CONF_RESET]))
|
cg.add(var.set_reset(config[CONF_RESET]))
|
||||||
|
if interrupt_pin := config.get(CONF_INTERRUPT_PIN):
|
||||||
|
cg.add(var.set_interrupt_pin(await cg.gpio_pin_expression(interrupt_pin)))
|
||||||
|
|
||||||
|
|
||||||
def validate_mode(value):
|
def validate_mode(value):
|
||||||
|
|||||||
@@ -33,9 +33,21 @@ void PI4IOE5V6408Component::setup() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No need to clear latched interrupts before attaching the ISR — if INT is
|
||||||
|
// already low the ISR fires immediately, loop runs, cache invalidates, and
|
||||||
|
// the read clears the latch. One harmless extra read at most.
|
||||||
|
if (this->interrupt_pin_ != nullptr) {
|
||||||
|
this->interrupt_pin_->setup();
|
||||||
|
this->interrupt_pin_->attach_interrupt(&PI4IOE5V6408Component::gpio_intr, this, gpio::INTERRUPT_FALLING_EDGE);
|
||||||
|
this->set_invalidate_on_read_(false);
|
||||||
|
this->disable_loop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
void IRAM_ATTR PI4IOE5V6408Component::gpio_intr(PI4IOE5V6408Component *arg) { arg->enable_loop_soon_any_context(); }
|
||||||
void PI4IOE5V6408Component::dump_config() {
|
void PI4IOE5V6408Component::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "PI4IOE5V6408:");
|
ESP_LOGCONFIG(TAG, "PI4IOE5V6408:");
|
||||||
|
LOG_PIN(" Interrupt Pin: ", this->interrupt_pin_);
|
||||||
LOG_I2C_DEVICE(this)
|
LOG_I2C_DEVICE(this)
|
||||||
if (this->is_failed()) {
|
if (this->is_failed()) {
|
||||||
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL);
|
||||||
@@ -60,7 +72,12 @@ void PI4IOE5V6408Component::pin_mode(uint8_t pin, gpio::Flags flags) {
|
|||||||
this->write_gpio_modes_();
|
this->write_gpio_modes_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PI4IOE5V6408Component::loop() { this->reset_pin_cache_(); }
|
void PI4IOE5V6408Component::loop() {
|
||||||
|
this->reset_pin_cache_();
|
||||||
|
if (this->interrupt_pin_ != nullptr) {
|
||||||
|
this->disable_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool PI4IOE5V6408Component::read_gpio_outputs_() {
|
bool PI4IOE5V6408Component::read_gpio_outputs_() {
|
||||||
if (this->is_failed())
|
if (this->is_failed())
|
||||||
@@ -142,6 +159,13 @@ bool PI4IOE5V6408Component::write_gpio_modes_() {
|
|||||||
this->status_set_warning(LOG_STR("Failed to write GPIO pull enable"));
|
this->status_set_warning(LOG_STR("Failed to write GPIO pull enable"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Enable interrupts for input pins when interrupt pin is configured
|
||||||
|
// (input pins have mode_mask_ bit cleared)
|
||||||
|
if (this->interrupt_pin_ != nullptr &&
|
||||||
|
!this->write_byte(PI4IOE5V6408_REGISTER_INTERRUPT_ENABLE_MASK, static_cast<uint8_t>(~this->mode_mask_))) {
|
||||||
|
this->status_set_warning(LOG_STR("Failed to write interrupt enable mask"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
|
||||||
ESP_LOGV(TAG,
|
ESP_LOGV(TAG,
|
||||||
"Wrote GPIO config:\n"
|
"Wrote GPIO config:\n"
|
||||||
|
|||||||
@@ -22,8 +22,11 @@ class PI4IOE5V6408Component : public Component,
|
|||||||
|
|
||||||
/// Indicate if the component should reset the state during setup
|
/// Indicate if the component should reset the state during setup
|
||||||
void set_reset(bool reset) { this->reset_ = reset; }
|
void set_reset(bool reset) { this->reset_ = reset; }
|
||||||
|
void set_interrupt_pin(InternalGPIOPin *pin) { this->interrupt_pin_ = pin; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
static void IRAM_ATTR gpio_intr(PI4IOE5V6408Component *arg);
|
||||||
|
|
||||||
bool digital_read_hw(uint8_t pin) override;
|
bool digital_read_hw(uint8_t pin) override;
|
||||||
bool digital_read_cache(uint8_t pin) override;
|
bool digital_read_cache(uint8_t pin) override;
|
||||||
void digital_write_hw(uint8_t pin, bool value) override;
|
void digital_write_hw(uint8_t pin, bool value) override;
|
||||||
@@ -40,6 +43,7 @@ class PI4IOE5V6408Component : public Component,
|
|||||||
uint8_t pull_up_down_mask_{0x00};
|
uint8_t pull_up_down_mask_{0x00};
|
||||||
|
|
||||||
bool reset_{true};
|
bool reset_{true};
|
||||||
|
InternalGPIOPin *interrupt_pin_{nullptr};
|
||||||
|
|
||||||
bool read_gpio_modes_();
|
bool read_gpio_modes_();
|
||||||
bool write_gpio_modes_();
|
bool write_gpio_modes_();
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
mcp23008:
|
mcp23008:
|
||||||
i2c_id: i2c_bus
|
- i2c_id: i2c_bus
|
||||||
id: mcp23008_hub
|
id: mcp23008_hub
|
||||||
|
- i2c_id: i2c_bus
|
||||||
|
id: mcp23008_hub_int
|
||||||
|
address: 0x21
|
||||||
|
interrupt_pin: ${interrupt_pin}
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -9,6 +13,12 @@ binary_sensor:
|
|||||||
mcp23xxx: mcp23008_hub
|
mcp23xxx: mcp23008_hub
|
||||||
number: 0
|
number: 0
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
|
- platform: gpio
|
||||||
|
id: mcp23008_binary_sensor_int
|
||||||
|
pin:
|
||||||
|
mcp23xxx: mcp23008_hub_int
|
||||||
|
number: 0
|
||||||
|
mode: INPUT
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
substitutions:
|
||||||
|
interrupt_pin: GPIO15
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
substitutions:
|
||||||
|
interrupt_pin: GPIO15
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml
|
i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
substitutions:
|
||||||
|
interrupt_pin: GPIO2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml
|
i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
mcp23017:
|
mcp23017:
|
||||||
i2c_id: i2c_bus
|
- i2c_id: i2c_bus
|
||||||
id: mcp23017_hub
|
id: mcp23017_hub
|
||||||
|
- i2c_id: i2c_bus
|
||||||
|
id: mcp23017_hub_int
|
||||||
|
address: 0x21
|
||||||
|
interrupt_pin: ${interrupt_pin}
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -9,6 +13,12 @@ binary_sensor:
|
|||||||
mcp23xxx: mcp23017_hub
|
mcp23xxx: mcp23017_hub
|
||||||
number: 0
|
number: 0
|
||||||
mode: INPUT
|
mode: INPUT
|
||||||
|
- platform: gpio
|
||||||
|
id: mcp23017_binary_sensor_int
|
||||||
|
pin:
|
||||||
|
mcp23xxx: mcp23017_hub_int
|
||||||
|
number: 0
|
||||||
|
mode: INPUT
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
substitutions:
|
||||||
|
interrupt_pin: GPIO15
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
substitutions:
|
||||||
|
interrupt_pin: GPIO15
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml
|
i2c: !include ../../test_build_components/common/i2c/esp8266-ard.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
substitutions:
|
||||||
|
interrupt_pin: GPIO2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml
|
i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml
|
||||||
|
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ mcp23s08:
|
|||||||
- id: mcp23s08_hub
|
- id: mcp23s08_hub
|
||||||
cs_pin: ${cs_pin}
|
cs_pin: ${cs_pin}
|
||||||
deviceaddress: 0
|
deviceaddress: 0
|
||||||
|
interrupt_pin: ${interrupt_pin}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
cs_pin: GPIO5
|
cs_pin: GPIO5
|
||||||
|
interrupt_pin: GPIO15
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
spi: !include ../../test_build_components/common/spi/esp32-idf.yaml
|
spi: !include ../../test_build_components/common/spi/esp32-idf.yaml
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
cs_pin: GPIO15
|
cs_pin: GPIO15
|
||||||
|
interrupt_pin: GPIO0
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml
|
spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
cs_pin: GPIO5
|
cs_pin: GPIO5
|
||||||
|
interrupt_pin: GPIO2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
spi: !include ../../test_build_components/common/spi/rp2040-ard.yaml
|
spi: !include ../../test_build_components/common/spi/rp2040-ard.yaml
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ mcp23s17:
|
|||||||
- id: mcp23s17_hub
|
- id: mcp23s17_hub
|
||||||
cs_pin: ${cs_pin}
|
cs_pin: ${cs_pin}
|
||||||
deviceaddress: 0
|
deviceaddress: 0
|
||||||
|
interrupt_pin: ${interrupt_pin}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
cs_pin: GPIO5
|
cs_pin: GPIO5
|
||||||
|
interrupt_pin: GPIO15
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
spi: !include ../../test_build_components/common/spi/esp32-idf.yaml
|
spi: !include ../../test_build_components/common/spi/esp32-idf.yaml
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
cs_pin: GPIO15
|
cs_pin: GPIO15
|
||||||
|
interrupt_pin: GPIO0
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml
|
spi: !include ../../test_build_components/common/spi/esp8266-ard.yaml
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
cs_pin: GPIO5
|
cs_pin: GPIO5
|
||||||
|
interrupt_pin: GPIO2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
spi: !include ../../test_build_components/common/spi/rp2040-ard.yaml
|
spi: !include ../../test_build_components/common/spi/rp2040-ard.yaml
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
pi4ioe5v6408:
|
pi4ioe5v6408:
|
||||||
i2c_id: i2c_bus
|
- i2c_id: i2c_bus
|
||||||
id: pi4ioe1
|
id: pi4ioe1
|
||||||
address: 0x44
|
address: 0x44
|
||||||
|
- i2c_id: i2c_bus
|
||||||
|
id: pi4ioe1_int
|
||||||
|
address: 0x45
|
||||||
|
interrupt_pin: ${interrupt_pin}
|
||||||
|
|
||||||
switch:
|
switch:
|
||||||
- platform: gpio
|
- platform: gpio
|
||||||
@@ -16,3 +20,8 @@ binary_sensor:
|
|||||||
pin:
|
pin:
|
||||||
pi4ioe5v6408: pi4ioe1
|
pi4ioe5v6408: pi4ioe1
|
||||||
number: 1
|
number: 1
|
||||||
|
- platform: gpio
|
||||||
|
id: sensor1_int
|
||||||
|
pin:
|
||||||
|
pi4ioe5v6408: pi4ioe1_int
|
||||||
|
number: 1
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
i2c_sda: GPIO21
|
i2c_sda: GPIO21
|
||||||
i2c_scl: GPIO22
|
i2c_scl: GPIO22
|
||||||
|
interrupt_pin: GPIO15
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
i2c: !include ../../test_build_components/common/i2c/esp32-idf.yaml
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
i2c_sda: GPIO4
|
i2c_sda: GPIO4
|
||||||
i2c_scl: GPIO5
|
i2c_scl: GPIO5
|
||||||
|
interrupt_pin: GPIO2
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml
|
i2c: !include ../../test_build_components/common/i2c/rp2040-ard.yaml
|
||||||
|
|||||||
Reference in New Issue
Block a user