From d948ec667e0db828b98f1668ac50a1479880d4ad Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Thu, 26 Mar 2026 12:12:32 +0100 Subject: [PATCH] fast inline color fading for bus drivers based on upstream color_fade() and color_scale() by @DedeHai --- wled00/bus_manager.cpp | 2 +- wled00/bus_manager.h | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 9c093867..47ec11e9 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -1142,7 +1142,7 @@ void __attribute__((hot)) IRAM_ATTR BusHub75Matrix::setPixelColor(uint16_t pix, uint32_t IRAM_ATTR BusHub75Matrix::getPixelColor(uint16_t pix) const { // if (pix >= _len || !_ledBuffer) return BLACK; // not necessary - this was already checked at busses.getPixelColor() #if defined(WLEDMM_FASTPATH) && !defined(WLEDMM_SAVE_FLASH) - return color_fade(uint32_t(_ledBuffer[pix]) & 0x00FFFFFF, _bri); // this is slightly faster if we have inline color_fade() + return color_fade_fast(uint32_t(_ledBuffer[pix]) & 0x00FFFFFF, _bri); // this is slightly faster if we have inline color_fade() #else return uint32_t(_ledBuffer[pix].scale8(_bri)) & 0x00FFFFFF; // do it the FastLED way #endif diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index e61b48e3..9649ba0f 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -32,6 +32,28 @@ bool getBitFromArray(const uint8_t* byteArray, size_t position) __attribute__(( size_t getBitArrayBytes(size_t num_bits) __attribute__((const)); // number of bytes needed for an array with num_bits bits void setBitArray(uint8_t* byteArray, size_t numBits, bool value); // set all bits to same value +/** + * fast color fading / scaling - based on upstream color_fade() and color_scale() by @DedeHai + */ + +// fast color fade without "video" option - fades color toward black +static inline uint32_t color_fade_fast(uint32_t c1, uint_fast8_t amount) { + if (c1 == 0 || amount == 0) return 0; // black or no change + if (amount == 255) return c1; + constexpr uint32_t TWO_CHANNEL_MASK = 0x00FF00FF; + uint32_t rb = c1 & TWO_CHANNEL_MASK; // extract R and B channels + uint32_t wg = (c1 >> 8) & TWO_CHANNEL_MASK; // extract W and G channels (shifted for multiplication) + uint32_t rb_scaled = ((rb * (amount + 1)) >> 8) & TWO_CHANNEL_MASK; // scale red and blue + uint32_t wg_scaled = ((wg * (amount + 1)) & ~TWO_CHANNEL_MASK); // scale white and green + return (rb_scaled | wg_scaled); +} +// faster than fastled color scaling as it does in place scaling +static inline void CRGB_scale_fast(CRGB &c, const uint8_t scale) { + c.r = ((c.r * scale) >> 8); + c.g = ((c.g * scale) >> 8); + c.b = ((c.b * scale) >> 8); +} + #define GET_BIT(var,bit) (((var)>>(bit))&0x01) #define SET_BIT(var,bit) ((var)|=(uint16_t)(0x0001<<(bit)))