From e1f10b0430e736e67a806018ba019d7d116fcb05 Mon Sep 17 00:00:00 2001 From: Bruce Luckcuck Date: Thu, 5 Sep 2019 11:58:54 -0400 Subject: [PATCH] Optimize ledstrip DMA buffer update to reduce task processing time Previous logic was updating updating the DMA buffer for all possible LED positions (32) regardless of how many were used. Since there are 24 bytes per LED, this performed a lot of unnecessary processing in cases where the user had less than 32 LEDs configured. Also includes a bug fix in that if the LED count was decreased (like making changed using the Configurator LED tab), the now unused LEDs at the end of the string would remain on at the last color applied. Now they will be properly turned off. The bug was minor as it was resolved by a reboot, but made setup using the Configurator confusing since changes made are reflected when the user clicked the "Save" button (which does not reboot). --- src/main/drivers/light_ws2811strip.c | 23 +++++++++++++++++++---- src/main/drivers/light_ws2811strip.h | 2 ++ src/main/io/ledstrip.c | 1 + src/test/unit/ledstrip_unittest.cc | 3 +++ 4 files changed, 25 insertions(+), 4 deletions(-) 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) { }; + }