[gpio_expander][pcf8574][mpr121][ch422g][ch423][pcm5122][weikai] Move the GPIO expanders and pin providers onto the shared pin helpers (#20868)

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
J. Nick Koston
2026-10-18 16:27:01 -10:00
committed by GitHub
co-authored by pre-commit-ci-lite[bot]
parent ded5ad6cb1
commit 28e43235fa
53 changed files with 220 additions and 906 deletions
+6 -9
View File
@@ -7,7 +7,6 @@ from esphome.const import (
CONF_I2C_ID,
CONF_ID,
CONF_INPUT,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OPEN_DRAIN,
@@ -18,6 +17,7 @@ from esphome.types import ConfigType
CODEOWNERS = ["@jesterret", "@clydebarrow"]
DEPENDENCIES = ["i2c"]
AUTO_LOAD = ["gpio_expander"]
DOMAIN = "ch422g"
MULTI_CONF = True
ch422g_ns = cg.esphome_ns.namespace("ch422g")
@@ -66,13 +66,10 @@ CH422G_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_CH422G, CH422G_PIN_SCHEMA, pin_mode_check)
async def ch422g_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
var = await pins.new_parented_pin(config, CONF_CH422G)
# The parent collects every pin's mode before its setup() writes the mode register
parent = await cg.get_variable(config[CONF_CH422G])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
cg.add(
parent.pin_mode(config[CONF_NUMBER], pins.gpio_flags_expr(config[CONF_MODE]))
)
return var
+2 -12
View File
@@ -120,16 +120,6 @@ bool CH422GComponent::write_outputs_() {
float CH422GComponent::get_setup_priority() const { return setup_priority::IO; }
void CH422GGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool CH422GGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; }
void CH422GGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value ^ this->inverted_); }
size_t CH422GGPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "EXIO%u via CH422G", this->pin_);
}
void CH422GGPIOPin::set_flags(gpio::Flags flags) {
flags_ = flags;
this->parent_->pin_mode(this->pin_, flags);
}
} // namespace esphome::ch422g
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::ch422g::CH422GComponent, "EXIO%u via CH422G")
+4 -21
View File
@@ -1,5 +1,6 @@
#pragma once
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
@@ -42,26 +43,8 @@ class CH422GComponent final : public Component, public i2c::I2CDevice {
};
/// Helper class to expose a CH422G pin as a GPIO pin.
class CH422GGPIOPin final : public GPIOPin {
public:
void setup() override{};
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(CH422GComponent *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags);
gpio::Flags get_flags() const override { return this->flags_; }
protected:
CH422GComponent *parent_{};
uint8_t pin_{};
bool inverted_{};
gpio::Flags flags_{};
};
using CH422GGPIOPin = gpio_expander::ExpanderGPIOPin<CH422GComponent>;
} // namespace esphome::ch422g
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::ch422g::CH422GComponent);
+6 -9
View File
@@ -7,7 +7,6 @@ from esphome.const import (
CONF_I2C_ID,
CONF_ID,
CONF_INPUT,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OPEN_DRAIN,
@@ -19,6 +18,7 @@ from esphome.types import ConfigType
CODEOWNERS = ["@dwmw2"]
DEPENDENCIES = ["i2c"]
AUTO_LOAD = ["gpio_expander"]
DOMAIN = "ch423"
MULTI_CONF = True
ch423_ns = cg.esphome_ns.namespace("ch423")
@@ -93,13 +93,10 @@ CH423_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_CH423, CH423_PIN_SCHEMA, pin_mode_check)
async def ch423_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
var = await pins.new_parented_pin(config, CONF_CH423)
# The parent collects every pin's mode before its setup() writes the mode register
parent = await cg.get_variable(config[CONF_CH423])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
cg.add(
parent.pin_mode(config[CONF_NUMBER], pins.gpio_flags_expr(config[CONF_MODE]))
)
return var
+2 -12
View File
@@ -123,16 +123,6 @@ bool CH423Component::write_outputs_() {
float CH423Component::get_setup_priority() const { return setup_priority::IO; }
void CH423GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool CH423GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; }
void CH423GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value ^ this->inverted_); }
size_t CH423GPIOPin::dump_summary(char *buffer, size_t len) const {
return snprintf(buffer, len, "EXIO%u via CH423", this->pin_);
}
void CH423GPIOPin::set_flags(gpio::Flags flags) {
flags_ = flags;
this->parent_->pin_mode(this->pin_, flags);
}
} // namespace esphome::ch423
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::ch423::CH423Component, "EXIO%u via CH423")
+4 -21
View File
@@ -1,5 +1,6 @@
#pragma once
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
@@ -41,26 +42,8 @@ class CH423Component final : public Component, public i2c::I2CDevice {
};
/// Helper class to expose a CH423 pin as a GPIO pin.
class CH423GPIOPin final : public GPIOPin {
public:
void setup() override{};
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(CH423Component *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags);
gpio::Flags get_flags() const override { return this->flags_; }
protected:
CH423Component *parent_{};
uint8_t pin_{};
bool inverted_{};
gpio::Flags flags_{};
};
using CH423GPIOPin = gpio_expander::ExpanderGPIOPin<CH423Component>;
} // namespace esphome::ch423
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::ch423::CH423Component);
+4 -30
View File
@@ -2,21 +2,14 @@ from esphome import automation, pins
import esphome.codegen as cg
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
CONF_PULLUP,
)
from esphome.const import CONF_ID, CONF_INPUT, CONF_OUTPUT, CONF_PULLUP
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
CODEOWNERS = ["@looping40"]
DOMAIN = "max6956"
AUTO_LOAD = ["gpio_expander"]
DEPENDENCIES = ["i2c"]
MULTI_CONF = True
@@ -56,23 +49,13 @@ async def to_code(config: ConfigType) -> None:
cg.add(var.set_brightness_global(config[CONF_BRIGHTNESS_GLOBAL]))
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
if value[CONF_PULLUP] and not value[CONF_INPUT]:
raise cv.Invalid("Pullup only available with input")
return value
CONF_MAX6956 = "max6956"
MAX6956_PIN_SCHEMA = pins.gpio_base_schema(
MAX6956GPIOPin,
cv.int_range(min=4, max=31),
modes=[CONF_INPUT, CONF_PULLUP, CONF_OUTPUT],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output_pullup,
).extend(
{
cv.Required(CONF_MAX6956): pins.use_id_or_address(MAX6956),
@@ -82,16 +65,7 @@ MAX6956_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_MAX6956, MAX6956_PIN_SCHEMA)
async def max6956_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_MAX6956])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_MAX6956)
automation.register_apply_action(
+2 -11
View File
@@ -155,15 +155,6 @@ void MAX6956::dump_config() {
}
}
/**************************************
* MAX6956GPIOPin *
**************************************/
void MAX6956GPIOPin::setup() { pin_mode(flags_); }
void MAX6956GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool MAX6956GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void MAX6956GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
size_t MAX6956GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via Max6956", this->pin_);
}
} // namespace esphome::max6956
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::max6956::MAX6956, "%u via Max6956")
+4 -21
View File
@@ -3,6 +3,7 @@
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
namespace esphome::max6956 {
@@ -69,26 +70,8 @@ class MAX6956 final : public Component, public i2c::I2CDevice {
int8_t prev_bright_[28] = {0};
};
class MAX6956GPIOPin final : public GPIOPin {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(MAX6956 *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags) { flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
MAX6956 *parent_;
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
using MAX6956GPIOPin = gpio_expander::ExpanderGPIOPin<MAX6956>;
} // namespace esphome::max6956
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::max6956::MAX6956);
+3 -28
View File
@@ -2,15 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import gpio_expander, i2c
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INTERRUPT_PIN,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
)
from esphome.const import CONF_ID, CONF_INPUT, CONF_INTERRUPT_PIN, CONF_OUTPUT
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
@@ -41,20 +33,12 @@ async def to_code(config: ConfigType) -> None:
await cg.add_pin(var.set_interrupt_pin, config.get(CONF_INTERRUPT_PIN))
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
return value
CONF_MCP23016 = "mcp23016"
MCP23016_PIN_SCHEMA = pins.gpio_base_schema(
MCP23016GPIOPin,
cv.int_range(min=0, max=15),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output,
invertible=True,
).extend(
{
@@ -65,13 +49,4 @@ MCP23016_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23016, MCP23016_PIN_SCHEMA)
async def mcp23016_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_MCP23016])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_MCP23016)
+2 -8
View File
@@ -92,12 +92,6 @@ void MCP23016::update_reg_(uint8_t pin, bool pin_value, uint8_t reg_addr) {
}
}
void MCP23016GPIOPin::setup() { pin_mode(flags_); }
void MCP23016GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool MCP23016GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void MCP23016GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
size_t MCP23016GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via MCP23016", this->pin_);
}
} // namespace esphome::mcp23016
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::mcp23016::MCP23016, "%u via MCP23016")
+4 -21
View File
@@ -4,6 +4,7 @@
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
namespace esphome::mcp23016 {
@@ -56,26 +57,8 @@ class MCP23016 final : public Component, public i2c::I2CDevice, public gpio_expa
InternalGPIOPin *interrupt_pin_{nullptr};
};
class MCP23016GPIOPin final : public GPIOPin {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(MCP23016 *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags) { flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
MCP23016 *parent_;
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
using MCP23016GPIOPin = gpio_expander::ExpanderGPIOPin<MCP23016>;
} // namespace esphome::mcp23016
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::mcp23016::MCP23016);
+4 -24
View File
@@ -7,9 +7,6 @@ from esphome.const import (
CONF_INPUT,
CONF_INTERRUPT,
CONF_INTERRUPT_PIN,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OPEN_DRAIN_INTERRUPT,
CONF_OUTPUT,
CONF_PULLUP,
@@ -51,23 +48,13 @@ async def register_mcp23xxx(config: ConfigType, num_pins: int) -> MockObj:
return var
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
if value[CONF_PULLUP] and not value[CONF_INPUT]:
raise cv.Invalid("Pullup only available with input")
return value
CONF_MCP23XXX = "mcp23xxx"
MCP23XXX_PIN_SCHEMA = pins.gpio_base_schema(
MCP23XXXGPIOPin,
cv.int_range(min=0, max=15),
modes=[CONF_INPUT, CONF_OUTPUT, CONF_PULLUP],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output_pullup,
invertible=True,
).extend(
{
@@ -82,16 +69,9 @@ MCP23XXX_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23XXX, MCP23XXX_PIN_SCHEMA)
async def mcp23xxx_pin_to_code(config: ConfigType) -> MockObj:
parent_id: ID = config[CONF_MCP23XXX]
parent = await cg.get_variable(parent_id)
# Wait for the hub so its to_code has recorded the pin count
await cg.get_variable(parent_id)
num_pins = cg.TemplateArguments(CORE.data[CONF_MCP23XXX][parent_id.id])
var = cg.new_Pvariable(config[CONF_ID], num_pins)
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
var = await pins.new_parented_pin(config, CONF_MCP23XXX, num_pins)
cg.add(var.set_interrupt_mode(config[CONF_INTERRUPT]))
return var
+6 -20
View File
@@ -7,8 +7,6 @@ from esphome.const import (
CONF_CHANNEL,
CONF_ID,
CONF_INPUT,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
)
@@ -24,12 +22,15 @@ CONF_MAX_TOUCH_CHANNEL = "max_touch_channel"
CONF_MPR121 = "mpr121"
CONF_MPR121_ID = "mpr121_id"
AUTO_LOAD = ["gpio_expander"]
DEPENDENCIES = ["i2c"]
DOMAIN = "mpr121"
mpr121_ns = cg.esphome_ns.namespace("mpr121")
MPR121Component = mpr121_ns.class_("MPR121Component", cg.Component, i2c.I2CDevice)
MPR121GPIOPin = mpr121_ns.class_("MPR121GPIOPin", cg.GPIOPin)
MPR121GPIOPin = mpr121_ns.class_(
"MPR121GPIOPin", cg.GPIOPin, cg.Parented.template(MPR121Component)
)
MULTI_CONF = True
CONFIG_SCHEMA = (
@@ -85,12 +86,6 @@ async def to_code(config: ConfigType) -> None:
await i2c.register_i2c_device(var, config)
def validate_mode(value: ConfigType) -> ConfigType:
if bool(value[CONF_INPUT]) == bool(value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
return value
# https://www.nxp.com/docs/en/data-sheet/MPR121.pdf, page 4
#
# Among the 12 electrode inputs, 8 inputs are designed as multifunctional pins. When these pins are
@@ -100,7 +95,7 @@ MPR121_GPIO_PIN_SCHEMA = pins.gpio_base_schema(
MPR121GPIOPin,
cv.int_range(min=4, max=11),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output,
).extend(
{
cv.Required(CONF_MPR121): cv.use_id(MPR121Component),
@@ -121,13 +116,4 @@ def mpr121_pin_final_validate(
CONF_MPR121, MPR121_GPIO_PIN_SCHEMA, mpr121_pin_final_validate
)
async def mpr121_gpio_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_MPR121])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_MPR121)
+7 -24
View File
@@ -80,9 +80,10 @@ void MPR121Component::loop() {
this->read_byte(MPR121_GPIODATA, &this->gpio_input_);
}
bool MPR121Component::digital_read(uint8_t ionum) { return (this->gpio_input_ & (1 << ionum)) != 0; }
bool MPR121Component::digital_read(uint8_t pin) { return (this->gpio_input_ & (1 << (pin - 4))) != 0; }
void MPR121Component::digital_write(uint8_t ionum, bool value) {
void MPR121Component::digital_write(uint8_t pin, bool value) {
const uint8_t ionum = pin - 4;
if (value) {
this->gpio_output_ |= (1 << ionum);
} else {
@@ -91,7 +92,8 @@ void MPR121Component::digital_write(uint8_t ionum, bool value) {
this->flush_gpio_();
}
void MPR121Component::pin_mode(uint8_t ionum, gpio::Flags flags) {
void MPR121Component::pin_mode(uint8_t pin, gpio::Flags flags) {
const uint8_t ionum = pin - 4;
this->gpio_enable_ |= (1 << ionum);
if (flags & gpio::FLAG_INPUT) {
this->gpio_direction_ &= ~(1 << ionum);
@@ -115,25 +117,6 @@ bool MPR121Component::flush_gpio_() {
return this->status_comm_result(this->write_byte(MPR121_GPIODATA, this->gpio_output_));
}
void MPR121GPIOPin::setup() { this->pin_mode(this->flags_); }
void MPR121GPIOPin::pin_mode(gpio::Flags flags) {
assert(this->pin_ >= 4);
this->parent_->pin_mode(this->pin_ - 4, flags);
}
bool MPR121GPIOPin::digital_read() {
assert(this->pin_ >= 4);
return this->parent_->digital_read(this->pin_ - 4) != this->inverted_;
}
void MPR121GPIOPin::digital_write(bool value) {
assert(this->pin_ >= 4);
this->parent_->digital_write(this->pin_ - 4, value != this->inverted_);
}
size_t MPR121GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "ELE%u on MPR121", this->pin_);
}
} // namespace esphome::mpr121
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::mpr121::MPR121Component, "ELE%u on MPR121")
+8 -25
View File
@@ -4,6 +4,7 @@
#include "esphome/core/defines.h"
#include "esphome/core/hal.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "esphome/components/i2c/i2c.h"
#include <vector>
@@ -73,10 +74,10 @@ class MPR121Component final : public Component, public i2c::I2CDevice {
void set_max_touch_channel(uint8_t max_touch_channel) { this->max_touch_channel_ = max_touch_channel; }
// GPIO helper functions.
bool digital_read(uint8_t ionum);
void digital_write(uint8_t ionum, bool value);
void pin_mode(uint8_t ionum, gpio::Flags flags);
// GPIO helper functions; `pin` is the electrode number, 4 to 11, of the shared GPIO pins.
bool digital_read(uint8_t pin);
void digital_write(uint8_t pin, bool value);
void pin_mode(uint8_t pin, gpio::Flags flags);
protected:
std::vector<MPR121Channel *> channels_{};
@@ -98,26 +99,8 @@ class MPR121Component final : public Component, public i2c::I2CDevice {
};
/// Helper class to expose a MPR121 pin as an internal input GPIO pin.
class MPR121GPIOPin final : public GPIOPin {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(MPR121Component *parent) { this->parent_ = parent; }
void set_pin(uint8_t pin) { this->pin_ = pin; }
void set_inverted(bool inverted) { this->inverted_ = inverted; }
void set_flags(gpio::Flags flags) { this->flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
MPR121Component *parent_;
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
using MPR121GPIOPin = gpio_expander::ExpanderGPIOPin<MPR121Component>;
} // namespace esphome::mpr121
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::mpr121::MPR121Component);
+7 -35
View File
@@ -6,9 +6,6 @@ from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INTERRUPT_PIN,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
CONF_PULLUP,
)
@@ -45,43 +42,18 @@ async def to_code(config: ConfigType) -> None:
await cg.add_pin(var.set_interrupt_pin, config.get(CONF_INTERRUPT_PIN))
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
if value[CONF_PULLUP] and not value[CONF_INPUT]:
raise cv.Invalid("Pullup only available with input")
return value
PCA6416A_PIN_SCHEMA = cv.All(
PCA6416A_PIN_SCHEMA = pins.gpio_base_schema(
PCA6416AGPIOPin,
cv.int_range(min=0, max=15),
modes=[CONF_INPUT, CONF_PULLUP, CONF_OUTPUT],
mode_validator=pins.gpio_validate_input_xor_output_pullup,
).extend(
{
cv.GenerateID(): cv.declare_id(PCA6416AGPIOPin),
cv.Required(CONF_PCA6416A): pins.use_id_or_address(PCA6416AComponent),
cv.Required(CONF_NUMBER): cv.int_range(min=0, max=15),
cv.Optional(CONF_MODE, default={}): cv.All(
{
cv.Optional(CONF_INPUT, default=False): cv.boolean,
cv.Optional(CONF_PULLUP, default=False): cv.boolean,
cv.Optional(CONF_OUTPUT, default=False): cv.boolean,
},
validate_mode,
),
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
}
)
@pins.PIN_SCHEMA_REGISTRY.register(CONF_PCA6416A, PCA6416A_PIN_SCHEMA)
async def pca6416a_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_PCA6416A])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_PCA6416A)
+2 -8
View File
@@ -187,12 +187,6 @@ void PCA6416AComponent::update_register_(uint8_t pin, bool pin_value, uint8_t re
float PCA6416AComponent::get_setup_priority() const { return setup_priority::IO; }
void PCA6416AGPIOPin::setup() { pin_mode(flags_); }
void PCA6416AGPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool PCA6416AGPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void PCA6416AGPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
size_t PCA6416AGPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via PCA6416A", this->pin_);
}
} // namespace esphome::pca6416a
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::pca6416a::PCA6416AComponent, "%u via PCA6416A")
+4 -22
View File
@@ -4,6 +4,7 @@
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
namespace esphome::pca6416a {
@@ -48,27 +49,8 @@ class PCA6416AComponent final : public Component,
InternalGPIOPin *interrupt_pin_{nullptr};
};
/// Helper class to expose a PCA6416A pin as an internal input GPIO pin.
class PCA6416AGPIOPin final : public GPIOPin {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(PCA6416AComponent *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags) { flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
PCA6416AComponent *parent_;
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
using PCA6416AGPIOPin = gpio_expander::ExpanderGPIOPin<PCA6416AComponent>;
} // namespace esphome::pca6416a
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::pca6416a::PCA6416AComponent);
+3 -25
View File
@@ -2,15 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import gpio_expander, i2c
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INTERRUPT_PIN,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
)
from esphome.const import CONF_ID, CONF_INPUT, CONF_INTERRUPT_PIN, CONF_OUTPUT
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
@@ -45,19 +37,11 @@ async def to_code(config: ConfigType) -> None:
await cg.add_pin(var.set_interrupt_pin, config.get(CONF_INTERRUPT_PIN))
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
return value
PCA9505_PIN_SCHEMA = pins.gpio_base_schema(
PCA9505GPIOPin,
cv.int_range(min=0, max=39),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output,
).extend(
{
cv.Required(CONF_PCA9505): cv.use_id(PCA9505Component),
@@ -67,10 +51,4 @@ PCA9505_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_PCA9505, PCA9505_PIN_SCHEMA)
async def pca9505_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_parented(var, config[CONF_PCA9505])
cg.add(var.set_pin(config[CONF_NUMBER]))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_PCA9505)
+2 -12
View File
@@ -135,16 +135,6 @@ bool PCA9505Component::write_all_banks_(uint8_t reg, uint8_t value) {
float PCA9505Component::get_setup_priority() const { return setup_priority::IO; }
void PCA9505GPIOPin::setup() { this->pin_mode(this->flags_); }
void PCA9505GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool PCA9505GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void PCA9505GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
size_t PCA9505GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via PCA9505", this->pin_);
}
} // namespace esphome::pca9505
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::pca9505::PCA9505Component, "%u via PCA9505")
+4 -19
View File
@@ -4,6 +4,7 @@
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "esphome/components/i2c/i2c.h"
namespace esphome::pca9505 {
@@ -49,24 +50,8 @@ class PCA9505Component final : public Component,
InternalGPIOPin *interrupt_pin_{nullptr};
};
class PCA9505GPIOPin final : public GPIOPin, public Parented<PCA9505Component> {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_pin(uint8_t pin) { this->pin_ = pin; }
void set_inverted(bool inverted) { this->inverted_ = inverted; }
void set_flags(gpio::Flags flags) { this->flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
uint8_t pin_{0};
bool inverted_{false};
gpio::Flags flags_{};
};
using PCA9505GPIOPin = gpio_expander::ExpanderGPIOPin<PCA9505Component>;
} // namespace esphome::pca9505
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::pca9505::PCA9505Component);
+2 -21
View File
@@ -6,8 +6,6 @@ from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INTERRUPT_PIN,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
)
@@ -51,19 +49,11 @@ async def to_code(config: ConfigType) -> None:
await cg.add_pin(var.set_interrupt_pin, config.get(CONF_INTERRUPT_PIN))
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
return value
PCA9554_PIN_SCHEMA = pins.gpio_base_schema(
PCA9554GPIOPin,
cv.int_range(min=0, max=15),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output,
).extend(
{
cv.Required(CONF_PCA9554): pins.use_id_or_address(PCA9554Component),
@@ -83,13 +73,4 @@ def pca9554_pin_final_validate(
CONF_PCA9554, PCA9554_PIN_SCHEMA, pca9554_pin_final_validate
)
async def pca9554_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_PCA9554])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_PCA9554)
+2 -8
View File
@@ -135,12 +135,6 @@ bool PCA9554Component::write_register_(uint8_t reg, uint16_t value) {
float PCA9554Component::get_setup_priority() const { return setup_priority::IO; }
void PCA9554GPIOPin::setup() { pin_mode(flags_); }
void PCA9554GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool PCA9554GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void PCA9554GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
size_t PCA9554GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via PCA9554", this->pin_);
}
} // namespace esphome::pca9554
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::pca9554::PCA9554Component, "%u via PCA9554")
+4 -25
View File
@@ -4,6 +4,7 @@
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
namespace esphome::pca9554 {
@@ -52,30 +53,8 @@ class PCA9554Component final : public Component,
InternalGPIOPin *interrupt_pin_{nullptr};
};
/// Helper class to expose a PCA9554 pin as an internal input GPIO pin.
class PCA9554GPIOPin final : public GPIOPin {
public:
// User provided, not "= default": `new(p) PCA9554GPIOPin()` would zero-fill .bss that is already zero.
PCA9554GPIOPin() {}
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(PCA9554Component *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags) { flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
PCA9554Component *parent_{nullptr};
uint8_t pin_{0};
bool inverted_{false};
gpio::Flags flags_{};
};
using PCA9554GPIOPin = gpio_expander::ExpanderGPIOPin<PCA9554Component>;
} // namespace esphome::pca9554
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::pca9554::PCA9554Component);
+8 -20
View File
@@ -6,7 +6,6 @@ from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INTERRUPT_PIN,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
@@ -23,7 +22,9 @@ MULTI_CONF = True
pcf8574_ns = cg.esphome_ns.namespace("pcf8574")
PCF8574Component = pcf8574_ns.class_("PCF8574Component", cg.Component, i2c.I2CDevice)
PCF8574GPIOPin = pcf8574_ns.class_("PCF8574GPIOPin", cg.GPIOPin)
PCF8574GPIOPin = pcf8574_ns.class_(
"PCF8574GPIOPin", cg.GPIOPin, cg.Parented.template(PCF8574Component)
)
CONF_PCF8574 = "pcf8574"
CONF_PCF8575 = "pcf8575"
@@ -51,19 +52,11 @@ async def to_code(config: ConfigType) -> None:
await cg.add_pin(var.set_interrupt_pin, config.get(CONF_INTERRUPT_PIN))
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
return value
PCF8574_PIN_SCHEMA = pins.gpio_base_schema(
PCF8574GPIOPin,
cv.int_range(min=0, max=15),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output,
invertible=True,
).extend(
{
@@ -74,13 +67,8 @@ PCF8574_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_PCF8574, PCF8574_PIN_SCHEMA)
async def pcf8574_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_PCF8574])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
var = await pins.new_parented_pin(config, CONF_PCF8574)
if config[CONF_MODE][CONF_INPUT]:
parent = await cg.get_variable(config[CONF_PCF8574])
cg.add(parent.register_input_pin(config[CONF_NUMBER]))
return var
+2 -13
View File
@@ -109,17 +109,6 @@ bool PCF8574Component::write_gpio_() {
}
float PCF8574Component::get_setup_priority() const { return setup_priority::IO; }
void PCF8574GPIOPin::setup() { pin_mode(flags_); }
void PCF8574GPIOPin::set_flags(gpio::Flags flags) {
this->flags_ = flags;
if (flags & gpio::FLAG_INPUT)
this->parent_->register_input_pin(this->pin_);
}
void PCF8574GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool PCF8574GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void PCF8574GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
size_t PCF8574GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via PCF8574", this->pin_);
}
} // namespace esphome::pcf8574
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::pcf8574::PCF8574Component, "%u via PCF8574")
+4 -26
View File
@@ -4,6 +4,7 @@
#include "esphome/core/hal.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
namespace esphome::pcf8574 {
@@ -56,31 +57,8 @@ class PCF8574Component final : public Component,
InternalGPIOPin *interrupt_pin_{nullptr};
};
/// Helper class to expose a PCF8574 pin as an internal input GPIO pin.
class PCF8574GPIOPin final : public GPIOPin {
public:
// User provided, not "= default": `new(p) PCF8574GPIOPin()` would zero-fill .bss that is already zero.
PCF8574GPIOPin() {}
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(PCF8574Component *parent) { parent_ = parent; }
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
// Call after set_parent() and set_pin(): input flags register the pin with the parent.
void set_flags(gpio::Flags flags);
gpio::Flags get_flags() const override { return this->flags_; }
protected:
PCF8574Component *parent_{nullptr};
uint8_t pin_{0};
bool inverted_{false};
gpio::Flags flags_{};
};
using PCF8574GPIOPin = gpio_expander::ExpanderGPIOPin<PCF8574Component>;
} // namespace esphome::pcf8574
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::pcf8574::PCF8574Component);
+2 -18
View File
@@ -6,9 +6,7 @@ import esphome.config_validation as cv
from esphome.const import (
CONF_BITS_PER_SAMPLE,
CONF_ENABLE_PIN,
CONF_ID,
CONF_INPUT,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
@@ -92,14 +90,6 @@ CONFIG_SCHEMA = cv.All(
)
def _validate_pin_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output, not both")
return value
def _validate_pin(value: ConfigType) -> ConfigType:
if value[CONF_MODE][CONF_INPUT] and value[CONF_NUMBER] == 6:
raise cv.Invalid("GPIO6 cannot be used as input on the PCM5122")
@@ -111,7 +101,7 @@ PIN_SCHEMA = cv.All(
PCM5122GPIOPin,
cv.int_range(min=3, max=6),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=_validate_pin_mode,
mode_validator=pins.gpio_validate_input_xor_output,
).extend(
{
cv.Required(CONF_PCM5122): cv.use_id(PCM5122),
@@ -123,13 +113,7 @@ PIN_SCHEMA = cv.All(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_PCM5122, PIN_SCHEMA)
async def pcm5122_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_parented(var, config[CONF_PCM5122])
cg.add(var.set_pin(config[CONF_NUMBER]))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_PCM5122)
async def to_code(config: ConfigType) -> None:
+2 -19
View File
@@ -6,9 +6,6 @@ from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INTERRUPT_PIN,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
CONF_PULLDOWN,
CONF_PULLUP,
@@ -52,14 +49,6 @@ async def to_code(config: ConfigType) -> None:
await cg.add_pin(var.set_interrupt_pin, config.get(CONF_INTERRUPT_PIN))
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
return value
PI4IOE5V6408_PIN_SCHEMA = pins.gpio_base_schema(
PI4IOE5V6408GPIOPin,
cv.int_range(min=0, max=7),
@@ -69,7 +58,7 @@ PI4IOE5V6408_PIN_SCHEMA = pins.gpio_base_schema(
CONF_PULLUP,
CONF_PULLDOWN,
],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output,
).extend(
{
cv.Required(CONF_PI4IOE5V6408): pins.use_id_or_address(PI4IOE5V6408Component),
@@ -79,10 +68,4 @@ PI4IOE5V6408_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_PI4IOE5V6408, PI4IOE5V6408_PIN_SCHEMA)
async def pi4ioe5v6408_pin_schema(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_parented(var, config[CONF_PI4IOE5V6408])
cg.add(var.set_pin(config[CONF_NUMBER]))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_PI4IOE5V6408)
@@ -182,14 +182,6 @@ bool PI4IOE5V6408Component::digital_read_cache(uint8_t pin) { return (this->inpu
float PI4IOE5V6408Component::get_setup_priority() const { return setup_priority::IO; }
void PI4IOE5V6408GPIOPin::setup() { this->pin_mode(this->flags_); }
void PI4IOE5V6408GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool PI4IOE5V6408GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void PI4IOE5V6408GPIOPin::digital_write(bool value) {
this->parent_->digital_write(this->pin_, value != this->inverted_);
}
size_t PI4IOE5V6408GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via PI4IOE5V6408", this->pin_);
}
} // namespace esphome::pi4ioe5v6408
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::pi4ioe5v6408::PI4IOE5V6408Component, "%u via PI4IOE5V6408")
+4 -19
View File
@@ -1,6 +1,7 @@
#pragma once
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
@@ -49,24 +50,8 @@ class PI4IOE5V6408Component final : public Component,
bool read_gpio_outputs_();
};
class PI4IOE5V6408GPIOPin final : public GPIOPin, public Parented<PI4IOE5V6408Component> {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_pin(uint8_t pin) { this->pin_ = pin; }
void set_inverted(bool inverted) { this->inverted_ = inverted; }
void set_flags(gpio::Flags flags) { this->flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
using PI4IOE5V6408GPIOPin = gpio_expander::ExpanderGPIOPin<PI4IOE5V6408Component>;
} // namespace esphome::pi4ioe5v6408
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::pi4ioe5v6408::PI4IOE5V6408Component);
+8 -33
View File
@@ -4,11 +4,7 @@ from esphome.components import i2c, key_provider
from esphome.components.const import CONF_KEYS
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_ON_KEY,
CONF_OPEN_DRAIN,
CONF_OUTPUT,
@@ -113,12 +109,7 @@ async def to_code(config: ConfigType) -> None:
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
if value[CONF_PULLUP] and not value[CONF_INPUT]:
raise cv.Invalid("Pullup only available with input")
pins.gpio_validate_input_xor_output_pullup(value)
if value[CONF_PULLDOWN] and not value[CONF_INPUT]:
raise cv.Invalid("Pulldown only available with input")
if value[CONF_PULLUP] and value[CONF_PULLDOWN]:
@@ -129,34 +120,18 @@ def validate_mode(value: ConfigType) -> ConfigType:
CONF_SX1509 = "sx1509"
SX1509_PIN_SCHEMA = cv.All(
SX1509_PIN_SCHEMA = pins.gpio_base_schema(
SX1509GPIOPin,
cv.int_range(min=0, max=15),
modes=[CONF_INPUT, CONF_PULLUP, CONF_PULLDOWN, CONF_OUTPUT, CONF_OPEN_DRAIN],
mode_validator=validate_mode,
).extend(
{
cv.GenerateID(): cv.declare_id(SX1509GPIOPin),
cv.Required(CONF_SX1509): pins.use_id_or_address(SX1509Component),
cv.Required(CONF_NUMBER): cv.int_range(min=0, max=15),
cv.Optional(CONF_MODE, default={}): cv.All(
{
cv.Optional(CONF_INPUT, default=False): cv.boolean,
cv.Optional(CONF_PULLUP, default=False): cv.boolean,
cv.Optional(CONF_PULLDOWN, default=False): cv.boolean,
cv.Optional(CONF_OUTPUT, default=False): cv.boolean,
cv.Optional(CONF_OPEN_DRAIN, default=False): cv.boolean,
},
validate_mode,
),
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
}
)
@pins.PIN_SCHEMA_REGISTRY.register(CONF_SX1509, SX1509_PIN_SCHEMA)
async def sx1509_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_SX1509])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_SX1509)
+2
View File
@@ -312,3 +312,5 @@ void SX1509Component::set_debounce_keypad_(uint8_t time, uint8_t num_rows, uint8
}
} // namespace esphome::sx1509
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::sx1509::SX1509Component, "%u via sx1509")
+5 -1
View File
@@ -5,7 +5,7 @@
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "sx1509_gpio_pin.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "sx1509_registers.h"
#include <vector>
@@ -97,4 +97,8 @@ class SX1509Component final : public Component,
void clock_(uint8_t osc_source = 2, uint8_t osc_pin_function = 1, uint8_t osc_freq_out = 0, uint8_t osc_divider = 0);
};
using SX1509GPIOPin = gpio_expander::ExpanderGPIOPin<SX1509Component>;
} // namespace esphome::sx1509
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::sx1509::SX1509Component);
@@ -1,18 +0,0 @@
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "sx1509.h"
#include "sx1509_gpio_pin.h"
namespace esphome::sx1509 {
ESPHOME_LOG_TAG(TAG, "sx1509_gpio_pin");
void SX1509GPIOPin::setup() { pin_mode(flags_); }
void SX1509GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool SX1509GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void SX1509GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
size_t SX1509GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via sx1509", this->pin_);
}
} // namespace esphome::sx1509
@@ -1,31 +0,0 @@
#pragma once
#include "esphome/core/gpio.h"
namespace esphome::sx1509 {
class SX1509Component;
class SX1509GPIOPin final : public GPIOPin {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_parent(SX1509Component *parent) { this->parent_ = parent; }
void set_pin(uint8_t pin) { this->pin_ = pin; }
void set_inverted(bool inverted) { this->inverted_ = inverted; }
void set_flags(gpio::Flags flags) { this->flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
SX1509Component *parent_;
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
} // namespace esphome::sx1509
+3 -25
View File
@@ -2,15 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import gpio_expander, i2c
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INTERRUPT_PIN,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
)
from esphome.const import CONF_ID, CONF_INPUT, CONF_INTERRUPT_PIN, CONF_OUTPUT
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
@@ -44,19 +36,11 @@ async def to_code(config: ConfigType) -> None:
await cg.add_pin(var.set_interrupt_pin, config.get(CONF_INTERRUPT_PIN))
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
return value
TCA9555_PIN_SCHEMA = pins.gpio_base_schema(
TCA9555GPIOPin,
cv.int_range(min=0, max=15),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output,
invertible=True,
).extend(
{
@@ -67,10 +51,4 @@ TCA9555_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_TCA9555, TCA9555_PIN_SCHEMA)
async def tca9555_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
await cg.register_parented(var, config[CONF_TCA9555])
cg.add(var.set_pin(config[CONF_NUMBER]))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_TCA9555)
+2 -8
View File
@@ -129,12 +129,6 @@ bool TCA9555Component::digital_read_cache(uint8_t pin) { return this->input_mask
float TCA9555Component::get_setup_priority() const { return setup_priority::IO; }
void TCA9555GPIOPin::setup() { this->pin_mode(this->flags_); }
void TCA9555GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool TCA9555GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void TCA9555GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
size_t TCA9555GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via TCA9555", this->pin_);
}
} // namespace esphome::tca9555
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::tca9555::TCA9555Component, "%u via TCA9555")
+4 -20
View File
@@ -1,6 +1,7 @@
#pragma once
#include "esphome/components/gpio_expander/cached_gpio.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
@@ -46,25 +47,8 @@ class TCA9555Component final : public Component,
InternalGPIOPin *interrupt_pin_{nullptr};
};
/// Helper class to expose a TCA9555 pin as an internal input GPIO pin.
class TCA9555GPIOPin final : public GPIOPin, public Parented<TCA9555Component> {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_pin(uint8_t pin) { this->pin_ = pin; }
void set_inverted(bool inverted) { this->inverted_ = inverted; }
void set_flags(gpio::Flags flags) { this->flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
using TCA9555GPIOPin = gpio_expander::ExpanderGPIOPin<TCA9555Component>;
} // namespace esphome::tca9555
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::tca9555::TCA9555Component);
@@ -2,14 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
)
from esphome.const import CONF_ID, CONF_INPUT, CONF_OUTPUT
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
@@ -48,19 +41,11 @@ async def to_code(config: ConfigType) -> None:
await i2c.new_i2c_component(config)
def validate_mode(value: ConfigType) -> ConfigType:
if not (value[CONF_INPUT] or value[CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_INPUT] and value[CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
return value
WAVESHARE_IO_PIN_SCHEMA = pins.gpio_base_schema(
WaveshareIOCH32V003GPIOPin,
cv.int_range(min=0, max=7),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=validate_mode,
mode_validator=pins.gpio_validate_input_xor_output,
invertible=True,
).extend(
{
@@ -73,13 +58,4 @@ WAVESHARE_IO_PIN_SCHEMA = pins.gpio_base_schema(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_WAVESHARE_IO_CH32V003, WAVESHARE_IO_PIN_SCHEMA)
async def waveshare_io_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_WAVESHARE_IO_CH32V003])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_WAVESHARE_IO_CH32V003)
@@ -124,16 +124,6 @@ void WaveshareIOCH32V003Component::digital_write_hw(uint8_t pin, bool value) {
bool WaveshareIOCH32V003Component::digital_read_cache(uint8_t pin) { return this->input_mask_ & (1 << pin); }
float WaveshareIOCH32V003Component::get_setup_priority() const { return setup_priority::IO; }
void WaveshareIOCH32V003GPIOPin::setup() { this->pin_mode(this->flags_); }
void WaveshareIOCH32V003GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool WaveshareIOCH32V003GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) ^ this->inverted_; }
void WaveshareIOCH32V003GPIOPin::digital_write(bool value) {
this->parent_->digital_write(this->pin_, value ^ this->inverted_);
}
size_t WaveshareIOCH32V003GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "EXIO%u via WaveshareIO", this->pin_);
}
} // namespace esphome::waveshare_io_ch32v003
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::waveshare_io_ch32v003::WaveshareIOCH32V003Component, "EXIO%u via WaveshareIO")
@@ -4,6 +4,7 @@
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/component.h"
#include "esphome/core/hal.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
namespace esphome::waveshare_io_ch32v003 {
@@ -27,8 +28,6 @@ class WaveshareIOCH32V003Component : public Component,
void set_pwm_value(uint8_t value); // 0 - 255
protected:
friend class WaveshareIOCH32V003GPIOPin;
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;
@@ -41,25 +40,8 @@ class WaveshareIOCH32V003Component : public Component,
bool write_gpio_outputs_();
};
/// Helper class to expose a WaveshareIO pin as a GPIO pin.
class WaveshareIOCH32V003GPIOPin : public GPIOPin, public Parented<WaveshareIOCH32V003Component> {
public:
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
size_t dump_summary(char *buffer, size_t len) const override;
void set_pin(uint8_t pin) { this->pin_ = pin; }
void set_inverted(bool inverted) { this->inverted_ = inverted; }
void set_flags(gpio::Flags flags) { this->flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
protected:
uint8_t pin_{};
bool inverted_{};
gpio::Flags flags_{};
};
using WaveshareIOCH32V003GPIOPin = gpio_expander::ExpanderGPIOPin<WaveshareIOCH32V003Component>;
} // namespace esphome::waveshare_io_ch32v003
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::waveshare_io_ch32v003::WaveshareIOCH32V003Component);
+2 -4
View File
@@ -1,3 +1,4 @@
from esphome import pins
import esphome.codegen as cg
from esphome.components import uart
from esphome.components.const import CONF_DATA_BITS, CONF_PARITY, CONF_STOP_BITS
@@ -90,10 +91,7 @@ async def register_weikai(var: MockObj, config: ConfigType) -> None:
def validate_pin_mode(value: ConfigType) -> ConfigType:
"""Checks input/output mode inconsistency"""
if not (value[CONF_MODE][CONF_INPUT] or value[CONF_MODE][CONF_OUTPUT]):
raise cv.Invalid("Mode must be either input or output")
if value[CONF_MODE][CONF_INPUT] and value[CONF_MODE][CONF_OUTPUT]:
raise cv.Invalid("Mode must be either input or output")
pins.gpio_validate_input_xor_output(value[CONF_MODE])
return value
+2 -9
View File
@@ -2,7 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import i2c, weikai
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INVERTED, CONF_MODE, CONF_NUMBER
from esphome.const import CONF_ID
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
@@ -52,11 +52,4 @@ WK2168_PIN_SCHEMA = cv.All(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_WK2168_I2C, WK2168_PIN_SCHEMA)
async def sc16is75x_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_WK2168_I2C])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_WK2168_I2C)
+2 -9
View File
@@ -2,7 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import spi, weikai
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INVERTED, CONF_MODE, CONF_NUMBER
from esphome.const import CONF_ID
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
@@ -50,11 +50,4 @@ WK2168_PIN_SCHEMA = cv.All(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_WK2168_SPI, WK2168_PIN_SCHEMA)
async def sc16is75x_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_WK2168_SPI])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_WK2168_SPI)
+2 -9
View File
@@ -2,7 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import i2c, weikai
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INVERTED, CONF_MODE, CONF_NUMBER
from esphome.const import CONF_ID
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
@@ -52,11 +52,4 @@ WK2212_PIN_SCHEMA = cv.All(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_WK2212_I2C, WK2212_PIN_SCHEMA)
async def sc16is75x_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_WK2212_I2C])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_WK2212_I2C)
+2 -9
View File
@@ -2,7 +2,7 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import spi, weikai
import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_INVERTED, CONF_MODE, CONF_NUMBER
from esphome.const import CONF_ID
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
@@ -50,11 +50,4 @@ WK2212_PIN_SCHEMA = cv.All(
@pins.PIN_SCHEMA_REGISTRY.register(CONF_WK2212_SPI, WK2212_PIN_SCHEMA)
async def sc16is75x_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_WK2212_SPI])
cg.add(var.set_parent(parent))
num = config[CONF_NUMBER]
cg.add(var.set_pin(num))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_WK2212_SPI)
+9 -36
View File
@@ -2,19 +2,13 @@ from esphome import pins
import esphome.codegen as cg
from esphome.components import i2c
import esphome.config_validation as cv
from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_INVERTED,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
)
from esphome.const import CONF_ID, CONF_INPUT, CONF_OUTPUT
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
CONF_XL9535 = "xl9535"
AUTO_LOAD = ["gpio_expander"]
DEPENDENCIES = ["i2c"]
CODEOWNERS = ["@mreditor97"]
DOMAIN = "xl9535"
@@ -36,45 +30,24 @@ async def to_code(config: ConfigType) -> None:
await i2c.new_i2c_component(config)
def validate_mode(mode: ConfigType) -> ConfigType:
if not (mode[CONF_INPUT] or mode[CONF_OUTPUT]) or (
mode[CONF_INPUT] and mode[CONF_OUTPUT]
):
raise cv.Invalid("Mode must be either a input or a output")
return mode
def validate_pin(pin: int) -> int:
if pin in (8, 9):
raise cv.Invalid(f"pin {pin} doesn't exist")
return pin
XL9535_PIN_SCHEMA = cv.All(
XL9535_PIN_SCHEMA = pins.gpio_base_schema(
XL9535GPIOPin,
cv.All(cv.int_range(min=0, max=17), validate_pin),
modes=[CONF_INPUT, CONF_OUTPUT],
mode_validator=pins.gpio_validate_input_xor_output,
).extend(
{
cv.GenerateID(): cv.declare_id(XL9535GPIOPin),
cv.Required(CONF_XL9535): pins.use_id_or_address(XL9535Component),
cv.Required(CONF_NUMBER): cv.All(cv.int_range(min=0, max=17), validate_pin),
cv.Optional(CONF_MODE, default={}): cv.All(
{
cv.Optional(CONF_INPUT, default=False): cv.boolean,
cv.Optional(CONF_OUTPUT, default=False): cv.boolean,
},
validate_mode,
),
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
}
)
@pins.PIN_SCHEMA_REGISTRY.register(CONF_XL9535, XL9535_PIN_SCHEMA)
async def xl9535_pin_to_code(config: ConfigType) -> MockObj:
var = cg.new_Pvariable(config[CONF_ID])
parent = await cg.get_variable(config[CONF_XL9535])
cg.add(var.set_parent(parent))
cg.add(var.set_pin(config[CONF_NUMBER]))
cg.add(var.set_inverted(config[CONF_INVERTED]))
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
return var
return await pins.new_parented_pin(config, CONF_XL9535)
+2 -10
View File
@@ -103,14 +103,6 @@ void XL9535Component::pin_mode(uint8_t pin, gpio::Flags mode) {
}
}
void XL9535GPIOPin::setup() { this->pin_mode(this->flags_); }
size_t XL9535GPIOPin::dump_summary(char *buffer, size_t len) const {
return buf_append_printf(buffer, len, 0, "%u via XL9535", this->pin_);
}
void XL9535GPIOPin::pin_mode(gpio::Flags flags) { this->parent_->pin_mode(this->pin_, flags); }
bool XL9535GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
void XL9535GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
} // namespace esphome::xl9535
ESPHOME_EXPANDER_PIN_SUMMARY(esphome::xl9535::XL9535Component, "%u via XL9535")
+4 -22
View File
@@ -3,6 +3,7 @@
#include "esphome/core/component.h"
#include "esphome/components/i2c/i2c.h"
#include "esphome/core/hal.h"
#include "esphome/components/gpio_expander/expander_gpio_pin.h"
namespace esphome::xl9535 {
@@ -28,27 +29,8 @@ class XL9535Component final : public Component, public i2c::I2CDevice {
float get_setup_priority() const override { return setup_priority::IO; }
};
class XL9535GPIOPin final : public GPIOPin {
public:
void set_parent(XL9535Component *parent) { this->parent_ = parent; }
void set_pin(uint8_t pin) { this->pin_ = pin; }
void set_inverted(bool inverted) { this->inverted_ = inverted; }
void set_flags(gpio::Flags flags) { this->flags_ = flags; }
gpio::Flags get_flags() const override { return this->flags_; }
void setup() override;
size_t dump_summary(char *buffer, size_t len) const override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
protected:
XL9535Component *parent_;
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
};
using XL9535GPIOPin = gpio_expander::ExpanderGPIOPin<XL9535Component>;
} // namespace esphome::xl9535
ESPHOME_EXPANDER_PIN_SUMMARY_DECL(esphome::xl9535::XL9535Component);
+2 -4
View File
@@ -50,10 +50,8 @@ class PCF8574ResetTest : public ::testing::TestWithParam<bool> {
}
void configure_input_(uint8_t number) {
PCF8574GPIOPin pin;
pin.set_parent(&this->component_);
pin.set_pin(number);
pin.set_flags(gpio::FLAG_INPUT);
// Codegen registers input pins with the parent before setup()
this->component_.register_input_pin(number);
EXPECT_EQ(this->bus_.writes, 0);
EXPECT_EQ(this->bus_.reads, 0);
}
+38 -1
View File
@@ -5,7 +5,14 @@ from unittest.mock import AsyncMock, Mock, patch
import pytest
from esphome.components import pcf8574
from esphome.const import CONF_ID, CONF_RESET
from esphome.const import (
CONF_ID,
CONF_INPUT,
CONF_MODE,
CONF_NUMBER,
CONF_OUTPUT,
CONF_RESET,
)
@pytest.mark.asyncio
@@ -31,3 +38,33 @@ async def test_reset_configuration(options: dict, expected: bool) -> None:
var.set_reset.assert_not_called()
else:
var.set_reset.assert_called_once_with(False)
@pytest.mark.asyncio
@pytest.mark.parametrize(
"number, is_input",
[
(0, True),
(15, True),
(0, False),
(15, False),
],
)
async def test_pin_registers_inputs_only(number: int, is_input: bool) -> None:
config = {
CONF_NUMBER: number,
CONF_MODE: {CONF_INPUT: is_input, CONF_OUTPUT: not is_input},
pcf8574.CONF_PCF8574: "hub",
}
parent = Mock()
with (
patch.object(pcf8574.pins, "new_parented_pin", new_callable=AsyncMock),
patch.object(pcf8574.cg, "get_variable", AsyncMock(return_value=parent)),
patch.object(pcf8574.cg, "add"),
):
await pcf8574.pcf8574_pin_to_code(config)
if is_input:
parent.register_input_pin.assert_called_once_with(number)
else:
parent.register_input_pin.assert_not_called()