bit bang the "i2c" protocol
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
# SM2235 LED driver
|
||||
|
||||
Requires a configured i2c bus
|
||||
|
||||
Example:
|
||||
```yaml
|
||||
sm2235:
|
||||
- id: my_sm #optional
|
||||
sda: 4
|
||||
scl: 5
|
||||
rgb_current: 12 #optional
|
||||
cw_current: 25 #optional
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c
|
||||
from esphome.const import CONF_ID, CONF_NUM_CHANNELS
|
||||
from esphome import pins
|
||||
from esphome.const import CONF_ID, CONF_NUM_CHANNELS, CONF_SCL, CONF_SDA
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
MULTI_CONF = True
|
||||
|
||||
sm2235_ns = cg.esphome_ns.namespace("sm2235")
|
||||
SM2235 = sm2235_ns.class_("SM2235", cg.Component, i2c.I2CDevice)
|
||||
SM2235 = sm2235_ns.class_("SM2235", cg.Component)
|
||||
|
||||
CONF_RGB_CURRENT = "rgb_current"
|
||||
CONF_CW_CURRENT = "cw_current"
|
||||
@@ -16,19 +15,23 @@ CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(SM2235),
|
||||
cv.Required(CONF_SDA): pins.internal_gpio_input_pin_schema,
|
||||
cv.Required(CONF_SCL): pins.internal_gpio_input_pin_schema,
|
||||
cv.Optional(CONF_RGB_CURRENT, default=12): cv.int_range(min=4, max=64),
|
||||
cv.Optional(CONF_CW_CURRENT, default=25): cv.int_range(min=5, max=80),
|
||||
}
|
||||
)
|
||||
.extend(cv.COMPONENT_SCHEMA)
|
||||
.extend(i2c.i2c_device_schema(0))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
|
||||
pin = await cg.gpio_pin_expression(config[CONF_SDA])
|
||||
cg.add(var.set_sda_pin(pin))
|
||||
pin = await cg.gpio_pin_expression(config[CONF_SCL])
|
||||
cg.add(var.set_scl_pin(pin))
|
||||
currents = round((config[CONF_RGB_CURRENT] - 4) / 4) * 16 + round((config[CONF_CW_CURRENT] - 5) / 5)
|
||||
cg.add(var.set_currents(currents))
|
||||
|
||||
@@ -1,18 +1,44 @@
|
||||
#include "sm2235.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/hal.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sm2235 {
|
||||
|
||||
static const char *const TAG = "sm2235";
|
||||
|
||||
void SM2235::setup() {
|
||||
this->sda_pin_->setup();
|
||||
this->scl_pin_->setup();
|
||||
this->scl_pin_->digital_write(true);
|
||||
this->sda_pin_->digital_write(true);
|
||||
}
|
||||
|
||||
void SM2235::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "SM2235:");
|
||||
ESP_LOGCONFIG(TAG, " Channels: %d", this->num_channels_);
|
||||
}
|
||||
|
||||
void SM2235::start_() {
|
||||
this->sda_pin_->digital_write(false);
|
||||
delayMicroseconds(4);
|
||||
}
|
||||
|
||||
void SM2235::stop_() {
|
||||
this->sda_pin_->digital_write(true);
|
||||
delayMicroseconds(2);
|
||||
}
|
||||
|
||||
void SM2235::send_byte_(uint8_t value) {
|
||||
for (int i = 0; i < 9; i++, value <<= 1) {
|
||||
this->scl_pin_->digital_write(false);
|
||||
this->sda_pin_->digital_write(value & 0x80 > 0);
|
||||
delayMicroseconds(2);
|
||||
this->scl_pin_->digital_write(true);
|
||||
delayMicroseconds(2);
|
||||
}
|
||||
}
|
||||
|
||||
void SM2235::update_(uint8_t channel) {
|
||||
uint8_t byte0 = 0xc0 + channel;
|
||||
switch(this->num_channels_) {
|
||||
@@ -27,12 +53,13 @@ void SM2235::update_(uint8_t channel) {
|
||||
case 5:
|
||||
byte0 |= 0x30; break;
|
||||
}
|
||||
uint8_t data[3];
|
||||
data[0] = this->currents_;
|
||||
this->start_();
|
||||
this->send_byte_(byte0);
|
||||
this->send_byte_(this->currents_);
|
||||
uint16_t value = this->values_[channel];
|
||||
data[1] = value >> 8;
|
||||
data[2] = value & 0xff;
|
||||
this->bus_->write(byte0, data, 3);
|
||||
this->send_byte_(value >> 8);
|
||||
this->send_byte_(value & 0xff);
|
||||
this->stop_();
|
||||
}
|
||||
|
||||
void SM2235::register_channel(SM2235Channel *channel, uint8_t num) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/components/output/float_output.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sm2235 {
|
||||
@@ -21,10 +21,13 @@ class SM2235Channel : public output::FloatOutput {
|
||||
SM2235 *parent_;
|
||||
};
|
||||
|
||||
class SM2235 : public Component, public i2c::I2CDevice {
|
||||
class SM2235 : public Component {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
void set_sda_pin(InternalGPIOPin *pin) { this->sda_pin_ = pin; }
|
||||
void set_scl_pin(InternalGPIOPin *pin) { this->scl_pin_ = pin; }
|
||||
|
||||
void register_channel(SM2235Channel *channel, uint8_t num);
|
||||
void set_currents(uint8_t currents) { this->currents_ = currents; }
|
||||
@@ -35,7 +38,12 @@ class SM2235 : public Component, public i2c::I2CDevice {
|
||||
uint8_t currents_;
|
||||
uint8_t num_channels_{0};
|
||||
uint16_t values_[5] = {0};
|
||||
InternalGPIOPin *sda_pin_;
|
||||
InternalGPIOPin *scl_pin_;
|
||||
|
||||
void start_();
|
||||
void stop_();
|
||||
void send_byte_(uint8_t value);
|
||||
void update_(uint8_t channel);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user