Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support multiple neopixels. #76

Open
wants to merge 1 commit into
base: seesaw
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions components/seesaw/light/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import light
from esphome.const import CONF_OUTPUT_ID, CONF_PIN
from esphome.const import CONF_NUM_LEDS, CONF_OUTPUT_ID, CONF_PIN
from .. import seesaw_ns, Seesaw, CONF_SEESAW

SeesawNeopixel = seesaw_ns.class_("SeesawNeopixel", light.LightOutput, cg.Component)
SeesawNeopixel = seesaw_ns.class_("SeesawNeopixel", light.AddressableLight)

CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend(
CONFIG_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend(
{
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(SeesawNeopixel),
cv.GenerateID(CONF_SEESAW): cv.use_id(Seesaw),
cv.Required(CONF_PIN): cv.int_range(0, 31),
cv.Optional(CONF_NUM_LEDS, default=1): cv.positive_not_null_int,
}
)

Expand All @@ -20,6 +21,7 @@ async def to_code(config):
await cg.register_component(var, config)
await light.register_light(var, config)
seesaw = await cg.get_variable(config[CONF_SEESAW])
cg.add(var.set_num_leds(config[CONF_NUM_LEDS]))
cg.add(var.set_parent(seesaw))
cg.add(var.set_pin(config[CONF_PIN]))

26 changes: 22 additions & 4 deletions components/seesaw/light/seesaw_neopixel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,36 @@ namespace seesaw {
static const char *const TAG = "seesaw.neopixel";

void SeesawNeopixel::setup() {
this->parent_->setup_neopixel(this->pin_);
this->parent_->setup_neopixel(this->pin_, this->num_leds_);
}

void SeesawNeopixel::set_num_leds(uint16_t num_leds) {
this->num_leds_ = num_leds;

// Cleanup if already allocated
if (this->buf_ != nullptr) delete[] this->buf_;
if (this->effect_data_ != nullptr) delete[] this->effect_data_;

// Byte each for Red, Green, and Blue
this->buf_ = new uint8_t[this->size() * 3]; // NOLINT
this->effect_data_ = new uint8_t[this->size()]; // NOLINT

// Clear buffer
memset(this->buf_, 0x00, this->size() * 3);
memset(this->effect_data_, 0x00, this->size());
}

light::LightTraits SeesawNeopixel::get_traits() {
auto traits = light::LightTraits();
traits.set_supported_color_modes({light::ColorMode::RGB});
return traits;
}

void SeesawNeopixel::write_state(light::LightState *state) {
float red, green, blue;
state->current_values_as_rgb(&red, &green, &blue);
this->parent_->color_neopixel(red * 255, green * 255, blue * 255);
for(uint16_t i = 0; i < this->size(); i++) {
auto view = get_view_internal(i);
this->parent_->color_neopixel(i, view.get_red(), view.get_green(), view.get_blue());
}
}

} // namespace seesaw
Expand Down
19 changes: 17 additions & 2 deletions components/seesaw/light/seesaw_neopixel.h
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
#pragma once

#include "esphome/core/component.h"
#include "esphome/components/light/light_output.h"
#include "esphome/components/light/addressable_light.h"
#include "../seesaw.h"

namespace esphome {
namespace seesaw {

class SeesawNeopixel : public light::LightOutput, public Component {
class SeesawNeopixel : public light::AddressableLight {
public:
void setup() override;
void set_num_leds(uint16_t num_leds);
void set_parent(Seesaw *parent) { parent_ = parent; }
void set_pin(int pin) { this->pin_ = pin; }
light::LightTraits get_traits() override;
void write_state(light::LightState *state) override;
void clear_effect_data() override {
for (int i = 0; i < this->size(); i++)
this->effect_data_[i] = 0;
}
int32_t size() const override { return this->num_leds_; }
protected:
Seesaw *parent_;
int pin_;
uint8_t *buf_{nullptr};
uint8_t *effect_data_{nullptr};
uint16_t num_leds_{0};

light::ESPColorView get_view_internal(int32_t index) const override {
uint8_t *base = this->buf_ + (3 * index);

return light::ESPColorView(base + 0, base + 1, base + 2, nullptr, this->effect_data_ + index, &this->correction_);
}
};

} // namespace seesaw
Expand Down
9 changes: 5 additions & 4 deletions components/seesaw/seesaw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,14 +166,15 @@ void Seesaw::digital_write(uint8_t pin, bool state) {
this->write32(SEESAW_GPIO, SEESAW_GPIO_BULK_CLR, pin);
}

void Seesaw::setup_neopixel(int pin) {
void Seesaw::setup_neopixel(int pin, uint16_t n) {
this->write8(SEESAW_NEOPIXEL, SEESAW_NEOPIXEL_SPEED, 1);
this->write16(SEESAW_NEOPIXEL, SEESAW_NEOPIXEL_BUF_LENGTH, 3);
this->write16(SEESAW_NEOPIXEL, SEESAW_NEOPIXEL_BUF_LENGTH, n * 3);
this->write8(SEESAW_NEOPIXEL, SEESAW_NEOPIXEL_PIN, pin);
}

void Seesaw::color_neopixel(uint8_t r, uint8_t g, uint8_t b) {
uint8_t buf[7] = {SEESAW_NEOPIXEL, SEESAW_NEOPIXEL_BUF, 0, 0, g, r, b};
void Seesaw::color_neopixel(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
uint16_t offset = n * 3;
uint8_t buf[7] = {SEESAW_NEOPIXEL, SEESAW_NEOPIXEL_BUF, (offset >> 8), offset, g, r, b};
this->write(buf, 7);
buf[1] = SEESAW_NEOPIXEL_SHOW;
this->write(buf, 2);
Expand Down
4 changes: 2 additions & 2 deletions components/seesaw/seesaw.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ class Seesaw : public i2c::I2CDevice, public Component {
bool digital_read(uint8_t pin);
void digital_write(uint8_t pin, bool state);
void set_gpio_interrupt(uint32_t pin, bool enabled);
void setup_neopixel(int pin);
void color_neopixel(uint8_t r, uint8_t g, uint8_t b);
void setup_neopixel(int pin, uint16_t n);
void color_neopixel(uint16_t n, uint8_t r, uint8_t g, uint8_t b);

protected:
i2c::ErrorCode write8(SeesawModule mod, uint8_t reg, uint8_t value);
Expand Down