mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 16:37:52 +01:00
Migrate ESPColor to Color (#1551)
* Migrate ESPColor to Color * color.h constructor fix * Updated componets to use Color Added a using for ESPColor * Lint fixes * Fixed value error * Update display components to use colorutil * Updated to latest PR comments * Fixed COLOR_WHITE * Moved esp_scale to color_utils * Rename color_utils to display_color_utils
This commit is contained in:
parent
b17e0c298e
commit
ac25b138f5
@ -42,11 +42,11 @@ void AdalightLightEffect::reset_frame_(light::AddressableLight &it) {
|
||||
|
||||
void AdalightLightEffect::blank_all_leds_(light::AddressableLight &it) {
|
||||
for (int led = it.size(); led-- > 0;) {
|
||||
it[led].set(light::ESPColor::BLACK);
|
||||
it[led].set(COLOR_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
void AdalightLightEffect::apply(light::AddressableLight &it, const light::ESPColor ¤t_color) {
|
||||
void AdalightLightEffect::apply(light::AddressableLight &it, const Color ¤t_color) {
|
||||
const uint32_t now = millis();
|
||||
|
||||
if (now - this->last_ack_ >= ADALIGHT_ACK_INTERVAL) {
|
||||
@ -130,7 +130,7 @@ AdalightLightEffect::Frame AdalightLightEffect::parse_frame_(light::AddressableL
|
||||
for (int led = 0; led < accepted_led_count; led++, led_data += 3) {
|
||||
auto white = std::min(std::min(led_data[0], led_data[1]), led_data[2]);
|
||||
|
||||
it[led].set(light::ESPColor(led_data[0], led_data[1], led_data[2], white));
|
||||
it[led].set(Color(led_data[0], led_data[1], led_data[2], white));
|
||||
}
|
||||
|
||||
return CONSUMED;
|
||||
|
@ -16,7 +16,7 @@ class AdalightLightEffect : public light::AddressableLightEffect, public uart::U
|
||||
public:
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void apply(light::AddressableLight &it, const light::ESPColor ¤t_color) override;
|
||||
void apply(light::AddressableLight &it, const Color ¤t_color) override;
|
||||
|
||||
protected:
|
||||
enum Frame {
|
||||
|
@ -2,22 +2,58 @@ from esphome import config_validation as cv
|
||||
from esphome import codegen as cg
|
||||
from esphome.const import CONF_BLUE, CONF_GREEN, CONF_ID, CONF_RED, CONF_WHITE
|
||||
|
||||
ColorStruct = cg.esphome_ns.struct('Color')
|
||||
ColorStruct = cg.esphome_ns.struct("Color")
|
||||
|
||||
MULTI_CONF = True
|
||||
CONFIG_SCHEMA = cv.Schema({
|
||||
cv.Required(CONF_ID): cv.declare_id(ColorStruct),
|
||||
cv.Optional(CONF_RED, default=0.0): cv.percentage,
|
||||
cv.Optional(CONF_GREEN, default=0.0): cv.percentage,
|
||||
cv.Optional(CONF_BLUE, default=0.0): cv.percentage,
|
||||
cv.Optional(CONF_WHITE, default=0.0): cv.percentage,
|
||||
}).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
CONF_RED_INT = "red_int"
|
||||
CONF_GREEN_INT = "green_int"
|
||||
CONF_BLUE_INT = "blue_int"
|
||||
CONF_WHITE_INT = "white_int"
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.declare_id(ColorStruct),
|
||||
cv.Exclusive(CONF_RED, 'red'): cv.percentage,
|
||||
cv.Exclusive(CONF_RED_INT, 'red'): cv.uint8_t,
|
||||
cv.Exclusive(CONF_GREEN, 'green'): cv.percentage,
|
||||
cv.Exclusive(CONF_GREEN_INT, 'green'): cv.uint8_t,
|
||||
cv.Exclusive(CONF_BLUE, 'blue'): cv.percentage,
|
||||
cv.Exclusive(CONF_BLUE_INT, 'blue'): cv.uint8_t,
|
||||
cv.Exclusive(CONF_WHITE, 'white'): cv.percentage,
|
||||
cv.Exclusive(CONF_WHITE_INT, 'white'): cv.uint8_t,
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA)
|
||||
|
||||
|
||||
def to_code(config):
|
||||
r = 0
|
||||
if CONF_RED in config:
|
||||
r = int(config[CONF_RED]*255)
|
||||
elif CONF_RED_INT in config:
|
||||
r = config[CONF_RED_INT]
|
||||
|
||||
g = 0
|
||||
if CONF_GREEN in config:
|
||||
g = int(config[CONF_GREEN]*255)
|
||||
elif CONF_GREEN_INT in config:
|
||||
g = config[CONF_GREEN_INT]
|
||||
|
||||
b = 0
|
||||
if CONF_BLUE in config:
|
||||
b = int(config[CONF_BLUE]*255)
|
||||
elif CONF_BLUE_INT in config:
|
||||
b = config[CONF_BLUE_INT]
|
||||
|
||||
w = 0
|
||||
if CONF_WHITE in config:
|
||||
w = int(config[CONF_WHITE]*255)
|
||||
elif CONF_WHITE_INT in config:
|
||||
w = config[CONF_WHITE_INT]
|
||||
|
||||
cg.variable(config[CONF_ID], cg.StructInitializer(
|
||||
ColorStruct,
|
||||
('r', config[CONF_RED]),
|
||||
('g', config[CONF_GREEN]),
|
||||
('b', config[CONF_BLUE]),
|
||||
('w', config[CONF_WHITE])))
|
||||
('r', r),
|
||||
('g', g),
|
||||
('b', b),
|
||||
('w', w)))
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/color.h"
|
||||
#include "display_color_utils.h"
|
||||
|
||||
#ifdef USE_TIME
|
||||
#include "esphome/components/time/real_time_clock.h"
|
||||
|
110
esphome/components/display/display_color_utils.h
Normal file
110
esphome/components/display/display_color_utils.h
Normal file
@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
#include "esphome/core/color.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace display {
|
||||
enum ColorOrder : uint8_t { COLOR_ORDER_RGB = 0, COLOR_ORDER_BGR = 1, COLOR_ORDER_GRB = 2 };
|
||||
enum ColorBitness : uint8_t { COLOR_BITNESS_888 = 0, COLOR_BITNESS_565 = 1, COLOR_BITNESS_332 = 2 };
|
||||
inline static uint8_t esp_scale(uint8_t i, uint8_t scale, uint8_t max_value = 255) { return (max_value * i / scale); }
|
||||
|
||||
class ColorUtil {
|
||||
public:
|
||||
static Color to_color(uint32_t colorcode, ColorOrder color_order,
|
||||
ColorBitness color_bitness = ColorBitness::COLOR_BITNESS_888, bool right_bit_aligned = true) {
|
||||
uint8_t first_color, second_color, third_color;
|
||||
uint8_t first_bits = 0;
|
||||
uint8_t second_bits = 0;
|
||||
uint8_t third_bits = 0;
|
||||
|
||||
switch (color_bitness) {
|
||||
case COLOR_BITNESS_888:
|
||||
first_bits = 8;
|
||||
second_bits = 8;
|
||||
third_bits = 8;
|
||||
break;
|
||||
case COLOR_BITNESS_565:
|
||||
first_bits = 5;
|
||||
second_bits = 6;
|
||||
third_bits = 5;
|
||||
break;
|
||||
case COLOR_BITNESS_332:
|
||||
first_bits = 3;
|
||||
second_bits = 3;
|
||||
third_bits = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
first_color = right_bit_aligned ? esp_scale(((colorcode >> (second_bits + third_bits)) & ((1 << first_bits) - 1)),
|
||||
((1 << first_bits) - 1))
|
||||
: esp_scale(((colorcode >> 16) & 0xFF), (1 << first_bits) - 1);
|
||||
|
||||
second_color = right_bit_aligned
|
||||
? esp_scale(((colorcode >> third_bits) & ((1 << second_bits) - 1)), ((1 << second_bits) - 1))
|
||||
: esp_scale(((colorcode >> 8) & 0xFF), ((1 << second_bits) - 1));
|
||||
|
||||
third_color = (right_bit_aligned ? esp_scale(((colorcode >> 0) & 0xFF), ((1 << third_bits) - 1))
|
||||
: esp_scale(((colorcode >> 0) & 0xFF), (1 << third_bits) - 1));
|
||||
|
||||
Color color_return;
|
||||
|
||||
switch (color_order) {
|
||||
case COLOR_ORDER_RGB:
|
||||
color_return.r = first_color;
|
||||
color_return.g = second_color;
|
||||
color_return.b = third_color;
|
||||
break;
|
||||
case COLOR_ORDER_BGR:
|
||||
color_return.b = first_color;
|
||||
color_return.g = second_color;
|
||||
color_return.r = third_color;
|
||||
break;
|
||||
case COLOR_ORDER_GRB:
|
||||
color_return.g = first_color;
|
||||
color_return.r = second_color;
|
||||
color_return.b = third_color;
|
||||
break;
|
||||
}
|
||||
return color_return;
|
||||
}
|
||||
static uint8_t color_to_332(Color color, ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) {
|
||||
uint16_t red_color, green_color, blue_color;
|
||||
|
||||
red_color = esp_scale8(color.red, ((1 << 3) - 1));
|
||||
green_color = esp_scale8(color.green, ((1 << 3) - 1));
|
||||
blue_color = esp_scale8(color.blue, (1 << 2) - 1);
|
||||
|
||||
switch (color_order) {
|
||||
case COLOR_ORDER_RGB:
|
||||
return red_color << 5 | green_color << 2 | blue_color;
|
||||
case COLOR_ORDER_BGR:
|
||||
return blue_color << 6 | green_color << 3 | red_color;
|
||||
case COLOR_ORDER_GRB:
|
||||
return green_color << 5 | red_color << 2 | blue_color;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static uint16_t color_to_565(Color color, ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) {
|
||||
uint16_t red_color, green_color, blue_color;
|
||||
|
||||
red_color = esp_scale8(color.red, ((1 << 5) - 1));
|
||||
green_color = esp_scale8(color.green, ((1 << 6) - 1));
|
||||
blue_color = esp_scale8(color.blue, (1 << 5) - 1);
|
||||
|
||||
switch (color_order) {
|
||||
case COLOR_ORDER_RGB:
|
||||
return red_color << 11 | green_color << 5 | blue_color;
|
||||
case COLOR_ORDER_BGR:
|
||||
return blue_color << 11 | green_color << 5 | red_color;
|
||||
case COLOR_ORDER_GRB:
|
||||
return green_color << 10 | red_color << 5 | blue_color;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t color_to_grayscale4(Color color) {
|
||||
uint32_t gs4 = esp_scale8(color.white, 15);
|
||||
return gs4;
|
||||
}
|
||||
};
|
||||
} // namespace display
|
||||
} // namespace esphome
|
@ -40,7 +40,7 @@ void E131AddressableLightEffect::stop() {
|
||||
AddressableLightEffect::stop();
|
||||
}
|
||||
|
||||
void E131AddressableLightEffect::apply(light::AddressableLight &it, const light::ESPColor ¤t_color) {
|
||||
void E131AddressableLightEffect::apply(light::AddressableLight &it, const Color ¤t_color) {
|
||||
// ignore, it is run by `E131Component::update()`
|
||||
}
|
||||
|
||||
@ -63,22 +63,22 @@ bool E131AddressableLightEffect::process_(int universe, const E131Packet &packet
|
||||
case E131_MONO:
|
||||
for (; output_offset < output_end; output_offset++, input_data++) {
|
||||
auto output = (*it)[output_offset];
|
||||
output.set(light::ESPColor(input_data[0], input_data[0], input_data[0], input_data[0]));
|
||||
output.set(Color(input_data[0], input_data[0], input_data[0], input_data[0]));
|
||||
}
|
||||
break;
|
||||
|
||||
case E131_RGB:
|
||||
for (; output_offset < output_end; output_offset++, input_data += 3) {
|
||||
auto output = (*it)[output_offset];
|
||||
output.set(light::ESPColor(input_data[0], input_data[1], input_data[2],
|
||||
(input_data[0] + input_data[1] + input_data[2]) / 3));
|
||||
output.set(
|
||||
Color(input_data[0], input_data[1], input_data[2], (input_data[0] + input_data[1] + input_data[2]) / 3));
|
||||
}
|
||||
break;
|
||||
|
||||
case E131_RGBW:
|
||||
for (; output_offset < output_end; output_offset++, input_data += 4) {
|
||||
auto output = (*it)[output_offset];
|
||||
output.set(light::ESPColor(input_data[0], input_data[1], input_data[2], input_data[3]));
|
||||
output.set(Color(input_data[0], input_data[1], input_data[2], input_data[3]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class E131AddressableLightEffect : public light::AddressableLightEffect {
|
||||
public:
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void apply(light::AddressableLight &it, const light::ESPColor ¤t_color) override;
|
||||
void apply(light::AddressableLight &it, const Color ¤t_color) override;
|
||||
|
||||
public:
|
||||
int get_data_per_universe() const;
|
||||
|
@ -130,7 +130,7 @@ uint8_t ILI9341Display::convert_to_8bit_color_(uint16_t color_16bit) {
|
||||
}
|
||||
|
||||
void ILI9341Display::fill(Color color) {
|
||||
auto color565 = color.to_rgb_565();
|
||||
auto color565 = display::ColorUtil::color_to_565(color);
|
||||
memset(this->buffer_, convert_to_8bit_color_(color565), this->get_buffer_length_());
|
||||
this->x_low_ = 0;
|
||||
this->y_low_ = 0;
|
||||
@ -142,7 +142,7 @@ void ILI9341Display::fill_internal_(Color color) {
|
||||
this->set_addr_window_(0, 0, this->get_width_internal(), this->get_height_internal());
|
||||
this->start_data_();
|
||||
|
||||
auto color565 = color.to_rgb_565();
|
||||
auto color565 = display::ColorUtil::color_to_565(color);
|
||||
for (uint32_t i = 0; i < (this->get_width_internal()) * (this->get_height_internal()); i++) {
|
||||
this->write_byte(color565 >> 8);
|
||||
this->write_byte(color565);
|
||||
@ -162,7 +162,7 @@ void HOT ILI9341Display::draw_absolute_pixel_internal(int x, int y, Color color)
|
||||
this->y_high_ = (y > this->y_high_) ? y : this->y_high_;
|
||||
|
||||
uint32_t pos = (y * width_) + x;
|
||||
auto color565 = color.to_rgb_565();
|
||||
auto color565 = display::ColorUtil::color_to_565(color);
|
||||
buffer_[pos] = convert_to_8bit_color_(color565);
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,7 @@ namespace light {
|
||||
|
||||
static const char *TAG = "light.addressable";
|
||||
|
||||
const ESPColor ESPColor::BLACK = ESPColor(0, 0, 0, 0);
|
||||
const ESPColor ESPColor::WHITE = ESPColor(255, 255, 255, 255);
|
||||
|
||||
ESPColor ESPHSVColor::to_rgb() const {
|
||||
Color ESPHSVColor::to_rgb() const {
|
||||
// based on FastLED's hsv rainbow to rgb
|
||||
const uint8_t hue = this->hue;
|
||||
const uint8_t sat = this->saturation;
|
||||
@ -19,7 +16,7 @@ ESPColor ESPHSVColor::to_rgb() const {
|
||||
// third of the offset, 255/3 = 85 (actually only up to 82; 164)
|
||||
const uint8_t third = esp_scale8(offset8, 85);
|
||||
const uint8_t two_thirds = esp_scale8(offset8, 170);
|
||||
ESPColor rgb(255, 255, 255, 0);
|
||||
Color rgb(255, 255, 255, 0);
|
||||
switch (hue >> 5) {
|
||||
case 0b000:
|
||||
rgb.r = 255 - third;
|
||||
@ -76,7 +73,7 @@ ESPColor ESPHSVColor::to_rgb() const {
|
||||
return rgb;
|
||||
}
|
||||
|
||||
void ESPRangeView::set(const ESPColor &color) {
|
||||
void ESPRangeView::set(const Color &color) {
|
||||
for (int32_t i = this->begin_; i < this->end_; i++) {
|
||||
(*this->parent_)[i] = color;
|
||||
}
|
||||
@ -179,12 +176,12 @@ void AddressableLight::call_setup() {
|
||||
#endif
|
||||
}
|
||||
|
||||
ESPColor esp_color_from_light_color_values(LightColorValues val) {
|
||||
Color esp_color_from_light_color_values(LightColorValues val) {
|
||||
auto r = static_cast<uint8_t>(roundf(val.get_red() * 255.0f));
|
||||
auto g = static_cast<uint8_t>(roundf(val.get_green() * 255.0f));
|
||||
auto b = static_cast<uint8_t>(roundf(val.get_blue() * 255.0f));
|
||||
auto w = static_cast<uint8_t>(roundf(val.get_white() * val.get_state() * 255.0f));
|
||||
return ESPColor(r, g, b, w);
|
||||
return Color(r, g, b, w);
|
||||
}
|
||||
|
||||
void AddressableLight::write_state(LightState *state) {
|
||||
@ -219,7 +216,7 @@ void AddressableLight::write_state(LightState *state) {
|
||||
this->last_transition_progress_ = new_progress;
|
||||
|
||||
auto end_values = state->transformer_->get_end_values();
|
||||
ESPColor target_color = esp_color_from_light_color_values(end_values);
|
||||
Color target_color = esp_color_from_light_color_values(end_values);
|
||||
|
||||
// our transition will handle brightness, disable brightness in correction.
|
||||
this->correction_.set_local_brightness(255);
|
||||
@ -247,7 +244,7 @@ void AddressableLight::write_state(LightState *state) {
|
||||
|
||||
if (alpha8 != 0) {
|
||||
uint8_t inv_alpha8 = 255 - alpha8;
|
||||
ESPColor add = target_color * alpha8;
|
||||
Color add = target_color * alpha8;
|
||||
|
||||
for (auto led : *this)
|
||||
led = add + led.get() * inv_alpha8;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/color.h"
|
||||
#include "light_output.h"
|
||||
#include "light_state.h"
|
||||
|
||||
@ -12,151 +13,7 @@
|
||||
namespace esphome {
|
||||
namespace light {
|
||||
|
||||
inline static uint8_t esp_scale8(uint8_t i, uint8_t scale) { return (uint16_t(i) * (1 + uint16_t(scale))) / 256; }
|
||||
|
||||
struct ESPColor {
|
||||
union {
|
||||
struct {
|
||||
union {
|
||||
uint8_t r;
|
||||
uint8_t red;
|
||||
};
|
||||
union {
|
||||
uint8_t g;
|
||||
uint8_t green;
|
||||
};
|
||||
union {
|
||||
uint8_t b;
|
||||
uint8_t blue;
|
||||
};
|
||||
union {
|
||||
uint8_t w;
|
||||
uint8_t white;
|
||||
};
|
||||
};
|
||||
uint8_t raw[4];
|
||||
uint32_t raw_32;
|
||||
};
|
||||
inline ESPColor() ALWAYS_INLINE : r(0), g(0), b(0), w(0) {} // NOLINT
|
||||
inline ESPColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) ALWAYS_INLINE : r(red),
|
||||
g(green),
|
||||
b(blue),
|
||||
w(white) {}
|
||||
inline ESPColor(uint8_t red, uint8_t green, uint8_t blue) ALWAYS_INLINE : r(red), g(green), b(blue), w(0) {}
|
||||
inline ESPColor(uint32_t colorcode) ALWAYS_INLINE : r((colorcode >> 16) & 0xFF),
|
||||
g((colorcode >> 8) & 0xFF),
|
||||
b((colorcode >> 0) & 0xFF),
|
||||
w((colorcode >> 24) & 0xFF) {}
|
||||
inline ESPColor(const ESPColor &rhs) ALWAYS_INLINE {
|
||||
this->r = rhs.r;
|
||||
this->g = rhs.g;
|
||||
this->b = rhs.b;
|
||||
this->w = rhs.w;
|
||||
}
|
||||
inline bool is_on() ALWAYS_INLINE { return this->raw_32 != 0; }
|
||||
inline ESPColor &operator=(const ESPColor &rhs) ALWAYS_INLINE {
|
||||
this->r = rhs.r;
|
||||
this->g = rhs.g;
|
||||
this->b = rhs.b;
|
||||
this->w = rhs.w;
|
||||
return *this;
|
||||
}
|
||||
inline ESPColor &operator=(uint32_t colorcode) ALWAYS_INLINE {
|
||||
this->w = (colorcode >> 24) & 0xFF;
|
||||
this->r = (colorcode >> 16) & 0xFF;
|
||||
this->g = (colorcode >> 8) & 0xFF;
|
||||
this->b = (colorcode >> 0) & 0xFF;
|
||||
return *this;
|
||||
}
|
||||
inline uint8_t &operator[](uint8_t x) ALWAYS_INLINE { return this->raw[x]; }
|
||||
inline ESPColor operator*(uint8_t scale) const ALWAYS_INLINE {
|
||||
return ESPColor(esp_scale8(this->red, scale), esp_scale8(this->green, scale), esp_scale8(this->blue, scale),
|
||||
esp_scale8(this->white, scale));
|
||||
}
|
||||
inline ESPColor &operator*=(uint8_t scale) ALWAYS_INLINE {
|
||||
this->red = esp_scale8(this->red, scale);
|
||||
this->green = esp_scale8(this->green, scale);
|
||||
this->blue = esp_scale8(this->blue, scale);
|
||||
this->white = esp_scale8(this->white, scale);
|
||||
return *this;
|
||||
}
|
||||
inline ESPColor operator*(const ESPColor &scale) const ALWAYS_INLINE {
|
||||
return ESPColor(esp_scale8(this->red, scale.red), esp_scale8(this->green, scale.green),
|
||||
esp_scale8(this->blue, scale.blue), esp_scale8(this->white, scale.white));
|
||||
}
|
||||
inline ESPColor &operator*=(const ESPColor &scale) ALWAYS_INLINE {
|
||||
this->red = esp_scale8(this->red, scale.red);
|
||||
this->green = esp_scale8(this->green, scale.green);
|
||||
this->blue = esp_scale8(this->blue, scale.blue);
|
||||
this->white = esp_scale8(this->white, scale.white);
|
||||
return *this;
|
||||
}
|
||||
inline ESPColor operator+(const ESPColor &add) const ALWAYS_INLINE {
|
||||
ESPColor ret;
|
||||
if (uint8_t(add.r + this->r) < this->r)
|
||||
ret.r = 255;
|
||||
else
|
||||
ret.r = this->r + add.r;
|
||||
if (uint8_t(add.g + this->g) < this->g)
|
||||
ret.g = 255;
|
||||
else
|
||||
ret.g = this->g + add.g;
|
||||
if (uint8_t(add.b + this->b) < this->b)
|
||||
ret.b = 255;
|
||||
else
|
||||
ret.b = this->b + add.b;
|
||||
if (uint8_t(add.w + this->w) < this->w)
|
||||
ret.w = 255;
|
||||
else
|
||||
ret.w = this->w + add.w;
|
||||
return ret;
|
||||
}
|
||||
inline ESPColor &operator+=(const ESPColor &add) ALWAYS_INLINE { return *this = (*this) + add; }
|
||||
inline ESPColor operator+(uint8_t add) const ALWAYS_INLINE { return (*this) + ESPColor(add, add, add, add); }
|
||||
inline ESPColor &operator+=(uint8_t add) ALWAYS_INLINE { return *this = (*this) + add; }
|
||||
inline ESPColor operator-(const ESPColor &subtract) const ALWAYS_INLINE {
|
||||
ESPColor ret;
|
||||
if (subtract.r > this->r)
|
||||
ret.r = 0;
|
||||
else
|
||||
ret.r = this->r - subtract.r;
|
||||
if (subtract.g > this->g)
|
||||
ret.g = 0;
|
||||
else
|
||||
ret.g = this->g - subtract.g;
|
||||
if (subtract.b > this->b)
|
||||
ret.b = 0;
|
||||
else
|
||||
ret.b = this->b - subtract.b;
|
||||
if (subtract.w > this->w)
|
||||
ret.w = 0;
|
||||
else
|
||||
ret.w = this->w - subtract.w;
|
||||
return ret;
|
||||
}
|
||||
inline ESPColor &operator-=(const ESPColor &subtract) ALWAYS_INLINE { return *this = (*this) - subtract; }
|
||||
inline ESPColor operator-(uint8_t subtract) const ALWAYS_INLINE {
|
||||
return (*this) - ESPColor(subtract, subtract, subtract, subtract);
|
||||
}
|
||||
inline ESPColor &operator-=(uint8_t subtract) ALWAYS_INLINE { return *this = (*this) - subtract; }
|
||||
static ESPColor random_color() {
|
||||
uint32_t rand = random_uint32();
|
||||
uint8_t w = rand >> 24;
|
||||
uint8_t r = rand >> 16;
|
||||
uint8_t g = rand >> 8;
|
||||
uint8_t b = rand >> 0;
|
||||
const uint16_t max_rgb = std::max(r, std::max(g, b));
|
||||
return ESPColor(uint8_t((uint16_t(r) * 255U / max_rgb)), uint8_t((uint16_t(g) * 255U / max_rgb)),
|
||||
uint8_t((uint16_t(b) * 255U / max_rgb)), w);
|
||||
}
|
||||
ESPColor fade_to_white(uint8_t amnt) const { return ESPColor(255, 255, 255, 255) - (*this * amnt); }
|
||||
ESPColor fade_to_black(uint8_t amnt) const { return *this * amnt; }
|
||||
ESPColor lighten(uint8_t delta) const { return *this + delta; }
|
||||
ESPColor darken(uint8_t delta) const { return *this - delta; }
|
||||
|
||||
static const ESPColor BLACK;
|
||||
static const ESPColor WHITE;
|
||||
};
|
||||
using ESPColor = Color;
|
||||
|
||||
struct ESPHSVColor {
|
||||
union {
|
||||
@ -181,19 +38,19 @@ struct ESPHSVColor {
|
||||
inline ESPHSVColor(uint8_t hue, uint8_t saturation, uint8_t value) ALWAYS_INLINE : hue(hue),
|
||||
saturation(saturation),
|
||||
value(value) {}
|
||||
ESPColor to_rgb() const;
|
||||
Color to_rgb() const;
|
||||
};
|
||||
|
||||
class ESPColorCorrection {
|
||||
public:
|
||||
ESPColorCorrection() : max_brightness_(255, 255, 255, 255) {}
|
||||
void set_max_brightness(const ESPColor &max_brightness) { this->max_brightness_ = max_brightness; }
|
||||
void set_max_brightness(const Color &max_brightness) { this->max_brightness_ = max_brightness; }
|
||||
void set_local_brightness(uint8_t local_brightness) { this->local_brightness_ = local_brightness; }
|
||||
void calculate_gamma_table(float gamma);
|
||||
inline ESPColor color_correct(ESPColor color) const ALWAYS_INLINE {
|
||||
inline Color color_correct(Color color) const ALWAYS_INLINE {
|
||||
// corrected = (uncorrected * max_brightness * local_brightness) ^ gamma
|
||||
return ESPColor(this->color_correct_red(color.red), this->color_correct_green(color.green),
|
||||
this->color_correct_blue(color.blue), this->color_correct_white(color.white));
|
||||
return Color(this->color_correct_red(color.red), this->color_correct_green(color.green),
|
||||
this->color_correct_blue(color.blue), this->color_correct_white(color.white));
|
||||
}
|
||||
inline uint8_t color_correct_red(uint8_t red) const ALWAYS_INLINE {
|
||||
uint8_t res = esp_scale8(esp_scale8(red, this->max_brightness_.red), this->local_brightness_);
|
||||
@ -212,10 +69,10 @@ class ESPColorCorrection {
|
||||
uint8_t res = esp_scale8(white, this->max_brightness_.white);
|
||||
return this->gamma_table_[res];
|
||||
}
|
||||
inline ESPColor color_uncorrect(ESPColor color) const ALWAYS_INLINE {
|
||||
inline Color color_uncorrect(Color color) const ALWAYS_INLINE {
|
||||
// uncorrected = corrected^(1/gamma) / (max_brightness * local_brightness)
|
||||
return ESPColor(this->color_uncorrect_red(color.red), this->color_uncorrect_green(color.green),
|
||||
this->color_uncorrect_blue(color.blue), this->color_uncorrect_white(color.white));
|
||||
return Color(this->color_uncorrect_red(color.red), this->color_uncorrect_green(color.green),
|
||||
this->color_uncorrect_blue(color.blue), this->color_uncorrect_white(color.white));
|
||||
}
|
||||
inline uint8_t color_uncorrect_red(uint8_t red) const ALWAYS_INLINE {
|
||||
if (this->max_brightness_.red == 0 || this->local_brightness_ == 0)
|
||||
@ -249,13 +106,13 @@ class ESPColorCorrection {
|
||||
protected:
|
||||
uint8_t gamma_table_[256];
|
||||
uint8_t gamma_reverse_table_[256];
|
||||
ESPColor max_brightness_;
|
||||
Color max_brightness_;
|
||||
uint8_t local_brightness_{255};
|
||||
};
|
||||
|
||||
class ESPColorSettable {
|
||||
public:
|
||||
virtual void set(const ESPColor &color) = 0;
|
||||
virtual void set(const Color &color) = 0;
|
||||
virtual void set_red(uint8_t red) = 0;
|
||||
virtual void set_green(uint8_t green) = 0;
|
||||
virtual void set_blue(uint8_t blue) = 0;
|
||||
@ -267,7 +124,7 @@ class ESPColorSettable {
|
||||
virtual void darken(uint8_t delta) = 0;
|
||||
void set(const ESPHSVColor &color) { this->set_hsv(color); }
|
||||
void set_hsv(const ESPHSVColor &color) {
|
||||
ESPColor rgb = color.to_rgb();
|
||||
Color rgb = color.to_rgb();
|
||||
this->set_rgb(rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
void set_rgb(uint8_t red, uint8_t green, uint8_t blue) {
|
||||
@ -291,7 +148,7 @@ class ESPColorView : public ESPColorSettable {
|
||||
white_(white),
|
||||
effect_data_(effect_data),
|
||||
color_correction_(color_correction) {}
|
||||
ESPColorView &operator=(const ESPColor &rhs) {
|
||||
ESPColorView &operator=(const Color &rhs) {
|
||||
this->set(rhs);
|
||||
return *this;
|
||||
}
|
||||
@ -299,7 +156,7 @@ class ESPColorView : public ESPColorSettable {
|
||||
this->set_hsv(rhs);
|
||||
return *this;
|
||||
}
|
||||
void set(const ESPColor &color) override { this->set_rgbw(color.r, color.g, color.b, color.w); }
|
||||
void set(const Color &color) override { this->set_rgbw(color.r, color.g, color.b, color.w); }
|
||||
void set_red(uint8_t red) override { *this->red_ = this->color_correction_->color_correct_red(red); }
|
||||
void set_green(uint8_t green) override { *this->green_ = this->color_correction_->color_correct_green(green); }
|
||||
void set_blue(uint8_t blue) override { *this->blue_ = this->color_correction_->color_correct_blue(blue); }
|
||||
@ -317,7 +174,7 @@ class ESPColorView : public ESPColorSettable {
|
||||
void fade_to_black(uint8_t amnt) override { this->set(this->get().fade_to_black(amnt)); }
|
||||
void lighten(uint8_t delta) override { this->set(this->get().lighten(delta)); }
|
||||
void darken(uint8_t delta) override { this->set(this->get().darken(delta)); }
|
||||
ESPColor get() const { return ESPColor(this->get_red(), this->get_green(), this->get_blue(), this->get_white()); }
|
||||
Color get() const { return Color(this->get_red(), this->get_green(), this->get_blue(), this->get_white()); }
|
||||
uint8_t get_red() const { return this->color_correction_->color_uncorrect_red(*this->red_); }
|
||||
uint8_t get_red_raw() const { return *this->red_; }
|
||||
uint8_t get_green() const { return this->color_correction_->color_uncorrect_green(*this->green_); }
|
||||
@ -370,8 +227,8 @@ class ESPRangeView : public ESPColorSettable {
|
||||
ESPRangeIterator begin();
|
||||
ESPRangeIterator end();
|
||||
|
||||
void set(const ESPColor &color) override;
|
||||
ESPRangeView &operator=(const ESPColor &rhs) {
|
||||
void set(const Color &color) override;
|
||||
ESPRangeView &operator=(const Color &rhs) {
|
||||
this->set(rhs);
|
||||
return *this;
|
||||
}
|
||||
@ -454,8 +311,8 @@ class AddressableLight : public LightOutput, public Component {
|
||||
void set_effect_active(bool effect_active) { this->effect_active_ = effect_active; }
|
||||
void write_state(LightState *state) override;
|
||||
void set_correction(float red, float green, float blue, float white = 1.0f) {
|
||||
this->correction_.set_max_brightness(ESPColor(uint8_t(roundf(red * 255.0f)), uint8_t(roundf(green * 255.0f)),
|
||||
uint8_t(roundf(blue * 255.0f)), uint8_t(roundf(white * 255.0f))));
|
||||
this->correction_.set_max_brightness(Color(uint8_t(roundf(red * 255.0f)), uint8_t(roundf(green * 255.0f)),
|
||||
uint8_t(roundf(blue * 255.0f)), uint8_t(roundf(white * 255.0f))));
|
||||
}
|
||||
void setup_state(LightState *state) override {
|
||||
this->correction_.calculate_gamma_table(state->get_gamma_correct());
|
||||
|
@ -34,13 +34,13 @@ class AddressableLightEffect : public LightEffect {
|
||||
this->start();
|
||||
}
|
||||
void stop() override { this->get_addressable_()->set_effect_active(false); }
|
||||
virtual void apply(AddressableLight &it, const ESPColor ¤t_color) = 0;
|
||||
virtual void apply(AddressableLight &it, const Color ¤t_color) = 0;
|
||||
void apply() override {
|
||||
LightColorValues color = this->state_->remote_values;
|
||||
// not using any color correction etc. that will be handled by the addressable layer
|
||||
ESPColor current_color =
|
||||
ESPColor(static_cast<uint8_t>(color.get_red() * 255), static_cast<uint8_t>(color.get_green() * 255),
|
||||
static_cast<uint8_t>(color.get_blue() * 255), static_cast<uint8_t>(color.get_white() * 255));
|
||||
Color current_color =
|
||||
Color(static_cast<uint8_t>(color.get_red() * 255), static_cast<uint8_t>(color.get_green() * 255),
|
||||
static_cast<uint8_t>(color.get_blue() * 255), static_cast<uint8_t>(color.get_white() * 255));
|
||||
this->apply(*this->get_addressable_(), current_color);
|
||||
}
|
||||
|
||||
@ -51,11 +51,11 @@ class AddressableLightEffect : public LightEffect {
|
||||
class AddressableLambdaLightEffect : public AddressableLightEffect {
|
||||
public:
|
||||
AddressableLambdaLightEffect(const std::string &name,
|
||||
const std::function<void(AddressableLight &, ESPColor, bool initial_run)> &f,
|
||||
const std::function<void(AddressableLight &, Color, bool initial_run)> &f,
|
||||
uint32_t update_interval)
|
||||
: AddressableLightEffect(name), f_(f), update_interval_(update_interval) {}
|
||||
void start() override { this->initial_run_ = true; }
|
||||
void apply(AddressableLight &it, const ESPColor ¤t_color) override {
|
||||
void apply(AddressableLight &it, const Color ¤t_color) override {
|
||||
const uint32_t now = millis();
|
||||
if (now - this->last_run_ >= this->update_interval_) {
|
||||
this->last_run_ = now;
|
||||
@ -65,7 +65,7 @@ class AddressableLambdaLightEffect : public AddressableLightEffect {
|
||||
}
|
||||
|
||||
protected:
|
||||
std::function<void(AddressableLight &, ESPColor, bool initial_run)> f_;
|
||||
std::function<void(AddressableLight &, Color, bool initial_run)> f_;
|
||||
uint32_t update_interval_;
|
||||
uint32_t last_run_{0};
|
||||
bool initial_run_;
|
||||
@ -74,7 +74,7 @@ class AddressableLambdaLightEffect : public AddressableLightEffect {
|
||||
class AddressableRainbowLightEffect : public AddressableLightEffect {
|
||||
public:
|
||||
explicit AddressableRainbowLightEffect(const std::string &name) : AddressableLightEffect(name) {}
|
||||
void apply(AddressableLight &it, const ESPColor ¤t_color) override {
|
||||
void apply(AddressableLight &it, const Color ¤t_color) override {
|
||||
ESPHSVColor hsv;
|
||||
hsv.value = 255;
|
||||
hsv.saturation = 240;
|
||||
@ -106,7 +106,7 @@ class AddressableColorWipeEffect : public AddressableLightEffect {
|
||||
void set_colors(const std::vector<AddressableColorWipeEffectColor> &colors) { this->colors_ = colors; }
|
||||
void set_add_led_interval(uint32_t add_led_interval) { this->add_led_interval_ = add_led_interval; }
|
||||
void set_reverse(bool reverse) { this->reverse_ = reverse; }
|
||||
void apply(AddressableLight &it, const ESPColor ¤t_color) override {
|
||||
void apply(AddressableLight &it, const Color ¤t_color) override {
|
||||
const uint32_t now = millis();
|
||||
if (now - this->last_add_ < this->add_led_interval_)
|
||||
return;
|
||||
@ -116,7 +116,7 @@ class AddressableColorWipeEffect : public AddressableLightEffect {
|
||||
else
|
||||
it.shift_right(1);
|
||||
const AddressableColorWipeEffectColor color = this->colors_[this->at_color_];
|
||||
const ESPColor esp_color = ESPColor(color.r, color.g, color.b, color.w);
|
||||
const Color esp_color = Color(color.r, color.g, color.b, color.w);
|
||||
if (this->reverse_)
|
||||
it[-1] = esp_color;
|
||||
else
|
||||
@ -126,7 +126,7 @@ class AddressableColorWipeEffect : public AddressableLightEffect {
|
||||
this->at_color_ = (this->at_color_ + 1) % this->colors_.size();
|
||||
AddressableColorWipeEffectColor &new_color = this->colors_[this->at_color_];
|
||||
if (new_color.random) {
|
||||
ESPColor c = ESPColor::random_color();
|
||||
Color c = Color::random_color();
|
||||
new_color.r = c.r;
|
||||
new_color.g = c.g;
|
||||
new_color.b = c.b;
|
||||
@ -148,8 +148,8 @@ class AddressableScanEffect : public AddressableLightEffect {
|
||||
explicit AddressableScanEffect(const std::string &name) : AddressableLightEffect(name) {}
|
||||
void set_move_interval(uint32_t move_interval) { this->move_interval_ = move_interval; }
|
||||
void set_scan_width(uint32_t scan_width) { this->scan_width_ = scan_width; }
|
||||
void apply(AddressableLight &it, const ESPColor ¤t_color) override {
|
||||
it.all() = ESPColor::BLACK;
|
||||
void apply(AddressableLight &it, const Color ¤t_color) override {
|
||||
it.all() = COLOR_BLACK;
|
||||
|
||||
for (auto i = 0; i < this->scan_width_; i++) {
|
||||
it[this->at_led_ + i] = current_color;
|
||||
@ -181,7 +181,7 @@ class AddressableScanEffect : public AddressableLightEffect {
|
||||
class AddressableTwinkleEffect : public AddressableLightEffect {
|
||||
public:
|
||||
explicit AddressableTwinkleEffect(const std::string &name) : AddressableLightEffect(name) {}
|
||||
void apply(AddressableLight &addressable, const ESPColor ¤t_color) override {
|
||||
void apply(AddressableLight &addressable, const Color ¤t_color) override {
|
||||
const uint32_t now = millis();
|
||||
uint8_t pos_add = 0;
|
||||
if (now - this->last_progress_ > this->progress_interval_) {
|
||||
@ -199,7 +199,7 @@ class AddressableTwinkleEffect : public AddressableLightEffect {
|
||||
else
|
||||
view.set_effect_data(new_pos);
|
||||
} else {
|
||||
view = ESPColor::BLACK;
|
||||
view = COLOR_BLACK;
|
||||
}
|
||||
}
|
||||
while (random_float() < this->twinkle_probability_) {
|
||||
@ -221,7 +221,7 @@ class AddressableTwinkleEffect : public AddressableLightEffect {
|
||||
class AddressableRandomTwinkleEffect : public AddressableLightEffect {
|
||||
public:
|
||||
explicit AddressableRandomTwinkleEffect(const std::string &name) : AddressableLightEffect(name) {}
|
||||
void apply(AddressableLight &it, const ESPColor ¤t_color) override {
|
||||
void apply(AddressableLight &it, const Color ¤t_color) override {
|
||||
const uint32_t now = millis();
|
||||
uint8_t pos_add = 0;
|
||||
if (now - this->last_progress_ > this->progress_interval_) {
|
||||
@ -237,7 +237,7 @@ class AddressableRandomTwinkleEffect : public AddressableLightEffect {
|
||||
if (color == 0) {
|
||||
view = current_color * sine;
|
||||
} else {
|
||||
view = ESPColor(((color >> 2) & 1) * sine, ((color >> 1) & 1) * sine, ((color >> 0) & 1) * sine);
|
||||
view = Color(((color >> 2) & 1) * sine, ((color >> 1) & 1) * sine, ((color >> 0) & 1) * sine);
|
||||
}
|
||||
const uint8_t new_x = x + pos_add;
|
||||
if (new_x > 0b11111)
|
||||
@ -245,7 +245,7 @@ class AddressableRandomTwinkleEffect : public AddressableLightEffect {
|
||||
else
|
||||
view.set_effect_data((new_x << 3) | color);
|
||||
} else {
|
||||
view = ESPColor(0, 0, 0, 0);
|
||||
view = Color(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
while (random_float() < this->twinkle_probability_) {
|
||||
@ -270,9 +270,9 @@ class AddressableFireworksEffect : public AddressableLightEffect {
|
||||
explicit AddressableFireworksEffect(const std::string &name) : AddressableLightEffect(name) {}
|
||||
void start() override {
|
||||
auto &it = *this->get_addressable_();
|
||||
it.all() = ESPColor::BLACK;
|
||||
it.all() = COLOR_BLACK;
|
||||
}
|
||||
void apply(AddressableLight &it, const ESPColor ¤t_color) override {
|
||||
void apply(AddressableLight &it, const Color ¤t_color) override {
|
||||
const uint32_t now = millis();
|
||||
if (now - this->last_update_ < this->update_interval_)
|
||||
return;
|
||||
@ -280,7 +280,7 @@ class AddressableFireworksEffect : public AddressableLightEffect {
|
||||
// "invert" the fade out parameter so that higher values make fade out faster
|
||||
const uint8_t fade_out_mult = 255u - this->fade_out_rate_;
|
||||
for (auto view : it) {
|
||||
ESPColor target = view.get() * fade_out_mult;
|
||||
Color target = view.get() * fade_out_mult;
|
||||
if (target.r < 64)
|
||||
target *= 170;
|
||||
view = target;
|
||||
@ -294,7 +294,7 @@ class AddressableFireworksEffect : public AddressableLightEffect {
|
||||
if (random_float() < this->spark_probability_) {
|
||||
const size_t pos = random_uint32() % it.size();
|
||||
if (this->use_random_color_) {
|
||||
it[pos] = ESPColor::random_color();
|
||||
it[pos] = Color::random_color();
|
||||
} else {
|
||||
it[pos] = current_color;
|
||||
}
|
||||
@ -316,7 +316,7 @@ class AddressableFireworksEffect : public AddressableLightEffect {
|
||||
class AddressableFlickerEffect : public AddressableLightEffect {
|
||||
public:
|
||||
explicit AddressableFlickerEffect(const std::string &name) : AddressableLightEffect(name) {}
|
||||
void apply(AddressableLight &it, const ESPColor ¤t_color) override {
|
||||
void apply(AddressableLight &it, const Color ¤t_color) override {
|
||||
const uint32_t now = millis();
|
||||
const uint8_t intensity = this->intensity_;
|
||||
const uint8_t inv_intensity = 255 - intensity;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
|
||||
from esphome.const import CONF_NAME, CONF_LAMBDA, CONF_UPDATE_INTERVAL, CONF_TRANSITION_LENGTH, \
|
||||
CONF_COLORS, CONF_STATE, CONF_DURATION, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, \
|
||||
CONF_WHITE, CONF_ALPHA, CONF_INTENSITY, CONF_SPEED, CONF_WIDTH, CONF_NUM_LEDS, CONF_RANDOM, \
|
||||
@ -11,7 +12,7 @@ from .types import LambdaLightEffect, RandomLightEffect, StrobeLightEffect, \
|
||||
FlickerLightEffect, AddressableRainbowLightEffect, AddressableColorWipeEffect, \
|
||||
AddressableColorWipeEffectColor, AddressableScanEffect, AddressableTwinkleEffect, \
|
||||
AddressableRandomTwinkleEffect, AddressableFireworksEffect, AddressableFlickerEffect, \
|
||||
AutomationLightEffect, ESPColor
|
||||
AutomationLightEffect, Color
|
||||
|
||||
CONF_ADD_LED_INTERVAL = 'add_led_interval'
|
||||
CONF_REVERSE = 'reverse'
|
||||
@ -162,7 +163,7 @@ def flicker_effect_to_code(config, effect_id):
|
||||
}
|
||||
)
|
||||
def addressable_lambda_effect_to_code(config, effect_id):
|
||||
args = [(AddressableLightRef, 'it'), (ESPColor, 'current_color'), (bool, 'initial_run')]
|
||||
args = [(AddressableLightRef, 'it'), (Color, 'current_color'), (bool, 'initial_run')]
|
||||
lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], args, return_type=cg.void)
|
||||
var = cg.new_Pvariable(effect_id, config[CONF_NAME], lambda_,
|
||||
config[CONF_UPDATE_INTERVAL])
|
||||
|
@ -10,7 +10,7 @@ LightOutput = light_ns.class_('LightOutput')
|
||||
AddressableLight = light_ns.class_('AddressableLight', cg.Component)
|
||||
AddressableLightRef = AddressableLight.operator('ref')
|
||||
|
||||
ESPColor = light_ns.class_('ESPColor')
|
||||
Color = cg.esphome_ns.class_('Color')
|
||||
LightColorValues = light_ns.class_('LightColorValues')
|
||||
|
||||
# Actions
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/color.h"
|
||||
#include "esphome/components/light/light_output.h"
|
||||
#include "esphome/components/light/addressable_light.h"
|
||||
|
||||
@ -73,7 +74,7 @@ class NeoPixelBusLightOutputBase : public light::AddressableLight {
|
||||
// ========== INTERNAL METHODS ==========
|
||||
void setup() override {
|
||||
for (int i = 0; i < this->size(); i++) {
|
||||
(*this)[i] = light::ESPColor(0, 0, 0, 0);
|
||||
(*this)[i] = Color(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
this->effect_data_ = new uint8_t[this->size()];
|
||||
|
@ -162,7 +162,7 @@ size_t SSD1322::get_buffer_length_() {
|
||||
void HOT SSD1322::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
|
||||
return;
|
||||
uint32_t color4 = color.to_grayscale4();
|
||||
uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
|
||||
// where should the bits go in the big buffer array? math...
|
||||
uint16_t pos = (x / SSD1322_PIXELSPERBYTE) + (y * this->get_width_internal() / SSD1322_PIXELSPERBYTE);
|
||||
uint8_t shift = (1u - (x % SSD1322_PIXELSPERBYTE)) * SSD1322_COLORSHIFT;
|
||||
@ -174,7 +174,7 @@ void HOT SSD1322::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
this->buffer_[pos] |= color4;
|
||||
}
|
||||
void SSD1322::fill(Color color) {
|
||||
const uint32_t color4 = color.to_grayscale4();
|
||||
const uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
|
||||
uint8_t fill = (color4 & SSD1322_COLORMASK) | ((color4 & SSD1322_COLORMASK) << SSD1322_COLORSHIFT);
|
||||
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
||||
this->buffer_[i] = fill;
|
||||
|
@ -192,7 +192,7 @@ size_t SSD1325::get_buffer_length_() {
|
||||
void HOT SSD1325::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
|
||||
return;
|
||||
uint32_t color4 = color.to_grayscale4();
|
||||
uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
|
||||
// where should the bits go in the big buffer array? math...
|
||||
uint16_t pos = (x / SSD1325_PIXELSPERBYTE) + (y * this->get_width_internal() / SSD1325_PIXELSPERBYTE);
|
||||
uint8_t shift = (x % SSD1325_PIXELSPERBYTE) * SSD1325_COLORSHIFT;
|
||||
@ -204,7 +204,7 @@ void HOT SSD1325::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
this->buffer_[pos] |= color4;
|
||||
}
|
||||
void SSD1325::fill(Color color) {
|
||||
const uint32_t color4 = color.to_grayscale4();
|
||||
const uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
|
||||
uint8_t fill = (color4 & SSD1325_COLORMASK) | ((color4 & SSD1325_COLORMASK) << SSD1325_COLORSHIFT);
|
||||
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
||||
this->buffer_[i] = fill;
|
||||
|
@ -136,7 +136,7 @@ size_t SSD1327::get_buffer_length_() {
|
||||
void HOT SSD1327::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
|
||||
return;
|
||||
uint32_t color4 = color.to_grayscale4();
|
||||
uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
|
||||
// where should the bits go in the big buffer array? math...
|
||||
uint16_t pos = (x / SSD1327_PIXELSPERBYTE) + (y * this->get_width_internal() / SSD1327_PIXELSPERBYTE);
|
||||
uint8_t shift = (x % SSD1327_PIXELSPERBYTE) * SSD1327_COLORSHIFT;
|
||||
@ -148,7 +148,7 @@ void HOT SSD1327::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
this->buffer_[pos] |= color4;
|
||||
}
|
||||
void SSD1327::fill(Color color) {
|
||||
const uint32_t color4 = color.to_grayscale4();
|
||||
const uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
|
||||
uint8_t fill = (color4 & SSD1327_COLORMASK) | ((color4 & SSD1327_COLORMASK) << SSD1327_COLORSHIFT);
|
||||
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
||||
this->buffer_[i] = fill;
|
||||
|
@ -123,14 +123,14 @@ size_t SSD1331::get_buffer_length_() {
|
||||
void HOT SSD1331::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
|
||||
return;
|
||||
const uint32_t color565 = color.to_rgb_565();
|
||||
const uint32_t color565 = display::ColorUtil::color_to_565(color);
|
||||
// where should the bits go in the big buffer array? math...
|
||||
uint16_t pos = (x + y * this->get_width_internal()) * SSD1331_BYTESPERPIXEL;
|
||||
this->buffer_[pos++] = (color565 >> 8) & 0xff;
|
||||
this->buffer_[pos] = color565 & 0xff;
|
||||
}
|
||||
void SSD1331::fill(Color color) {
|
||||
const uint32_t color565 = color.to_rgb_565();
|
||||
const uint32_t color565 = display::ColorUtil::color_to_565(color);
|
||||
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
||||
if (i & 1) {
|
||||
this->buffer_[i] = color565 & 0xff;
|
||||
|
@ -151,14 +151,14 @@ size_t SSD1351::get_buffer_length_() {
|
||||
void HOT SSD1351::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
|
||||
return;
|
||||
const uint32_t color565 = color.to_rgb_565();
|
||||
const uint32_t color565 = display::ColorUtil::color_to_565(color);
|
||||
// where should the bits go in the big buffer array? math...
|
||||
uint16_t pos = (x + y * this->get_width_internal()) * SSD1351_BYTESPERPIXEL;
|
||||
this->buffer_[pos++] = (color565 >> 8) & 0xff;
|
||||
this->buffer_[pos] = color565 & 0xff;
|
||||
}
|
||||
void SSD1351::fill(Color color) {
|
||||
const uint32_t color565 = color.to_rgb_565();
|
||||
const uint32_t color565 = display::ColorUtil::color_to_565(color);
|
||||
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
|
||||
if (i & 1) {
|
||||
this->buffer_[i] = color565 & 0xff;
|
||||
|
@ -308,11 +308,11 @@ void HOT ST7735::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
return;
|
||||
|
||||
if (this->eightbitcolor_) {
|
||||
const uint32_t color332 = color.to_332();
|
||||
const uint32_t color332 = display::ColorUtil::color_to_332(color);
|
||||
uint16_t pos = (x + y * this->get_width_internal());
|
||||
this->buffer_[pos] = color332;
|
||||
} else {
|
||||
const uint32_t color565 = color.to_565();
|
||||
const uint32_t color565 = display::ColorUtil::color_to_565(color);
|
||||
uint16_t pos = (x + y * this->get_width_internal()) * 2;
|
||||
this->buffer_[pos++] = (color565 >> 8) & 0xff;
|
||||
this->buffer_[pos] = color565 & 0xff;
|
||||
@ -444,9 +444,11 @@ void HOT ST7735::write_display_data_() {
|
||||
if (this->eightbitcolor_) {
|
||||
for (int line = 0; line < this->get_buffer_length(); line = line + this->get_width_internal()) {
|
||||
for (int index = 0; index < this->get_width_internal(); ++index) {
|
||||
auto color = Color(this->buffer_[index + line], Color::ColorOrder::COLOR_ORDER_RGB,
|
||||
Color::ColorBitness::COLOR_BITNESS_332, true)
|
||||
.to_565();
|
||||
auto color332 = display::ColorUtil::to_color(this->buffer_[index + line], display::ColorOrder::COLOR_ORDER_RGB,
|
||||
display::ColorBitness::COLOR_BITNESS_332, true);
|
||||
|
||||
auto color = display::ColorUtil::color_to_565(color332);
|
||||
|
||||
this->write_byte((color >> 8) & 0xff);
|
||||
this->write_byte(color & 0xff);
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ void HOT ST7789V::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
|
||||
return;
|
||||
|
||||
auto color565 = color.to_rgb_565();
|
||||
auto color565 = display::ColorUtil::color_to_565(color);
|
||||
|
||||
uint16_t pos = (x + y * this->get_width_internal()) * 2;
|
||||
this->buffer_[pos++] = (color565 >> 8) & 0xff;
|
||||
|
@ -40,11 +40,11 @@ void WLEDLightEffect::stop() {
|
||||
|
||||
void WLEDLightEffect::blank_all_leds_(light::AddressableLight &it) {
|
||||
for (int led = it.size(); led-- > 0;) {
|
||||
it[led].set(light::ESPColor::BLACK);
|
||||
it[led].set(COLOR_BLACK);
|
||||
}
|
||||
}
|
||||
|
||||
void WLEDLightEffect::apply(light::AddressableLight &it, const light::ESPColor ¤t_color) {
|
||||
void WLEDLightEffect::apply(light::AddressableLight &it, const Color ¤t_color) {
|
||||
// Init UDP lazily
|
||||
if (!udp_) {
|
||||
udp_.reset(new WiFiUDP());
|
||||
@ -152,7 +152,7 @@ bool WLEDLightEffect::parse_warls_frame_(light::AddressableLight &it, const uint
|
||||
uint8_t b = payload[3];
|
||||
|
||||
if (led < max_leds) {
|
||||
it[led].set(light::ESPColor(r, g, b));
|
||||
it[led].set(Color(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ bool WLEDLightEffect::parse_drgb_frame_(light::AddressableLight &it, const uint8
|
||||
uint8_t b = payload[2];
|
||||
|
||||
if (led < max_leds) {
|
||||
it[led].set(light::ESPColor(r, g, b));
|
||||
it[led].set(Color(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ bool WLEDLightEffect::parse_drgbw_frame_(light::AddressableLight &it, const uint
|
||||
uint8_t w = payload[3];
|
||||
|
||||
if (led < max_leds) {
|
||||
it[led].set(light::ESPColor(r, g, b, w));
|
||||
it[led].set(Color(r, g, b, w));
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,7 +228,7 @@ bool WLEDLightEffect::parse_dnrgb_frame_(light::AddressableLight &it, const uint
|
||||
uint8_t b = payload[2];
|
||||
|
||||
if (led < max_leds) {
|
||||
it[led].set(light::ESPColor(r, g, b));
|
||||
it[led].set(Color(r, g, b));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ class WLEDLightEffect : public light::AddressableLightEffect {
|
||||
public:
|
||||
void start() override;
|
||||
void stop() override;
|
||||
void apply(light::AddressableLight &it, const light::ESPColor ¤t_color) override;
|
||||
void apply(light::AddressableLight &it, const Color ¤t_color) override;
|
||||
void set_port(uint16_t port) { this->port_ = port; }
|
||||
|
||||
protected:
|
||||
|
@ -6,7 +6,6 @@
|
||||
namespace esphome {
|
||||
|
||||
inline static uint8_t esp_scale8(uint8_t i, uint8_t scale) { return (uint16_t(i) * (1 + uint16_t(scale))) / 256; }
|
||||
inline static uint8_t esp_scale(uint8_t i, uint8_t scale, uint8_t max_value = 255) { return (max_value * i / scale); }
|
||||
|
||||
struct Color {
|
||||
union {
|
||||
@ -31,75 +30,19 @@ struct Color {
|
||||
uint8_t raw[4];
|
||||
uint32_t raw_32;
|
||||
};
|
||||
enum ColorOrder : uint8_t { COLOR_ORDER_RGB = 0, COLOR_ORDER_BGR = 1, COLOR_ORDER_GRB = 2 };
|
||||
enum ColorBitness : uint8_t { COLOR_BITNESS_888 = 0, COLOR_BITNESS_565 = 1, COLOR_BITNESS_332 = 2 };
|
||||
|
||||
inline Color() ALWAYS_INLINE : r(0), g(0), b(0), w(0) {} // NOLINT
|
||||
inline Color(float red, float green, float blue) ALWAYS_INLINE : r(uint8_t(red * 255)),
|
||||
g(uint8_t(green * 255)),
|
||||
b(uint8_t(blue * 255)),
|
||||
w(0) {}
|
||||
inline Color(float red, float green, float blue, float white) ALWAYS_INLINE : r(uint8_t(red * 255)),
|
||||
g(uint8_t(green * 255)),
|
||||
b(uint8_t(blue * 255)),
|
||||
w(uint8_t(white * 255)) {}
|
||||
inline Color(uint8_t red, uint8_t green, uint8_t blue) ALWAYS_INLINE : r(red), g(green), b(blue), w(0) {}
|
||||
|
||||
inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) ALWAYS_INLINE : r(red),
|
||||
g(green),
|
||||
b(blue),
|
||||
w(white) {}
|
||||
inline Color(uint32_t colorcode) ALWAYS_INLINE : r((colorcode >> 16) & 0xFF),
|
||||
g((colorcode >> 8) & 0xFF),
|
||||
b((colorcode >> 0) & 0xFF),
|
||||
w((colorcode >> 24) & 0xFF) {}
|
||||
inline Color(uint32_t colorcode, ColorOrder color_order, ColorBitness color_bitness = ColorBitness::COLOR_BITNESS_888,
|
||||
bool right_bit_aligned = true) {
|
||||
uint8_t first_color, second_color, third_color;
|
||||
uint8_t first_bits = 0;
|
||||
uint8_t second_bits = 0;
|
||||
uint8_t third_bits = 0;
|
||||
|
||||
switch (color_bitness) {
|
||||
case COLOR_BITNESS_888:
|
||||
first_bits = 8;
|
||||
second_bits = 8;
|
||||
third_bits = 8;
|
||||
break;
|
||||
case COLOR_BITNESS_565:
|
||||
first_bits = 5;
|
||||
second_bits = 6;
|
||||
third_bits = 5;
|
||||
break;
|
||||
case COLOR_BITNESS_332:
|
||||
first_bits = 3;
|
||||
second_bits = 3;
|
||||
third_bits = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
first_color = right_bit_aligned ? esp_scale(((colorcode >> (second_bits + third_bits)) & ((1 << first_bits) - 1)),
|
||||
((1 << first_bits) - 1))
|
||||
: esp_scale(((colorcode >> 16) & 0xFF), (1 << first_bits) - 1);
|
||||
|
||||
second_color = right_bit_aligned
|
||||
? esp_scale(((colorcode >> third_bits) & ((1 << second_bits) - 1)), ((1 << second_bits) - 1))
|
||||
: esp_scale(((colorcode >> 8) & 0xFF), ((1 << second_bits) - 1));
|
||||
|
||||
third_color = (right_bit_aligned ? esp_scale(((colorcode >> 0) & 0xFF), ((1 << third_bits) - 1))
|
||||
: esp_scale(((colorcode >> 0) & 0xFF), (1 << third_bits) - 1));
|
||||
|
||||
switch (color_order) {
|
||||
case COLOR_ORDER_RGB:
|
||||
this->r = first_color;
|
||||
this->g = second_color;
|
||||
this->b = third_color;
|
||||
break;
|
||||
case COLOR_ORDER_BGR:
|
||||
this->b = first_color;
|
||||
this->g = second_color;
|
||||
this->r = third_color;
|
||||
break;
|
||||
case COLOR_ORDER_GRB:
|
||||
this->g = first_color;
|
||||
this->r = second_color;
|
||||
this->b = third_color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
inline bool is_on() ALWAYS_INLINE { return this->raw_32 != 0; }
|
||||
inline Color &operator=(const Color &rhs) ALWAYS_INLINE {
|
||||
this->r = rhs.r;
|
||||
@ -187,65 +130,21 @@ struct Color {
|
||||
}
|
||||
inline Color &operator-=(uint8_t subtract) ALWAYS_INLINE { return *this = (*this) - subtract; }
|
||||
static Color random_color() {
|
||||
float r = float(random_uint32()) / float(UINT32_MAX);
|
||||
float g = float(random_uint32()) / float(UINT32_MAX);
|
||||
float b = float(random_uint32()) / float(UINT32_MAX);
|
||||
float w = float(random_uint32()) / float(UINT32_MAX);
|
||||
return Color(r, g, b, w);
|
||||
uint32_t rand = random_uint32();
|
||||
uint8_t w = rand >> 24;
|
||||
uint8_t r = rand >> 16;
|
||||
uint8_t g = rand >> 8;
|
||||
uint8_t b = rand >> 0;
|
||||
const uint16_t max_rgb = std::max(r, std::max(g, b));
|
||||
return Color(uint8_t((uint16_t(r) * 255U / max_rgb)), uint8_t((uint16_t(g) * 255U / max_rgb)),
|
||||
uint8_t((uint16_t(b) * 255U / max_rgb)), w);
|
||||
}
|
||||
Color fade_to_white(uint8_t amnt) { return Color(1, 1, 1, 1) - (*this * amnt); }
|
||||
Color fade_to_white(uint8_t amnt) { return Color(255, 255, 255, 255) - (*this * amnt); }
|
||||
Color fade_to_black(uint8_t amnt) { return *this * amnt; }
|
||||
Color lighten(uint8_t delta) { return *this + delta; }
|
||||
Color darken(uint8_t delta) { return *this - delta; }
|
||||
uint8_t to_332(ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) const {
|
||||
uint16_t red_color, green_color, blue_color;
|
||||
|
||||
red_color = esp_scale8(this->red, ((1 << 3) - 1));
|
||||
green_color = esp_scale8(this->green, ((1 << 3) - 1));
|
||||
blue_color = esp_scale8(this->blue, (1 << 2) - 1);
|
||||
|
||||
switch (color_order) {
|
||||
case COLOR_ORDER_RGB:
|
||||
return red_color << 5 | green_color << 2 | blue_color;
|
||||
case COLOR_ORDER_BGR:
|
||||
return blue_color << 6 | green_color << 3 | red_color;
|
||||
case COLOR_ORDER_GRB:
|
||||
return green_color << 5 | red_color << 2 | blue_color;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
uint16_t to_565(ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) const {
|
||||
uint16_t red_color, green_color, blue_color;
|
||||
|
||||
red_color = esp_scale8(this->red, ((1 << 5) - 1));
|
||||
green_color = esp_scale8(this->green, ((1 << 6) - 1));
|
||||
blue_color = esp_scale8(this->blue, (1 << 5) - 1);
|
||||
|
||||
switch (color_order) {
|
||||
case COLOR_ORDER_RGB:
|
||||
return red_color << 11 | green_color << 5 | blue_color;
|
||||
case COLOR_ORDER_BGR:
|
||||
return blue_color << 11 | green_color << 5 | red_color;
|
||||
case COLOR_ORDER_GRB:
|
||||
return green_color << 10 | red_color << 5 | blue_color;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
uint32_t to_rgb_565() const {
|
||||
uint32_t color565 =
|
||||
(esp_scale8(this->red, 31) << 11) | (esp_scale8(this->green, 63) << 5) | (esp_scale8(this->blue, 31) << 0);
|
||||
return color565;
|
||||
}
|
||||
uint32_t to_bgr_565() const {
|
||||
uint32_t color565 =
|
||||
(esp_scale8(this->blue, 31) << 11) | (esp_scale8(this->green, 63) << 5) | (esp_scale8(this->red, 31) << 0);
|
||||
return color565;
|
||||
}
|
||||
uint32_t to_grayscale4() const {
|
||||
uint32_t gs4 = esp_scale8(this->white, 15);
|
||||
return gs4;
|
||||
}
|
||||
};
|
||||
|
||||
static const Color COLOR_BLACK(0, 0, 0);
|
||||
static const Color COLOR_WHITE(1, 1, 1);
|
||||
static const Color COLOR_WHITE(255, 255, 255, 255);
|
||||
}; // namespace esphome
|
||||
|
@ -1693,7 +1693,7 @@ interval:
|
||||
color:
|
||||
- id: kbx_red
|
||||
red: 100%
|
||||
green: 1%
|
||||
green_int: 123
|
||||
blue: 2%
|
||||
- id: kbx_blue
|
||||
red: 0%
|
||||
|
Loading…
Reference in New Issue
Block a user