Feature/m5angle8: Add support for m5angle8 input device (#6799)

Co-authored-by: Richard Nauber <richard@nauber.dev>
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
rnauber
2024-07-21 23:57:59 +02:00
committed by GitHub
parent 368662969e
commit 40e79299d5
20 changed files with 474 additions and 0 deletions
@@ -0,0 +1,31 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import light
from esphome.const import CONF_OUTPUT_ID
from .. import M5Stack8AngleComponent, m5stack_8angle_ns, CONF_M5STACK_8ANGLE_ID
M5Stack8AngleLightsComponent = m5stack_8angle_ns.class_(
"M5Stack8AngleLightOutput",
light.AddressableLight,
)
CONFIG_SCHEMA = cv.All(
light.ADDRESSABLE_LIGHT_SCHEMA.extend(
{
cv.GenerateID(CONF_M5STACK_8ANGLE_ID): cv.use_id(M5Stack8AngleComponent),
cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(M5Stack8AngleLightsComponent),
}
)
)
async def to_code(config):
hub = await cg.get_variable(config[CONF_M5STACK_8ANGLE_ID])
lights = cg.new_Pvariable(config[CONF_OUTPUT_ID])
await light.register_light(lights, config)
await cg.register_component(lights, config)
cg.add(lights.set_parent(hub))
@@ -0,0 +1,45 @@
#include "m5stack_8angle_light.h"
#include "esphome/core/log.h"
namespace esphome {
namespace m5stack_8angle {
static const char *const TAG = "m5stack_8angle.light";
void M5Stack8AngleLightOutput::setup() {
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
this->buf_ = allocator.allocate(M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED);
if (this->buf_ == nullptr) {
ESP_LOGE(TAG, "Failed to allocate buffer of size %u", M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED);
this->mark_failed();
return;
};
memset(this->buf_, 0xFF, M5STACK_8ANGLE_NUM_LEDS * M5STACK_8ANGLE_BYTES_PER_LED);
this->effect_data_ = allocator.allocate(M5STACK_8ANGLE_NUM_LEDS);
if (this->effect_data_ == nullptr) {
ESP_LOGE(TAG, "Failed to allocate effect data of size %u", M5STACK_8ANGLE_NUM_LEDS);
this->mark_failed();
return;
};
memset(this->effect_data_, 0x00, M5STACK_8ANGLE_NUM_LEDS);
}
void M5Stack8AngleLightOutput::write_state(light::LightState *state) {
for (int i = 0; i < M5STACK_8ANGLE_NUM_LEDS;
i++) { // write one LED at a time, otherwise the message will be truncated
this->parent_->write_register(M5STACK_8ANGLE_REGISTER_RGB_24B + i * M5STACK_8ANGLE_BYTES_PER_LED,
this->buf_ + i * M5STACK_8ANGLE_BYTES_PER_LED, M5STACK_8ANGLE_BYTES_PER_LED);
}
}
light::ESPColorView M5Stack8AngleLightOutput::get_view_internal(int32_t index) const {
size_t pos = index * M5STACK_8ANGLE_BYTES_PER_LED;
// red, green, blue, white, effect_data, color_correction
return {this->buf_ + pos, this->buf_ + pos + 1, this->buf_ + pos + 2,
nullptr, this->effect_data_ + index, &this->correction_};
}
} // namespace m5stack_8angle
} // namespace esphome
@@ -0,0 +1,37 @@
#pragma once
#include "esphome/components/light/addressable_light.h"
#include "esphome/components/light/light_output.h"
#include "../m5stack_8angle.h"
namespace esphome {
namespace m5stack_8angle {
static const uint8_t M5STACK_8ANGLE_NUM_LEDS = 9;
static const uint8_t M5STACK_8ANGLE_BYTES_PER_LED = 4;
class M5Stack8AngleLightOutput : public light::AddressableLight, public Parented<M5Stack8AngleComponent> {
public:
void setup() override;
void write_state(light::LightState *state) override;
int32_t size() const override { return M5STACK_8ANGLE_NUM_LEDS; }
light::LightTraits get_traits() override {
auto traits = light::LightTraits();
traits.set_supported_color_modes({light::ColorMode::RGB});
return traits;
};
void clear_effect_data() override { memset(this->effect_data_, 0x00, M5STACK_8ANGLE_NUM_LEDS); };
protected:
light::ESPColorView get_view_internal(int32_t index) const override;
uint8_t *buf_{nullptr};
uint8_t *effect_data_{nullptr};
};
} // namespace m5stack_8angle
} // namespace esphome