fix when on_boot at 800

This commit is contained in:
J. Nick Koston
2026-04-13 22:40:17 -10:00
parent 12b55f176f
commit c7b4ee5c60
2 changed files with 33 additions and 20 deletions
+30 -19
View File
@@ -59,23 +59,11 @@ void AddressableLightTransformer::start() {
this->light_.correction_.set_local_brightness(255);
this->target_color_ *= to_uint8_scale(end_values.get_brightness() * end_values.get_state());
// When every LED starts at the same color (the common case: plain turn_on/turn_off on a uniform
// strip), interpolate math-only against a single start color. Avoiding the per-step read-back
// through the 8-bit stored byte prevents gamma round-trip quantization from stalling the fade
// at low values (e.g. gamma 2.8 pre-gamma values <27 round to stored 0, freezing progress).
this->uniform_start_color_.reset();
if (this->light_.size() > 0) {
Color first = this->light_[0].get();
bool uniform = true;
for (int32_t i = 1; i < this->light_.size(); i++) {
if (this->light_[i].get() != first) {
uniform = false;
break;
}
}
if (uniform)
this->uniform_start_color_ = first;
}
// Uniformity scan is deferred to the first apply() call. start() can run before the underlying
// LED output's setup() has allocated its frame buffer (e.g. on_boot at priority > HARDWARE
// triggering a transition), and reading through ESPColorView would deref a null buffer.
this->uniform_start_scanned_ = false;
this->uniform_start_is_uniform_ = false;
}
inline constexpr uint8_t subtract_scaled_difference(uint8_t a, uint8_t b, int32_t scale) {
@@ -115,7 +103,30 @@ optional<LightColorValues> AddressableLightTransformer::apply() {
// non-linear when applying small deltas.
if (smoothed_progress > this->last_transition_progress_ && this->last_transition_progress_ < 1.f) {
if (this->uniform_start_color_.has_value()) {
// Lazy uniformity scan: deferred from start() so the LED output's setup() has run and the
// frame buffer is valid. When every LED already has the same color (the common case: plain
// turn_on/turn_off on a uniform strip), interpolate math-only against a single start color.
// Avoiding the per-step read-back through the 8-bit stored byte prevents gamma round-trip
// quantization from stalling the fade at low values (e.g. gamma 2.8 pre-gamma values <27
// round to stored 0, freezing progress).
if (!this->uniform_start_scanned_) {
this->uniform_start_scanned_ = true;
if (this->light_.size() > 0) {
Color first = this->light_[0].get();
bool uniform = true;
for (int32_t i = 1; i < this->light_.size(); i++) {
if (this->light_[i].get() != first) {
uniform = false;
break;
}
}
if (uniform) {
this->uniform_start_color_ = first;
this->uniform_start_is_uniform_ = true;
}
}
}
if (this->uniform_start_is_uniform_) {
// All LEDs started at the same color: compute the interpolated value once and write it to
// every LED. No read-back, so each LED's stored byte advances through every gamma threshold
// as smoothed_progress crosses it, instead of stalling at 0 for low pre-gamma values.
@@ -125,7 +136,7 @@ optional<LightColorValues> AddressableLightTransformer::apply() {
// via its read-back. Concurrent per-LED mutation during a transition isn't a pattern we
// support, so this is acceptable.
// lerp(start, target, progress) via existing helper: target - (target-start)*(1-progress).
const Color &start = *this->uniform_start_color_;
const Color &start = this->uniform_start_color_;
int32_t remaining = int32_t(256.f * (1.f - smoothed_progress));
uint8_t r = subtract_scaled_difference(this->target_color_.red, start.red, remaining);
uint8_t g = subtract_scaled_difference(this->target_color_.green, start.green, remaining);
+3 -1
View File
@@ -115,7 +115,9 @@ class AddressableLightTransformer : public LightTransformer {
AddressableLight &light_;
float last_transition_progress_{0.0f};
Color target_color_{};
optional<Color> uniform_start_color_{};
Color uniform_start_color_{};
bool uniform_start_scanned_{false};
bool uniform_start_is_uniform_{false};
};
} // namespace esphome::light