mirror of
https://github.com/esphome/esphome.git
synced 2024-11-22 23:18:10 +01:00
SM16716 support (#541)
This commit is contained in:
parent
d41ddf380c
commit
2617e5092b
4 changed files with 178 additions and 0 deletions
31
esphome/components/sm16716/__init__.py
Normal file
31
esphome/components/sm16716/__init__.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.const import (CONF_CLOCK_PIN, CONF_DATA_PIN, CONF_ID,
|
||||
CONF_NUM_CHANNELS, CONF_NUM_CHIPS)
|
||||
|
||||
AUTO_LOAD = ['output']
|
||||
sm16716_ns = cg.esphome_ns.namespace('sm16716')
|
||||
SM16716 = sm16716_ns.class_('SM16716', cg.Component)
|
||||
|
||||
MULTI_CONF = True
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.GenerateID(): cv.declare_id(SM16716),
|
||||
cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema,
|
||||
cv.Optional(CONF_NUM_CHANNELS, default=3): cv.int_range(min=3, max=255),
|
||||
cv.Optional(CONF_NUM_CHIPS, default=1): cv.int_range(min=1, max=85),
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield cg.register_component(var, config)
|
||||
|
||||
data = yield cg.gpio_pin_expression(config[CONF_DATA_PIN])
|
||||
cg.add(var.set_data_pin(data))
|
||||
clock = yield cg.gpio_pin_expression(config[CONF_CLOCK_PIN])
|
||||
cg.add(var.set_clock_pin(clock))
|
||||
|
||||
cg.add(var.set_num_channels(config[CONF_NUM_CHANNELS]))
|
||||
cg.add(var.set_num_chips(config[CONF_NUM_CHIPS]))
|
25
esphome/components/sm16716/output.py
Normal file
25
esphome/components/sm16716/output.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import output
|
||||
from esphome.const import CONF_CHANNEL, CONF_ID
|
||||
from . import SM16716
|
||||
|
||||
DEPENDENCIES = ['sm16716']
|
||||
|
||||
Channel = SM16716.class_('Channel', output.FloatOutput)
|
||||
|
||||
CONF_SM16716_ID = 'sm16716_id'
|
||||
CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({
|
||||
cv.GenerateID(CONF_SM16716_ID): cv.use_id(SM16716),
|
||||
cv.Required(CONF_ID): cv.declare_id(Channel),
|
||||
cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535),
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
yield output.register_output(var, config)
|
||||
|
||||
parent = yield cg.get_variable(config[CONF_SM16716_ID])
|
||||
cg.add(var.set_parent(parent))
|
||||
cg.add(var.set_channel(config[CONF_CHANNEL]))
|
52
esphome/components/sm16716/sm16716.cpp
Normal file
52
esphome/components/sm16716/sm16716.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#include "sm16716.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sm16716 {
|
||||
|
||||
static const char *TAG = "sm16716";
|
||||
|
||||
void SM16716::setup() {
|
||||
ESP_LOGCONFIG(TAG, "Setting up SM16716OutputComponent...");
|
||||
this->data_pin_->setup();
|
||||
this->data_pin_->digital_write(false);
|
||||
this->clock_pin_->setup();
|
||||
this->clock_pin_->digital_write(false);
|
||||
this->pwm_amounts_.resize(this->num_channels_, 0);
|
||||
}
|
||||
void SM16716::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "SM16716:");
|
||||
LOG_PIN(" Data Pin: ", this->data_pin_);
|
||||
LOG_PIN(" Clock Pin: ", this->clock_pin_);
|
||||
ESP_LOGCONFIG(TAG, " Total number of channels: %u", this->num_channels_);
|
||||
ESP_LOGCONFIG(TAG, " Number of chips: %u", this->num_chips_);
|
||||
}
|
||||
void SM16716::loop() {
|
||||
if (!this->update_)
|
||||
return;
|
||||
|
||||
for (uint8_t i = 0; i < 50; i++) {
|
||||
this->write_bit_(false);
|
||||
}
|
||||
|
||||
// send 25 bits (1 start bit plus 24 data bits) for each chip
|
||||
for (uint8_t index = 0; index < this->num_channels_; index++) {
|
||||
// send a start bit initially and after every 3 channels
|
||||
if (index % 3 == 0) {
|
||||
this->write_bit_(true);
|
||||
}
|
||||
|
||||
this->write_byte_(this->pwm_amounts_[index]);
|
||||
}
|
||||
|
||||
// send a blank 25 bits to signal the end
|
||||
this->write_bit_(false);
|
||||
this->write_byte_(0);
|
||||
this->write_byte_(0);
|
||||
this->write_byte_(0);
|
||||
|
||||
this->update_ = false;
|
||||
}
|
||||
|
||||
} // namespace sm16716
|
||||
} // namespace esphome
|
70
esphome/components/sm16716/sm16716.h
Normal file
70
esphome/components/sm16716/sm16716.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/output/float_output.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace sm16716 {
|
||||
|
||||
class SM16716 : public Component {
|
||||
public:
|
||||
class Channel;
|
||||
|
||||
void set_data_pin(GPIOPin *data_pin) { data_pin_ = data_pin; }
|
||||
void set_clock_pin(GPIOPin *clock_pin) { clock_pin_ = clock_pin; }
|
||||
void set_num_channels(uint8_t num_channels) { num_channels_ = num_channels; }
|
||||
void set_num_chips(uint8_t num_chips) { num_chips_ = num_chips; }
|
||||
|
||||
void setup() override;
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
/// Send new values if they were updated.
|
||||
void loop() override;
|
||||
|
||||
class Channel : public output::FloatOutput {
|
||||
public:
|
||||
void set_parent(SM16716 *parent) { parent_ = parent; }
|
||||
void set_channel(uint8_t channel) { channel_ = channel; }
|
||||
|
||||
protected:
|
||||
void write_state(float state) override {
|
||||
auto amount = uint8_t(state * 0xFF);
|
||||
this->parent_->set_channel_value_(this->channel_, amount);
|
||||
}
|
||||
|
||||
SM16716 *parent_;
|
||||
uint8_t channel_;
|
||||
};
|
||||
|
||||
protected:
|
||||
void set_channel_value_(uint8_t channel, uint8_t value) {
|
||||
uint8_t index = this->num_channels_ - channel - 1;
|
||||
if (this->pwm_amounts_[index] != value) {
|
||||
this->update_ = true;
|
||||
}
|
||||
this->pwm_amounts_[index] = value;
|
||||
}
|
||||
void write_bit_(bool value) {
|
||||
this->data_pin_->digital_write(value);
|
||||
this->clock_pin_->digital_write(true);
|
||||
this->clock_pin_->digital_write(false);
|
||||
}
|
||||
void write_byte_(uint8_t data) {
|
||||
for (uint8_t mask = 0x80; mask; mask >>= 1) {
|
||||
this->write_bit_(data & mask);
|
||||
}
|
||||
}
|
||||
|
||||
GPIOPin *data_pin_;
|
||||
GPIOPin *clock_pin_;
|
||||
uint8_t num_channels_;
|
||||
uint8_t num_chips_;
|
||||
std::vector<uint8_t> pwm_amounts_;
|
||||
bool update_{true};
|
||||
};
|
||||
|
||||
} // namespace sm16716
|
||||
} // namespace esphome
|
Loading…
Reference in a new issue