diff --git a/src/main/drivers/light_ws2811strip.c b/src/main/drivers/light_ws2811strip.c index eb0e1d32f2..0e4d157ce7 100644 --- a/src/main/drivers/light_ws2811strip.c +++ b/src/main/drivers/light_ws2811strip.c @@ -57,6 +57,8 @@ uint32_t ledStripDMABuffer[WS2811_DMA_BUFFER_SIZE]; static ioTag_t ledStripIoTag; static bool ws2811Initialised = false; volatile bool ws2811LedDataTransferInProgress = false; +static unsigned usedLedCount = 0; +static bool needsFullRefresh = true; uint16_t BIT_COMPARE_1 = 0; uint16_t BIT_COMPARE_0 = 0; @@ -87,18 +89,27 @@ void scaleLedValue(uint16_t index, const uint8_t scalePercent) void setStripColor(const hsvColor_t *color) { - for (unsigned index = 0; index < WS2811_DATA_BUFFER_SIZE; index++) { + for (unsigned index = 0; index < usedLedCount; index++) { ledColorBuffer[index] = *color; } } void setStripColors(const hsvColor_t *colors) { - for (unsigned index = 0; index < WS2811_DATA_BUFFER_SIZE; index++) { + for (unsigned index = 0; index < usedLedCount; index++) { setLedHsv(index, colors++); } } +void setUsedLedCount(unsigned ledCount) +{ + usedLedCount = (ledCount < WS2811_DATA_BUFFER_SIZE) ? ledCount : WS2811_DATA_BUFFER_SIZE; + + // Update all possible positions on the next update in case the count + // decreased otherwise LEDs on the end could be left in their previous state + needsFullRefresh = true; +} + void ws2811LedStripInit(ioTag_t ioTag) { memset(ledStripDMABuffer, 0, sizeof(ledStripDMABuffer)); @@ -129,6 +140,7 @@ bool isWS2811LedStripReady(void) STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color, unsigned ledIndex) { + uint32_t packed_colour; switch (ledFormat) { @@ -163,11 +175,14 @@ void ws2811UpdateStrip(ledStripFormatRGB_e ledFormat) // fill transmit buffer with correct compare values to achieve // correct pulse widths according to color values - while (ledIndex < WS2811_DATA_BUFFER_SIZE) { - rgbColor24bpp_t *rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]); + const unsigned ledUpdateCount = needsFullRefresh ? WS2811_DATA_BUFFER_SIZE : usedLedCount; + const hsvColor_t hsvBlack = { 0, 0, 0 }; + while (ledIndex < ledUpdateCount) { + rgbColor24bpp_t *rgb24 = hsvToRgb24(ledIndex < usedLedCount ? &ledColorBuffer[ledIndex] : &hsvBlack); updateLEDDMABuffer(ledFormat, rgb24, ledIndex++); } + needsFullRefresh = false; ws2811LedDataTransferInProgress = true; ws2811LedStripDMAEnable(); diff --git a/src/main/drivers/light_ws2811strip.h b/src/main/drivers/light_ws2811strip.h index 53d40be12f..5da975dc8e 100644 --- a/src/main/drivers/light_ws2811strip.h +++ b/src/main/drivers/light_ws2811strip.h @@ -67,6 +67,8 @@ void setLedValue(uint16_t index, const uint8_t value); void setStripColor(const hsvColor_t *color); void setStripColors(const hsvColor_t *colors); +void setUsedLedCount(unsigned ledCount); + bool isWS2811LedStripReady(void); #if defined(STM32F1) || defined(STM32F3) diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c index b72ac93f72..a57b08ebed 100644 --- a/src/main/io/ledstrip.c +++ b/src/main/io/ledstrip.c @@ -269,6 +269,7 @@ STATIC_UNIT_TESTED void updateLedCount(void) ledCounts.count = count; ledCounts.ring = countRing; ledCounts.larson = countScanner; + setUsedLedCount(ledCounts.count); } void reevaluateLedConfig(void) diff --git a/src/test/unit/ledstrip_unittest.cc b/src/test/unit/ledstrip_unittest.cc index dd651cdbab..2b053c012b 100644 --- a/src/test/unit/ledstrip_unittest.cc +++ b/src/test/unit/ledstrip_unittest.cc @@ -394,4 +394,7 @@ uint8_t getRssiPercent(void) { return 0; } bool isFlipOverAfterCrashActive(void) { return false; } void ws2811LedStripEnable(void) { } + +void setUsedLedCount(unsigned) { }; + }