feat: add rainbow effect for segments

This commit is contained in:
Philip Stark 2023-05-12 17:16:24 +02:00
parent dd1408c5cb
commit b712b90be1
3 changed files with 93 additions and 25 deletions

View file

@ -80,23 +80,31 @@ void Wordclock::update() {
// Color on = this->on_color * this->on_transformer->apply().value_or(255); // Color on = this->on_color * this->on_transformer->apply().value_or(255);
// Color off = this->off_color * this->off_transformer->apply().value_or(255); // Color off = this->off_color * this->off_transformer->apply().value_or(255);
this->current_position = 0;
uint8_t transition_progress = this->on_transformer->apply().value_or(255); uint8_t transition_progress = this->on_transformer->apply().value_or(255);
// uint8_t on_progress = this->on_transformer->apply().value_or(255); // uint8_t on_progress = this->on_transformer->apply().value_or(255);
// uint8_t off_progress = this->off_transformer->apply().value_or(255); // uint8_t off_progress = this->off_transformer->apply().value_or(255);
// ESP_LOGD("wordclock.cpp", "off progress [%d]", off_progress); // ESP_LOGD("wordclock.cpp", "off progress [%d]", off_progress);
Color added_color = this->off_color.gradient(this->on_color, transition_progress); // Color added_color = this->off_color.gradient(this->on_color, transition_progress);
Color removed_color = this->on_color.gradient(this->off_color, transition_progress); Color removed_color = this->on_color.gradient(this->off_color, transition_progress);
// ESP_LOGD("wordclock.cpp", "transition progress [%d], added [0x%06x], removed [0x%06x]", transition_progress, added_color.raw_32, removed_color.raw_32); // ESP_LOGD("wordclock.cpp", "transition progress [%d], added [0x%06x], removed [0x%06x]", transition_progress, added_color.raw_32, removed_color.raw_32);
for (uint16_t segment_idx : *this->added_segments) {
// ESP_LOGD("wordclock.cpp", "on [%d]", segment_idx);
this->draw_segment(segment_idx, added_color);
// this->draw_segment(segment_idx, on_progress);
}
for (uint16_t segment_idx : *this->removed_segments) { for (uint16_t segment_idx : *this->removed_segments) {
// ESP_LOGD("wordclock.cpp", "off [%d]", segment_idx); // ESP_LOGD("wordclock.cpp", "off [%d]", segment_idx);
this->draw_segment(segment_idx, removed_color); // this->disable_segment(segment_idx, this->off_color, transition_progress);
this->disable_segment_effect(segment_idx, this->off_color, transition_progress);
// this->disable_segment(segment_idx, removed_color);
// this->draw_segment(segment_idx, off_progress); // this->draw_segment(segment_idx, off_progress);
} }
for (uint16_t segment_idx : *this->added_segments) {
// ESP_LOGD("wordclock.cpp", "on [%d]", segment_idx);
// this->segment_effect_base(segment_idx, this->off_color, transition_progress);
this->enable_segment_effect(segment_idx, this->off_color, transition_progress);
// this->draw_segment(segment_idx, on_progress);
}
for (uint16_t segment_idx : *this->staying_segments) {
this->apply_segment_effect(segment_idx);
}
} }
} }
@ -106,6 +114,8 @@ void Wordclock::find_difference(std::vector<uint16_t> *a_vec, std::vector<uint16
// } // }
this->added_segments->clear(); this->added_segments->clear();
this->removed_segments->clear(); this->removed_segments->clear();
this->staying_segments->clear();
auto a = a_vec->begin(); auto a = a_vec->begin();
auto b = b_vec->begin(); auto b = b_vec->begin();
@ -115,10 +125,22 @@ void Wordclock::find_difference(std::vector<uint16_t> *a_vec, std::vector<uint16
else if (b == b_vec->end()) { this->removed_segments->push_back(*a); a++; } else if (b == b_vec->end()) { this->removed_segments->push_back(*a); a++; }
else if (*a > *b) { this->added_segments-> push_back(*b); b++; } else if (*a > *b) { this->added_segments-> push_back(*b); b++; }
else if (*a < *b) { this->removed_segments->push_back(*a); a++; } else if (*a < *b) { this->removed_segments->push_back(*a); a++; }
else if (*a == *b) { a++; b++; } else if (*a == *b) { this->staying_segments->push_back(*a); a++; b++; }
} }
} }
Color Wordclock::get_next_color(uint32_t position, const Color &current_color) {
uint32_t speed_ = 3;
uint16_t width_ = 100;
// uint16_t width_ = 50;
esphome::light::ESPHSVColor hsv;
hsv.value = 255;
hsv.saturation = 240;
hsv.hue = ((millis() * speed_ + (position * (0xFFFF / width_))) % 0xFFFF) >> 8;
// hsv.hue = hue >> 8;
return hsv.to_rgb();
}
int8_t Wordclock::find_hour(uint8_t target_value) { int8_t Wordclock::find_hour(uint8_t target_value) {
std::vector<Hour> *elements = this->hours; std::vector<Hour> *elements = this->hours;
for (int i = 0; i < elements->size(); i++) { for (int i = 0; i < elements->size(); i++) {
@ -184,6 +206,7 @@ Wordclock::Wordclock(
this->added_segments = new std::vector<uint16_t>(); this->added_segments = new std::vector<uint16_t>();
this->removed_segments = new std::vector<uint16_t>(); this->removed_segments = new std::vector<uint16_t>();
this->staying_segments = new std::vector<uint16_t>();
this->on_transformer = new BrightnessTransitionTransformer(); this->on_transformer = new BrightnessTransitionTransformer();
// this->on_transformer->setup(0, this->brightness, 700); // this->on_transformer->setup(0, this->brightness, 700);

View file

@ -164,9 +164,13 @@ protected:
std::vector<uint16_t> *added_segments; std::vector<uint16_t> *added_segments;
std::vector<uint16_t> *removed_segments; std::vector<uint16_t> *removed_segments;
std::vector<uint16_t> *staying_segments;
std::vector<uint16_t> *current_segments; std::vector<uint16_t> *current_segments;
std::vector<uint16_t> *previous_segments; std::vector<uint16_t> *previous_segments;
uint32_t current_position{0};
Color get_next_color(uint32_t position, const Color &current_color);
// Color // Color
// Color get_on_color() { // Color get_on_color() {
// return this->on_color * this->brightness; // return this->on_color * this->brightness;
@ -185,14 +189,63 @@ protected:
// void draw_segment(uint16_t segment_id) { // void draw_segment(uint16_t segment_id) {
// this->draw_segment(segment_id, this->brightness); // this->draw_segment(segment_id, this->brightness);
// } // }
void draw_segment(uint16_t segment_id, uint8_t brightness) { // void draw_segment(uint16_t segment_id, uint8_t brightness) {
this->draw_segment(segment_id, this->on_color * brightness); // this->draw_segment(segment_id, this->on_color * brightness);
} // }
void draw_segment(uint16_t segment_id, Color color) {
SegmentCoords s = this->segments->at(segment_id); // void draw_segment(uint16_t segment_id, Color color) {
// SegmentCoords s = this->segments->at(segment_id);
// // ESP_LOGD("wordclock.cpp", "brightness[%d] * color[%06x] = %06x", brightness, color.raw_32, (color * brightness).raw_32);
// this->display->line(s.x1, s.y1, s.x2, s.y2, color);
// }
void segment_effect_base(uint16_t segment_id, bool to_effect, Color base_color, uint8_t transition_progress) {
// ESP_LOGD("wordclock.cpp", "brightness[%d] * color[%06x] = %06x", brightness, color.raw_32, (color * brightness).raw_32); // ESP_LOGD("wordclock.cpp", "brightness[%d] * color[%06x] = %06x", brightness, color.raw_32, (color * brightness).raw_32);
this->display->line(s.x1, s.y1, s.x2, s.y2, color); SegmentCoords s = this->segments->at(segment_id);
int x1 = s.x1; int y1 = s.y1; int x2 = s.x2; int y2 = s.y2;
Color color_to_draw;
Color effect_color;
const int32_t dx = abs(x2 - x1), sx = x1 < x2 ? 1 : -1;
const int32_t dy = -abs(y2 - y1), sy = y1 < y2 ? 1 : -1;
int32_t err = dx + dy;
while (true) {
effect_color = this->get_next_color(x1 + y1, Color(0));
if (to_effect) {
color_to_draw = base_color.gradient(effect_color, transition_progress);
} else {
color_to_draw = effect_color.gradient(base_color, transition_progress);
// c = base_color.gradient(this->get_next_color(x1 + y1, Color(0)), transition_progress);
} }
this->display->draw_pixel_at(x1, y1, color_to_draw);
// this->display->draw_pixel_at(x1, y1, this->get_next_color(this->current_position++, Color(0)));
if (x1 == x2 && y1 == y2) break;
int32_t e2 = 2 * err;
if (e2 >= dy) {
err += dy;
x1 += sx;
}
if (e2 <= dx) {
err += dx;
y1 += sy;
}
}
}
void enable_segment_effect(uint16_t segment_id, Color off_color, uint8_t transition_progress) {
segment_effect_base(segment_id, true, off_color, transition_progress);
}
void disable_segment_effect(uint16_t segment_id, Color off_color, uint8_t transition_progress) {
segment_effect_base(segment_id, false, off_color, transition_progress);
}
void apply_segment_effect(uint16_t segment_id) {
segment_effect_base(segment_id, true, Color(0), 255);
}
// void disable_segment(uint16_t segment_id, Color off_color, uint8_t transition_progress) {
// SegmentCoords s = this->segments->at(segment_id);
// this->display->line(s.x1, s.y1, s.x2, s.y2, color);
// }
void start_idle_animation() { void start_idle_animation() {
this->display->fill(this->off_color); this->display->fill(this->off_color);
this->display->set_enabled(false); this->display->set_enabled(false);

View file

@ -48,8 +48,6 @@ light:
pin: GPIO3 pin: GPIO3
num_leds: 198 num_leds: 198
restore_mode: ALWAYS_OFF restore_mode: ALWAYS_OFF
# default_transition_length: 0.0s
# default_transition_length: 0.1s
method: method:
type: esp8266_dma type: esp8266_dma
@ -77,21 +75,15 @@ display:
return (y * 18 + mapping_odd[x]); return (y * 18 + mapping_odd[x]);
} }
# color:
# - id: col_on
# hex: "CC0000"
# - id: col_off
# hex: "005500"
color: color:
- id: col_on - id: col_on
red: 90% red: 90%
green: 50% green: 50%
blue: 0% blue: 0%
- id: col_off - id: col_off
red: 20% red: 0%
green: 20% green: 0%
blue: 30% blue: 0%
wordclock: wordclock:
time_id: current_time time_id: current_time