From b11d5f6799b04585bfe28f35f8eda8e174a90e00 Mon Sep 17 00:00:00 2001 From: Jim Bauwens Date: Sun, 23 May 2021 22:57:48 +0200 Subject: [PATCH] Allow segments in a light partition to be reversed (#1484) Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> --- esphome/components/partition/light.py | 15 +++++++++++++-- esphome/components/partition/light_partition.h | 16 +++++++++++++--- esphome/const.py | 1 + 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/esphome/components/partition/light.py b/esphome/components/partition/light.py index 202481b936..c366aea033 100644 --- a/esphome/components/partition/light.py +++ b/esphome/components/partition/light.py @@ -1,7 +1,14 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import light -from esphome.const import CONF_FROM, CONF_ID, CONF_SEGMENTS, CONF_TO, CONF_OUTPUT_ID +from esphome.const import ( + CONF_FROM, + CONF_ID, + CONF_SEGMENTS, + CONF_TO, + CONF_OUTPUT_ID, + CONF_REVERSED, +) partitions_ns = cg.esphome_ns.namespace("partition") AddressableSegment = partitions_ns.class_("AddressableSegment") @@ -28,6 +35,7 @@ CONFIG_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend( cv.Required(CONF_ID): cv.use_id(light.AddressableLightState), cv.Required(CONF_FROM): cv.positive_int, cv.Required(CONF_TO): cv.positive_int, + cv.Optional(CONF_REVERSED, default=False): cv.boolean, }, validate_from_to, ), @@ -43,7 +51,10 @@ def to_code(config): var = yield cg.get_variable(conf[CONF_ID]) segments.append( AddressableSegment( - var, conf[CONF_FROM], conf[CONF_TO] - conf[CONF_FROM] + 1 + var, + conf[CONF_FROM], + conf[CONF_TO] - conf[CONF_FROM] + 1, + conf[CONF_REVERSED], ) ) diff --git a/esphome/components/partition/light_partition.h b/esphome/components/partition/light_partition.h index 8085c43720..11589ee539 100644 --- a/esphome/components/partition/light_partition.h +++ b/esphome/components/partition/light_partition.h @@ -8,20 +8,25 @@ namespace partition { class AddressableSegment { public: - AddressableSegment(light::LightState *src, int32_t src_offset, int32_t size) - : src_(static_cast(src->get_output())), src_offset_(src_offset), size_(size) {} + AddressableSegment(light::LightState *src, int32_t src_offset, int32_t size, bool reversed) + : src_(static_cast(src->get_output())), + src_offset_(src_offset), + size_(size), + reversed_(reversed) {} light::AddressableLight *get_src() const { return this->src_; } int32_t get_src_offset() const { return this->src_offset_; } int32_t get_size() const { return this->size_; } int32_t get_dst_offset() const { return this->dst_offset_; } void set_dst_offset(int32_t dst_offset) { this->dst_offset_ = dst_offset; } + bool is_reversed() const { return this->reversed_; } protected: light::AddressableLight *src_; int32_t src_offset_; int32_t size_; int32_t dst_offset_; + bool reversed_; }; class PartitionLightOutput : public light::AddressableLight { @@ -72,7 +77,12 @@ class PartitionLightOutput : public light::AddressableLight { // offset within the segment int32_t seg_off = index - seg.get_dst_offset(); // offset within the src - int32_t src_off = seg.get_src_offset() + seg_off; + int32_t src_off; + if (seg.is_reversed()) + src_off = seg.get_src_offset() + seg.get_size() - seg_off - 1; + else + src_off = seg.get_src_offset() + seg_off; + auto view = (*seg.get_src())[src_off]; view.raw_set_color_correction(&this->correction_); return view; diff --git a/esphome/const.py b/esphome/const.py index a70fefa648..e93d2b7d25 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -471,6 +471,7 @@ CONF_RESTORE_STATE = "restore_state" CONF_RESTORE_VALUE = "restore_value" CONF_RETAIN = "retain" CONF_REVERSE_ACTIVE_ENERGY = "reverse_active_energy" +CONF_REVERSED = "reversed" CONF_RGB_ORDER = "rgb_order" CONF_RGBW = "rgbw" CONF_RISING_EDGE = "rising_edge"