mirror of
https://github.com/esphome/esphome.git
synced 2025-10-02 01:52:21 +01:00
MCP23XXX Refactor (#1560)
* Refactor MCP23XXX classes to consolidate shared code * Update test mcp23xxx pin schemas
This commit is contained in:
@@ -1,26 +1,18 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import spi
|
||||
from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED
|
||||
|
||||
CODEOWNERS = ["@SenexCrenshaw"]
|
||||
from esphome.components import spi, mcp23x17_base, mcp23xxx_base
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
AUTO_LOAD = ["mcp23x17_base"]
|
||||
CODEOWNERS = ["@SenexCrenshaw", "@jesserockz"]
|
||||
DEPENDENCIES = ["spi"]
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_DEVICEADDRESS = "deviceaddress"
|
||||
|
||||
mcp23S17_ns = cg.esphome_ns.namespace("mcp23s17")
|
||||
mcp23S17GPIOMode = mcp23S17_ns.enum("MCP23S17GPIOMode")
|
||||
mcp23S17_GPIO_MODES = {
|
||||
"INPUT": mcp23S17GPIOMode.MCP23S17_INPUT,
|
||||
"INPUT_PULLUP": mcp23S17GPIOMode.MCP23S17_INPUT_PULLUP,
|
||||
"OUTPUT": mcp23S17GPIOMode.MCP23S17_OUTPUT,
|
||||
}
|
||||
|
||||
mcp23S17 = mcp23S17_ns.class_("MCP23S17", cg.Component, spi.SPIDevice)
|
||||
mcp23S17GPIOPin = mcp23S17_ns.class_("MCP23S17GPIOPin", cg.GPIOPin)
|
||||
mcp23S17 = mcp23S17_ns.class_("MCP23S17", mcp23x17_base.MCP23X17Base, spi.SPIDevice)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
@@ -29,47 +21,12 @@ CONFIG_SCHEMA = (
|
||||
cv.Optional(CONF_DEVICEADDRESS, default=0): cv.uint8_t,
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(mcp23xxx_base.MCP23XXX_CONFIG_SCHEMA)
|
||||
.extend(spi.spi_device_schema())
|
||||
)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
var = yield mcp23xxx_base.register_mcp23xxx(config)
|
||||
cg.add(var.set_device_address(config[CONF_DEVICEADDRESS]))
|
||||
yield cg.register_component(var, config)
|
||||
yield spi.register_spi_device(var, config)
|
||||
|
||||
|
||||
CONF_MCP23S17 = "mcp23s17"
|
||||
|
||||
mcp23S17_OUTPUT_PIN_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_MCP23S17): cv.use_id(mcp23S17),
|
||||
cv.Required(CONF_NUMBER): cv.int_,
|
||||
cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(
|
||||
mcp23S17_GPIO_MODES, upper=True
|
||||
),
|
||||
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
mcp23S17_INPUT_PIN_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_MCP23S17): cv.use_id(mcp23S17),
|
||||
cv.Required(CONF_NUMBER): cv.int_range(0, 15),
|
||||
cv.Optional(CONF_MODE, default="INPUT"): cv.enum(
|
||||
mcp23S17_GPIO_MODES, upper=True
|
||||
),
|
||||
cv.Optional(CONF_INVERTED, default=False): cv.boolean,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@pins.PIN_SCHEMA_REGISTRY.register(
|
||||
CONF_MCP23S17, (mcp23S17_OUTPUT_PIN_SCHEMA, mcp23S17_INPUT_PIN_SCHEMA)
|
||||
)
|
||||
def mcp23S17_pin_to_code(config):
|
||||
parent = yield cg.get_variable(config[CONF_MCP23S17])
|
||||
yield mcp23S17GPIOPin.new(
|
||||
parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED]
|
||||
)
|
||||
|
@@ -19,17 +19,15 @@ void MCP23S17::setup() {
|
||||
this->enable();
|
||||
uint8_t cmd = 0b01000000;
|
||||
this->transfer_byte(cmd);
|
||||
this->transfer_byte(0x18);
|
||||
this->transfer_byte(0x0A);
|
||||
this->transfer_byte(this->device_opcode_);
|
||||
this->transfer_byte(0);
|
||||
this->transfer_byte(0xFF);
|
||||
this->transfer_byte(0xFF);
|
||||
|
||||
for (uint8_t i = 0; i < 20; i++) {
|
||||
this->transfer_byte(0);
|
||||
}
|
||||
this->transfer_byte(mcp23x17_base::MCP23X17_IOCONA);
|
||||
this->transfer_byte(0b00011000); // Enable HAEN pins for addressing
|
||||
this->disable();
|
||||
|
||||
if (this->open_drain_ints_) {
|
||||
// enable open-drain interrupt pins, 3.3V-safe
|
||||
this->write_reg(mcp23x17_base::MCP23X17_IOCONA, 0x04);
|
||||
this->write_reg(mcp23x17_base::MCP23X17_IOCONB, 0x04);
|
||||
}
|
||||
}
|
||||
|
||||
void MCP23S17::dump_config() {
|
||||
@@ -37,65 +35,6 @@ void MCP23S17::dump_config() {
|
||||
LOG_PIN(" CS Pin: ", this->cs_);
|
||||
}
|
||||
|
||||
float MCP23S17::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
|
||||
bool MCP23S17::digital_read(uint8_t pin) {
|
||||
uint8_t bit = pin % 8;
|
||||
uint8_t reg_addr = pin < 8 ? MCP23S17_GPIOA : MCP23S17_GPIOB;
|
||||
uint8_t value = 0;
|
||||
this->read_reg(reg_addr, &value);
|
||||
return value & (1 << bit);
|
||||
}
|
||||
|
||||
void MCP23S17::digital_write(uint8_t pin, bool value) {
|
||||
uint8_t reg_addr = pin < 8 ? MCP23S17_OLATA : MCP23S17_OLATB;
|
||||
this->update_reg(pin, value, reg_addr);
|
||||
}
|
||||
|
||||
void MCP23S17::pin_mode(uint8_t pin, uint8_t mode) {
|
||||
uint8_t iodir = pin < 8 ? MCP23S17_IODIRA : MCP23S17_IODIRB;
|
||||
uint8_t gppu = pin < 8 ? MCP23S17_GPPUA : MCP23S17_GPPUB;
|
||||
switch (mode) {
|
||||
case MCP23S17_INPUT:
|
||||
this->update_reg(pin, true, iodir);
|
||||
break;
|
||||
case MCP23S17_INPUT_PULLUP:
|
||||
this->update_reg(pin, true, iodir);
|
||||
this->update_reg(pin, true, gppu);
|
||||
break;
|
||||
case MCP23S17_OUTPUT:
|
||||
this->update_reg(pin, false, iodir);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MCP23S17::update_reg(uint8_t pin, bool pin_value, uint8_t reg_addr) {
|
||||
uint8_t bit = pin % 8;
|
||||
uint8_t reg_value = 0;
|
||||
if (reg_addr == MCP23S17_OLATA) {
|
||||
reg_value = this->olat_a_;
|
||||
} else if (reg_addr == MCP23S17_OLATB) {
|
||||
reg_value = this->olat_b_;
|
||||
} else {
|
||||
this->read_reg(reg_addr, ®_value);
|
||||
}
|
||||
|
||||
if (pin_value)
|
||||
reg_value |= 1 << bit;
|
||||
else
|
||||
reg_value &= ~(1 << bit);
|
||||
|
||||
this->write_reg(reg_addr, reg_value);
|
||||
|
||||
if (reg_addr == MCP23S17_OLATA) {
|
||||
this->olat_a_ = reg_value;
|
||||
} else if (reg_addr == MCP23S17_OLATB) {
|
||||
this->olat_b_ = reg_value;
|
||||
}
|
||||
}
|
||||
|
||||
bool MCP23S17::read_reg(uint8_t reg, uint8_t *value) {
|
||||
this->enable();
|
||||
this->transfer_byte(this->device_opcode_ | 1);
|
||||
@@ -115,12 +54,5 @@ bool MCP23S17::write_reg(uint8_t reg, uint8_t value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
MCP23S17GPIOPin::MCP23S17GPIOPin(MCP23S17 *parent, uint8_t pin, uint8_t mode, bool inverted)
|
||||
: GPIOPin(pin, mode, inverted), parent_(parent) {}
|
||||
void MCP23S17GPIOPin::setup() { this->pin_mode(this->mode_); }
|
||||
void MCP23S17GPIOPin::pin_mode(uint8_t mode) { this->parent_->pin_mode(this->pin_, mode); }
|
||||
bool MCP23S17GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; }
|
||||
void MCP23S17GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); }
|
||||
|
||||
} // namespace mcp23s17
|
||||
} // namespace esphome
|
||||
|
@@ -1,47 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/mcp23x17_base/mcp23x17_base.h"
|
||||
#include "esphome/core/esphal.h"
|
||||
#include "esphome/components/spi/spi.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace mcp23s17 {
|
||||
|
||||
/// Modes for MCP23S17 pins
|
||||
enum MCP23S17GPIOMode : uint8_t {
|
||||
MCP23S17_INPUT = INPUT, // 0x00
|
||||
MCP23S17_INPUT_PULLUP = INPUT_PULLUP, // 0x02
|
||||
MCP23S17_OUTPUT = OUTPUT // 0x01
|
||||
};
|
||||
|
||||
enum MCP23S17GPIORegisters {
|
||||
// A side
|
||||
MCP23S17_IODIRA = 0x00,
|
||||
MCP23S17_IPOLA = 0x02,
|
||||
MCP23S17_GPINTENA = 0x04,
|
||||
MCP23S17_DEFVALA = 0x06,
|
||||
MCP23S17_INTCONA = 0x08,
|
||||
MCP23S17_IOCONA = 0x0A,
|
||||
MCP23S17_GPPUA = 0x0C,
|
||||
MCP23S17_INTFA = 0x0E,
|
||||
MCP23S17_INTCAPA = 0x10,
|
||||
MCP23S17_GPIOA = 0x12,
|
||||
MCP23S17_OLATA = 0x14,
|
||||
// B side
|
||||
MCP23S17_IODIRB = 0x01,
|
||||
MCP23S17_IPOLB = 0x03,
|
||||
MCP23S17_GPINTENB = 0x05,
|
||||
MCP23S17_DEFVALB = 0x07,
|
||||
MCP23S17_INTCONB = 0x09,
|
||||
MCP23S17_IOCONB = 0x0B,
|
||||
MCP23S17_GPPUB = 0x0D,
|
||||
MCP23S17_INTFB = 0x0F,
|
||||
MCP23S17_INTCAPB = 0x11,
|
||||
MCP23S17_GPIOB = 0x13,
|
||||
MCP23S17_OLATB = 0x15,
|
||||
};
|
||||
|
||||
class MCP23S17 : public Component,
|
||||
class MCP23S17 : public mcp23x17_base::MCP23X17Base,
|
||||
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
|
||||
spi::DATA_RATE_8MHZ> {
|
||||
public:
|
||||
@@ -51,36 +18,11 @@ class MCP23S17 : public Component,
|
||||
void dump_config() override;
|
||||
void set_device_address(uint8_t device_addr);
|
||||
|
||||
bool digital_read(uint8_t pin);
|
||||
void digital_write(uint8_t pin, bool value);
|
||||
void pin_mode(uint8_t pin, uint8_t mode);
|
||||
|
||||
float get_setup_priority() const override;
|
||||
|
||||
// read a given register
|
||||
bool read_reg(uint8_t reg, uint8_t *value);
|
||||
// write a value to a given register
|
||||
bool write_reg(uint8_t reg, uint8_t value);
|
||||
// update registers with given pin value.
|
||||
void update_reg(uint8_t pin, bool pin_value, uint8_t reg_a);
|
||||
|
||||
protected:
|
||||
bool read_reg(uint8_t reg, uint8_t *value) override;
|
||||
bool write_reg(uint8_t reg, uint8_t value) override;
|
||||
|
||||
uint8_t device_opcode_ = 0x40;
|
||||
uint8_t olat_a_{0x00};
|
||||
uint8_t olat_b_{0x00};
|
||||
};
|
||||
|
||||
class MCP23S17GPIOPin : public GPIOPin {
|
||||
public:
|
||||
MCP23S17GPIOPin(MCP23S17 *parent, uint8_t pin, uint8_t mode, bool inverted = false);
|
||||
|
||||
void setup() override;
|
||||
void pin_mode(uint8_t mode) override;
|
||||
bool digital_read() override;
|
||||
void digital_write(bool value) override;
|
||||
|
||||
protected:
|
||||
MCP23S17 *parent_;
|
||||
};
|
||||
|
||||
} // namespace mcp23s17
|
||||
|
Reference in New Issue
Block a user