diff --git a/src/main/drivers/light_ws2811strip.c b/src/main/drivers/light_ws2811strip.c index 6df190fbad..776197562b 100644 --- a/src/main/drivers/light_ws2811strip.c +++ b/src/main/drivers/light_ws2811strip.c @@ -52,7 +52,9 @@ FAST_RAM_ZERO_INIT uint32_t ledStripDMABuffer[WS2811_DMA_BUFFER_SIZE]; uint32_t ledStripDMABuffer[WS2811_DMA_BUFFER_SIZE]; #endif -volatile uint8_t ws2811LedDataTransferInProgress = 0; +static ioTag_t ledStripIoTag; +static bool ws2811Initialised = false; +volatile bool ws2811LedDataTransferInProgress = false; uint16_t BIT_COMPARE_1 = 0; uint16_t BIT_COMPARE_0 = 0; @@ -83,16 +85,14 @@ void scaleLedValue(uint16_t index, const uint8_t scalePercent) void setStripColor(const hsvColor_t *color) { - uint16_t index; - for (index = 0; index < WS2811_DATA_BUFFER_SIZE; index++) { + for (unsigned index = 0; index < WS2811_DATA_BUFFER_SIZE; index++) { ledColorBuffer[index] = *color; } } void setStripColors(const hsvColor_t *colors) { - uint16_t index; - for (index = 0; index < WS2811_DATA_BUFFER_SIZE; index++) { + for (unsigned index = 0; index < WS2811_DATA_BUFFER_SIZE; index++) { setLedHsv(index, colors++); } } @@ -100,23 +100,32 @@ void setStripColors(const hsvColor_t *colors) void ws2811LedStripInit(ioTag_t ioTag) { memset(ledStripDMABuffer, 0, sizeof(ledStripDMABuffer)); - ws2811LedStripHardwareInit(ioTag); - const hsvColor_t hsv_black = { 0, 0, 0 }; - setStripColor(&hsv_black); - // RGB or GRB ordering doesn't matter for black - ws2811UpdateStrip(LED_RGB); + ledStripIoTag = ioTag; +} + +void ws2811LedStripEnable(void) +{ + if (!ws2811Initialised) { + if (!ws2811LedStripHardwareInit(ledStripIoTag)) { + return; + } + + const hsvColor_t hsv_black = { 0, 0, 0 }; + setStripColor(&hsv_black); + // RGB or GRB ordering doesn't matter for black + ws2811UpdateStrip(LED_RGB); + + ws2811Initialised = true; + } } bool isWS2811LedStripReady(void) { - return !ws2811LedDataTransferInProgress; + return ws2811Initialised && !ws2811LedDataTransferInProgress; } -STATIC_UNIT_TESTED uint16_t dmaBufferOffset; -static int16_t ledIndex; - -STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color) +STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color, unsigned ledIndex) { uint32_t packed_colour; @@ -131,8 +140,9 @@ STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbCol break; } - for (int8_t index = 23; index >= 0; index--) { - ledStripDMABuffer[dmaBufferOffset++] = (packed_colour & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0; + unsigned dmaBufferOffset = 0; + for (int index = 23; index >= 0; index--) { + ledStripDMABuffer[ledIndex * WS2811_BITS_PER_LED + dmaBufferOffset++] = (packed_colour & (1 << index)) ? BIT_COMPARE_1 : BIT_COMPARE_0; } } @@ -142,28 +152,22 @@ STATIC_UNIT_TESTED void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbCol */ void ws2811UpdateStrip(ledStripFormatRGB_e ledFormat) { - static rgbColor24bpp_t *rgb24; - // don't wait - risk of infinite block, just get an update next time round - if (ws2811LedDataTransferInProgress) { + if (!ws2811Initialised || ws2811LedDataTransferInProgress) { return; } - dmaBufferOffset = 0; // reset buffer memory index - ledIndex = 0; // reset led index + unsigned ledIndex = 0; // reset led index // fill transmit buffer with correct compare values to achieve // correct pulse widths according to color values - while (ledIndex < WS2811_DATA_BUFFER_SIZE) - { - rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]); + while (ledIndex < WS2811_DATA_BUFFER_SIZE) { + rgbColor24bpp_t *rgb24 = hsvToRgb24(&ledColorBuffer[ledIndex]); - updateLEDDMABuffer(ledFormat, rgb24); - - ledIndex++; + updateLEDDMABuffer(ledFormat, rgb24, ledIndex++); } - ws2811LedDataTransferInProgress = 1; + ws2811LedDataTransferInProgress = true; ws2811LedStripDMAEnable(); } diff --git a/src/main/drivers/light_ws2811strip.h b/src/main/drivers/light_ws2811strip.h index 77c15bca71..53d40be12f 100644 --- a/src/main/drivers/light_ws2811strip.h +++ b/src/main/drivers/light_ws2811strip.h @@ -51,8 +51,9 @@ typedef enum { } ledStripFormatRGB_e; void ws2811LedStripInit(ioTag_t ioTag); +void ws2811LedStripEnable(void); -void ws2811LedStripHardwareInit(ioTag_t ioTag); +bool ws2811LedStripHardwareInit(ioTag_t ioTag); void ws2811LedStripDMAEnable(void); void ws2811UpdateStrip(ledStripFormatRGB_e ledFormat); @@ -73,7 +74,7 @@ extern uint8_t ledStripDMABuffer[WS2811_DMA_BUFFER_SIZE]; #else extern uint32_t ledStripDMABuffer[WS2811_DMA_BUFFER_SIZE]; #endif -extern volatile uint8_t ws2811LedDataTransferInProgress; +extern volatile bool ws2811LedDataTransferInProgress; extern uint16_t BIT_COMPARE_1; extern uint16_t BIT_COMPARE_0; diff --git a/src/main/drivers/light_ws2811strip_hal.c b/src/main/drivers/light_ws2811strip_hal.c index f615baa76d..e463d7a632 100644 --- a/src/main/drivers/light_ws2811strip_hal.c +++ b/src/main/drivers/light_ws2811strip_hal.c @@ -37,7 +37,6 @@ #include "light_ws2811strip.h" static IO_t ws2811IO = IO_NONE; -bool ws2811Initialised = false; static TIM_HandleTypeDef TimHandle; static uint16_t timerChannel = 0; @@ -46,13 +45,13 @@ void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor) { HAL_DMA_IRQHandler(TimHandle.hdma[descriptor->userParam]); TIM_DMACmd(&TimHandle, timerChannel, DISABLE); - ws2811LedDataTransferInProgress = 0; + ws2811LedDataTransferInProgress = false; } -void ws2811LedStripHardwareInit(ioTag_t ioTag) +bool ws2811LedStripHardwareInit(ioTag_t ioTag) { if (!ioTag) { - return; + return false; } const timerHardware_t *timerHardware = timerGetByTag(ioTag); @@ -60,7 +59,7 @@ void ws2811LedStripHardwareInit(ioTag_t ioTag) timerChannel = timerHardware->channel; if (timerHardware->dmaRef == NULL) { - return; + return false; } TimHandle.Instance = timer; @@ -77,7 +76,7 @@ void ws2811LedStripHardwareInit(ioTag_t ioTag) TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) { /* Initialization Error */ - return; + return false; } static DMA_HandleTypeDef hdma_tim; @@ -116,7 +115,7 @@ void ws2811LedStripHardwareInit(ioTag_t ioTag) /* Initialize TIMx DMA handle */ if (HAL_DMA_Init(TimHandle.hdma[dmaIndex]) != HAL_OK) { /* Initialization Error */ - return; + return false; } TIM_OC_InitTypeDef TIM_OCInitStructure; @@ -131,32 +130,28 @@ void ws2811LedStripHardwareInit(ioTag_t ioTag) TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, timerChannel) != HAL_OK) { /* Configuration Error */ - return; + return false; } if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) { if (HAL_TIMEx_PWMN_Start(&TimHandle, timerChannel) != HAL_OK) { /* Starting PWM generation Error */ - return; + return false; } } else { if (HAL_TIM_PWM_Start(&TimHandle, timerChannel) != HAL_OK) { /* Starting PWM generation Error */ - return; + return false; } } - ws2811Initialised = true; + + return true; } void ws2811LedStripDMAEnable(void) { - if (!ws2811Initialised) { - ws2811LedDataTransferInProgress = 0; - return; - } - if (DMA_SetCurrDataCounter(&TimHandle, timerChannel, ledStripDMABuffer, WS2811_DMA_BUFFER_SIZE) != HAL_OK) { /* DMA set error */ - ws2811LedDataTransferInProgress = 0; + ws2811LedDataTransferInProgress = false; return; } /* Reset timer counter */ diff --git a/src/main/drivers/light_ws2811strip_stdperiph.c b/src/main/drivers/light_ws2811strip_stdperiph.c index 6b180bd0ac..d4fa19fa07 100644 --- a/src/main/drivers/light_ws2811strip_stdperiph.c +++ b/src/main/drivers/light_ws2811strip_stdperiph.c @@ -39,7 +39,6 @@ #include "light_ws2811strip.h" static IO_t ws2811IO = IO_NONE; -bool ws2811Initialised = false; #if defined(STM32F4) static DMA_Stream_TypeDef *dmaRef = NULL; #elif defined(STM32F3) || defined(STM32F1) @@ -63,11 +62,11 @@ static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) memset(ledStripDMABuffer, 0, sizeof(ledStripDMABuffer)); } else if (counter == (WS2811_LED_STRIP_LENGTH + WS2811_DELAY_ITERATIONS)) { counter = 0; - ws2811LedDataTransferInProgress = 0; + ws2811LedDataTransferInProgress = false; DMA_Cmd(descriptor->ref, DISABLE); } #else - ws2811LedDataTransferInProgress = 0; + ws2811LedDataTransferInProgress = false; DMA_Cmd(descriptor->ref, DISABLE); #endif @@ -75,10 +74,10 @@ static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) } } -void ws2811LedStripHardwareInit(ioTag_t ioTag) +bool ws2811LedStripHardwareInit(ioTag_t ioTag) { if (!ioTag) { - return; + return false; } TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; @@ -89,7 +88,7 @@ void ws2811LedStripHardwareInit(ioTag_t ioTag) timer = timerHardware->tim; if (timerHardware->dmaRef == NULL) { - return; + return false; } ws2811IO = IOGetByTag(ioTag); @@ -185,18 +184,15 @@ void ws2811LedStripHardwareInit(ioTag_t ioTag) DMA_Init(dmaRef, &DMA_InitStructure); TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE); DMA_ITConfig(dmaRef, DMA_IT_TC, ENABLE); - ws2811Initialised = true; + + return true; } void ws2811LedStripDMAEnable(void) { - if (!ws2811Initialised) - return; - DMA_SetCurrDataCounter(dmaRef, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred TIM_SetCounter(timer, 0); TIM_Cmd(timer, ENABLE); DMA_Cmd(dmaRef, ENABLE); } - #endif diff --git a/src/main/fc/init.c b/src/main/fc/init.c index 3fe6c6b923..f3971b2239 100644 --- a/src/main/fc/init.c +++ b/src/main/fc/init.c @@ -652,8 +652,6 @@ void init(void) #ifdef USE_LED_STRIP ledStripInit(); - delayMicroseconds(50); - if (featureIsEnabled(FEATURE_LED_STRIP)) { ledStripEnable(); } diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c index 5b61a72ced..461d3cacad 100644 --- a/src/main/io/ledstrip.c +++ b/src/main/io/ledstrip.c @@ -1150,6 +1150,8 @@ bool setModeColor(ledModeIndex_e modeIndex, int modeColorIndex, int colorIndex) void ledStripEnable(void) { + ws2811LedStripEnable(); + ledStripEnabled = true; } @@ -1157,8 +1159,8 @@ void ledStripDisable(void) { ledStripEnabled = false; previousProfileColorIndex = COLOR_UNDEFINED; - setStripColor(&HSV(BLACK)); + setStripColor(&HSV(BLACK)); ws2811UpdateStrip((ledStripFormatRGB_e)ledStripConfig()->ledstrip_grb_rgb); } diff --git a/src/test/unit/ledstrip_unittest.cc b/src/test/unit/ledstrip_unittest.cc index 5d5e522b52..dd651cdbab 100644 --- a/src/test/unit/ledstrip_unittest.cc +++ b/src/test/unit/ledstrip_unittest.cc @@ -393,4 +393,5 @@ uint8_t getRssiPercent(void) { return 0; } bool isFlipOverAfterCrashActive(void) { return false; } +void ws2811LedStripEnable(void) { } } diff --git a/src/test/unit/ws2811_unittest.cc b/src/test/unit/ws2811_unittest.cc index 75e6900120..a190dbd1a8 100644 --- a/src/test/unit/ws2811_unittest.cc +++ b/src/test/unit/ws2811_unittest.cc @@ -31,23 +31,15 @@ extern "C" { #include "gtest/gtest.h" extern "C" { -STATIC_UNIT_TESTED extern uint16_t dmaBufferOffset; - -STATIC_UNIT_TESTED void updateLEDDMABuffer(rgbColor24bpp_t *color); + void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color, unsigned ledIndex); } TEST(WS2812, updateDMABuffer) { // given rgbColor24bpp_t color1 = { .raw = {0xFF,0xAA,0x55} }; - // and - dmaBufferOffset = 0; - // when - updateLEDDMABuffer(&color1); - - // then - EXPECT_EQ(24, dmaBufferOffset); + updateLEDDMABuffer(LED_GRB, &color1, 0); // and uint8_t byteIndex = 0; @@ -89,8 +81,10 @@ rgbColor24bpp_t* hsvToRgb24(const hsvColor_t *c) { return NULL; } -void ws2811LedStripHardwareInit(ioTag_t ioTag) { +bool ws2811LedStripHardwareInit(ioTag_t ioTag) { UNUSED(ioTag); + + return true; } void ws2811LedStripDMAEnable(void) {}