Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add support for mcp23008 8-port io expander * add-mcp23008-support * Revert "add-mcp23008-support" This reverts commit b4bc778. * Fixed spacing typo * removed extra space in mcp23008.cpp, line 23 * Fixed trailing whitespace issue * Added mcp23008 component * Added component mcp23008 * Edited typo in test/test1.ymal Removed additional ' in line 1337 * Another typo
- Loading branch information
1 parent
4573670
commit 81b7653
Showing
5 changed files
with
244 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import esphome.codegen as cg | ||
import esphome.config_validation as cv | ||
from esphome import pins | ||
from esphome.components import i2c | ||
from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED | ||
|
||
DEPENDENCIES = ['i2c'] | ||
MULTI_CONF = True | ||
|
||
mcp23008_ns = cg.esphome_ns.namespace('mcp23008') | ||
MCP23008GPIOMode = mcp23008_ns.enum('MCP23008GPIOMode') | ||
MCP23008_GPIO_MODES = { | ||
'INPUT': MCP23008GPIOMode.MCP23008_INPUT, | ||
'INPUT_PULLUP': MCP23008GPIOMode.MCP23008_INPUT_PULLUP, | ||
'OUTPUT': MCP23008GPIOMode.MCP23008_OUTPUT, | ||
} | ||
|
||
MCP23008 = mcp23008_ns.class_('MCP23008', cg.Component, i2c.I2CDevice) | ||
MCP23008GPIOPin = mcp23008_ns.class_('MCP23008GPIOPin', cg.GPIOPin) | ||
|
||
CONFIG_SCHEMA = cv.Schema({ | ||
cv.Required(CONF_ID): cv.declare_id(MCP23008), | ||
}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x20)) | ||
|
||
|
||
def to_code(config): | ||
var = cg.new_Pvariable(config[CONF_ID]) | ||
yield cg.register_component(var, config) | ||
yield i2c.register_i2c_device(var, config) | ||
|
||
|
||
CONF_MCP23008 = 'mcp23008' | ||
MCP23008_OUTPUT_PIN_SCHEMA = cv.Schema({ | ||
cv.Required(CONF_MCP23008): cv.use_id(MCP23008), | ||
cv.Required(CONF_NUMBER): cv.int_, | ||
cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(MCP23008_GPIO_MODES, upper=True), | ||
cv.Optional(CONF_INVERTED, default=False): cv.boolean, | ||
}) | ||
MCP23008_INPUT_PIN_SCHEMA = cv.Schema({ | ||
cv.Required(CONF_MCP23008): cv.use_id(MCP23008), | ||
cv.Required(CONF_NUMBER): cv.int_, | ||
cv.Optional(CONF_MODE, default="INPUT"): cv.enum(MCP23008_GPIO_MODES, upper=True), | ||
cv.Optional(CONF_INVERTED, default=False): cv.boolean, | ||
}) | ||
|
||
|
||
@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23008, | ||
(MCP23008_OUTPUT_PIN_SCHEMA, MCP23008_INPUT_PIN_SCHEMA)) | ||
def mcp23008_pin_to_code(config): | ||
parent = yield cg.get_variable(config[CONF_MCP23008]) | ||
yield MCP23008GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
#include "mcp23008.h" | ||
#include "esphome/core/log.h" | ||
|
||
namespace esphome { | ||
namespace mcp23008 { | ||
|
||
static const char *TAG = "mcp23008"; | ||
|
||
void MCP23008::setup() { | ||
ESP_LOGCONFIG(TAG, "Setting up MCP23008..."); | ||
uint8_t iocon; | ||
if (!this->read_reg_(MCP23008_IOCON, &iocon)) { | ||
this->mark_failed(); | ||
return; | ||
} | ||
|
||
// all pins input | ||
this->write_reg_(MCP23008_IODIR, 0xFF); | ||
} | ||
bool MCP23008::digital_read(uint8_t pin) { | ||
uint8_t bit = pin % 8; | ||
uint8_t reg_addr = MCP23008_GPIO; | ||
uint8_t value = 0; | ||
this->read_reg_(reg_addr, &value); | ||
return value & (1 << bit); | ||
} | ||
void MCP23008::digital_write(uint8_t pin, bool value) { | ||
uint8_t reg_addr = MCP23008_OLAT; | ||
this->update_reg_(pin, value, reg_addr); | ||
} | ||
void MCP23008::pin_mode(uint8_t pin, uint8_t mode) { | ||
uint8_t iodir = MCP23008_IODIR; | ||
uint8_t gppu = MCP23008_GPPU; | ||
switch (mode) { | ||
case MCP23008_INPUT: | ||
this->update_reg_(pin, true, iodir); | ||
break; | ||
case MCP23008_INPUT_PULLUP: | ||
this->update_reg_(pin, true, iodir); | ||
this->update_reg_(pin, true, gppu); | ||
break; | ||
case MCP23008_OUTPUT: | ||
this->update_reg_(pin, false, iodir); | ||
break; | ||
default: | ||
break; | ||
} | ||
} | ||
float MCP23008::get_setup_priority() const { return setup_priority::HARDWARE; } | ||
bool MCP23008::read_reg_(uint8_t reg, uint8_t *value) { | ||
if (this->is_failed()) | ||
return false; | ||
|
||
return this->read_byte(reg, value); | ||
} | ||
bool MCP23008::write_reg_(uint8_t reg, uint8_t value) { | ||
if (this->is_failed()) | ||
return false; | ||
|
||
return this->write_byte(reg, value); | ||
} | ||
void MCP23008::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 == MCP23008_OLAT) { | ||
reg_value = this->olat_; | ||
} 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 == MCP23008_OLAT) { | ||
this->olat_ = reg_value; | ||
} | ||
} | ||
|
||
MCP23008GPIOPin::MCP23008GPIOPin(MCP23008 *parent, uint8_t pin, uint8_t mode, bool inverted) | ||
: GPIOPin(pin, mode, inverted), parent_(parent) {} | ||
void MCP23008GPIOPin::setup() { this->pin_mode(this->mode_); } | ||
void MCP23008GPIOPin::pin_mode(uint8_t mode) { this->parent_->pin_mode(this->pin_, mode); } | ||
bool MCP23008GPIOPin::digital_read() { return this->parent_->digital_read(this->pin_) != this->inverted_; } | ||
void MCP23008GPIOPin::digital_write(bool value) { this->parent_->digital_write(this->pin_, value != this->inverted_); } | ||
|
||
} // namespace mcp23008 | ||
} // namespace esphome |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#pragma once | ||
|
||
#include "esphome/core/component.h" | ||
#include "esphome/core/esphal.h" | ||
#include "esphome/components/i2c/i2c.h" | ||
|
||
namespace esphome { | ||
namespace mcp23008 { | ||
|
||
/// Modes for MCP23008 pins | ||
enum MCP23008GPIOMode : uint8_t { | ||
MCP23008_INPUT = INPUT, // 0x00 | ||
MCP23008_INPUT_PULLUP = INPUT_PULLUP, // 0x02 | ||
MCP23008_OUTPUT = OUTPUT // 0x01 | ||
}; | ||
|
||
enum MCP23008GPIORegisters { | ||
// A side | ||
MCP23008_IODIR = 0x00, | ||
MCP23008_IPOL = 0x01, | ||
MCP23008_GPINTEN = 0x02, | ||
MCP23008_DEFVAL = 0x03, | ||
MCP23008_INTCON = 0x04, | ||
MCP23008_IOCON = 0x05, | ||
MCP23008_GPPU = 0x06, | ||
MCP23008_INTF = 0x07, | ||
MCP23008_INTCAP = 0x08, | ||
MCP23008_GPIO = 0x09, | ||
MCP23008_OLAT = 0x0A, | ||
}; | ||
|
||
class MCP23008 : public Component, public i2c::I2CDevice { | ||
public: | ||
MCP23008() = default; | ||
|
||
void setup() override; | ||
|
||
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; | ||
|
||
protected: | ||
// 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); | ||
|
||
uint8_t olat_{0x00}; | ||
}; | ||
|
||
class MCP23008GPIOPin : public GPIOPin { | ||
public: | ||
MCP23008GPIOPin(MCP23008 *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: | ||
MCP23008 *parent_; | ||
}; | ||
|
||
} // namespace mcp23008 | ||
} // namespace esphome |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters