From e56f915018c1693e0ce7504d0c4aae4898078aa6 Mon Sep 17 00:00:00 2001 From: blckmn Date: Sat, 5 Nov 2016 13:35:20 +1100 Subject: [PATCH] Moving LED strip to be configurable via resource command --- src/main/config/config_master.h | 7 +- src/main/drivers/light_ws2811strip.c | 5 +- src/main/drivers/light_ws2811strip.h | 6 +- src/main/drivers/light_ws2811strip_hal.c | 65 +++++------ .../drivers/light_ws2811strip_stm32f10x.c | 53 +++++---- .../drivers/light_ws2811strip_stm32f30x.c | 73 +++++++------ .../drivers/light_ws2811strip_stm32f4xx.c | 101 ++++++++++-------- src/main/drivers/pwm_output_stm32f3xx.c | 1 - src/main/drivers/pwm_output_stm32f4xx.c | 1 + src/main/drivers/timer.c | 4 +- src/main/drivers/timer.h | 5 +- src/main/drivers/timer_hal.c | 15 +++ src/main/fc/config.c | 34 ++++-- src/main/fc/fc_msp.c | 14 +-- src/main/io/ledstrip.c | 60 ++++++----- src/main/io/ledstrip.h | 12 ++- src/main/io/serial_cli.c | 37 ++++--- src/main/main.c | 2 +- 18 files changed, 281 insertions(+), 214 deletions(-) diff --git a/src/main/config/config_master.h b/src/main/config/config_master.h index 4caf57f1e..dc5912e80 100644 --- a/src/main/config/config_master.h +++ b/src/main/config/config_master.h @@ -161,12 +161,7 @@ typedef struct master_s { #endif #ifdef LED_STRIP - ledConfig_t ledConfigs[LED_MAX_STRIP_LENGTH]; - hsvColor_t colors[LED_CONFIGURABLE_COLOR_COUNT]; - modeColorIndexes_t modeColors[LED_MODE_COUNT]; - specialColorIndexes_t specialColors; - uint8_t ledstrip_visual_beeper; // suppress LEDLOW mode if beeper is on - rc_alias_e ledstrip_aux_channel; + ledStripConfig_t ledStripConfig; #endif #ifdef TRANSPONDER diff --git a/src/main/drivers/light_ws2811strip.c b/src/main/drivers/light_ws2811strip.c index c7110799c..149c9b612 100644 --- a/src/main/drivers/light_ws2811strip.c +++ b/src/main/drivers/light_ws2811strip.c @@ -37,6 +37,7 @@ #include "common/color.h" #include "common/colorconversion.h" #include "dma.h" +#include "io.h" #include "light_ws2811strip.h" #if defined(STM32F4) || defined(STM32F7) @@ -84,10 +85,10 @@ void setStripColors(const hsvColor_t *colors) } } -void ws2811LedStripInit(void) +void ws2811LedStripInit(ioTag_t ioTag) { memset(&ledStripDMABuffer, 0, WS2811_DMA_BUFFER_SIZE); - ws2811LedStripHardwareInit(); + ws2811LedStripHardwareInit(ioTag); ws2811UpdateStrip(); } diff --git a/src/main/drivers/light_ws2811strip.h b/src/main/drivers/light_ws2811strip.h index c980353ab..c81be0279 100644 --- a/src/main/drivers/light_ws2811strip.h +++ b/src/main/drivers/light_ws2811strip.h @@ -17,6 +17,8 @@ #pragma once +#include "io.h" + #define WS2811_LED_STRIP_LENGTH 32 #define WS2811_BITS_PER_LED 24 #define WS2811_DELAY_BUFFER_LENGTH 42 // for 50us delay @@ -36,9 +38,9 @@ #define BIT_COMPARE_0 9 // timer compare value for logical 0 #endif -void ws2811LedStripInit(void); +void ws2811LedStripInit(ioTag_t ioTag); -void ws2811LedStripHardwareInit(void); +void ws2811LedStripHardwareInit(ioTag_t ioTag); void ws2811LedStripDMAEnable(void); void ws2811UpdateStrip(void); diff --git a/src/main/drivers/light_ws2811strip_hal.c b/src/main/drivers/light_ws2811strip_hal.c index 28bafabbf..5d8e4cd0c 100644 --- a/src/main/drivers/light_ws2811strip_hal.c +++ b/src/main/drivers/light_ws2811strip_hal.c @@ -31,26 +31,15 @@ #include "rcc.h" #include "timer.h" -#if !defined(WS2811_PIN) -#define WS2811_PIN PA0 -#define WS2811_TIMER TIM5 -#define WS2811_DMA_HANDLER_IDENTIFER DMA1_ST2_HANDLER -#define WS2811_DMA_STREAM DMA1_Stream2 -#define WS2811_DMA_IT DMA_IT_TCIF2 -#define WS2811_DMA_CHANNEL DMA_Channel_6 -#define WS2811_TIMER_CHANNEL TIM_Channel_1 -#define WS2811_TIMER_GPIO_AF GPIO_AF2_TIM5 -#endif - static IO_t ws2811IO = IO_NONE; -static uint16_t timDMASource = 0; bool ws2811Initialised = false; static TIM_HandleTypeDef TimHandle; +static uint16_t timerChannel = 0; void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) { - if(htim->Instance==WS2811_TIMER) + if(htim->Instance == TimHandle.Instance) { //HAL_TIM_PWM_Stop_DMA(&TimHandle,WS2811_TIMER_CHANNEL); ws2811LedDataTransferInProgress = 0; @@ -62,9 +51,20 @@ void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor) HAL_DMA_IRQHandler(TimHandle.hdma[descriptor->userParam]); } -void ws2811LedStripHardwareInit(void) +void ws2811LedStripHardwareInit(ioTag_t ioTag) { - TimHandle.Instance = WS2811_TIMER; + if (!ioTag) { + return; + } + + const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY); + TIM_TypeDef *timer = timerHardware->tim; + timerChannel = timerHardware->channel; + + if (timerHardware->dmaStream == NULL) { + return; + } + TimHandle.Instance = timer; TimHandle.Init.Prescaler = 1; TimHandle.Init.Period = 135; // 800kHz @@ -78,16 +78,14 @@ void ws2811LedStripHardwareInit(void) static DMA_HandleTypeDef hdma_tim; - ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); - /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ + ws2811IO = IOGetByTag(ioTag); IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); - IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), WS2811_TIMER_GPIO_AF); + IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), timerHardware->alternateFunction); __DMA1_CLK_ENABLE(); - /* Set the parameters to be configured */ - hdma_tim.Init.Channel = WS2811_DMA_CHANNEL; + hdma_tim.Init.Channel = timerHardware->dmaChannel; hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tim.Init.MemInc = DMA_MINC_ENABLE; @@ -101,30 +99,17 @@ void ws2811LedStripHardwareInit(void) hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE; /* Set hdma_tim instance */ - hdma_tim.Instance = WS2811_DMA_STREAM; + hdma_tim.Instance = timerHardware->dmaStream; - switch (WS2811_TIMER_CHANNEL) { - case TIM_CHANNEL_1: - timDMASource = TIM_DMA_ID_CC1; - break; - case TIM_CHANNEL_2: - timDMASource = TIM_DMA_ID_CC2; - break; - case TIM_CHANNEL_3: - timDMASource = TIM_DMA_ID_CC3; - break; - case TIM_CHANNEL_4: - timDMASource = TIM_DMA_ID_CC4; - break; - } + uint16_t dmaSource = timerDmaSource(timerChannel); /* Link hdma_tim to hdma[x] (channelx) */ - __HAL_LINKDMA(&TimHandle, hdma[timDMASource], hdma_tim); + __HAL_LINKDMA(&TimHandle, hdma[dmaSource], hdma_tim); - dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, timDMASource); + dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, dmaSource); /* Initialize TIMx DMA handle */ - if(HAL_DMA_Init(TimHandle.hdma[timDMASource]) != HAL_OK) + if(HAL_DMA_Init(TimHandle.hdma[dmaSource]) != HAL_OK) { /* Initialization Error */ return; @@ -140,7 +125,7 @@ void ws2811LedStripHardwareInit(void) TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET; TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE; - if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, WS2811_TIMER_CHANNEL) != HAL_OK) + if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, timerChannel) != HAL_OK) { /* Configuration Error */ return; @@ -160,7 +145,7 @@ void ws2811LedStripDMAEnable(void) return; } - if( HAL_TIM_PWM_Start_DMA(&TimHandle, WS2811_TIMER_CHANNEL, ledStripDMABuffer, WS2811_DMA_BUFFER_SIZE) != HAL_OK) + if( HAL_TIM_PWM_Start_DMA(&TimHandle, timerChannel, ledStripDMABuffer, WS2811_DMA_BUFFER_SIZE) != HAL_OK) { /* Starting PWM generation Error */ ws2811LedDataTransferInProgress = 0; diff --git a/src/main/drivers/light_ws2811strip_stm32f10x.c b/src/main/drivers/light_ws2811strip_stm32f10x.c index 911b7cdc6..3ccfafe2f 100644 --- a/src/main/drivers/light_ws2811strip_stm32f10x.c +++ b/src/main/drivers/light_ws2811strip_stm32f10x.c @@ -30,8 +30,13 @@ #include "rcc.h" #include "timer.h" +#define WS2811_TIMER_HZ 24000000 +#define WS2811_TIMER_PERIOD 29 + static IO_t ws2811IO = IO_NONE; bool ws2811Initialised = false; +static DMA_Channel_TypeDef *dmaChannel = NULL; +static TIM_TypeDef *timer = NULL; static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { @@ -41,32 +46,38 @@ static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { } } -void ws2811LedStripHardwareInit(void) +void ws2811LedStripHardwareInit(ioTag_t ioTag) { + if (!ioTag) { + return; + } + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; DMA_InitTypeDef DMA_InitStructure; - uint16_t prescalerValue; + const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY); + timer = timerHardware->tim; - dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); + if (timerHardware->dmaChannel == NULL) { + return; + } ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); -/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); IOConfigGPIO(ws2811IO, IO_CONFIG(GPIO_Speed_50MHz, GPIO_Mode_AF_PP)); RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE); /* Compute the prescaler value */ - prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; + uint16_t prescalerValue = (uint16_t) (SystemCoreClock / WS2811_TIMER_HZ) - 1; /* Time base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); - TIM_TimeBaseStructure.TIM_Period = 29; // 800kHz + TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); + TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); /* PWM1 Mode configuration: Channel1 */ TIM_OCStructInit(&TIM_OCInitStructure); @@ -74,20 +85,17 @@ void ws2811LedStripHardwareInit(void) TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; - TIM_OC1Init(TIM3, &TIM_OCInitStructure); - TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); + TIM_OC1Init(timer, &TIM_OCInitStructure); + TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable); - TIM_CtrlPWMOutputs(TIM3, ENABLE); + TIM_CtrlPWMOutputs(timer, ENABLE); /* configure DMA */ - /* DMA clock enable */ - RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); - /* DMA1 Channel6 Config */ - DMA_DeInit(DMA1_Channel6); + DMA_DeInit(dmaChannel); DMA_StructInit(&DMA_InitStructure); - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM3->CCR1; + DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ledStripDMABuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; @@ -99,12 +107,13 @@ void ws2811LedStripHardwareInit(void) DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; - DMA_Init(DMA1_Channel6, &DMA_InitStructure); + DMA_Init(dmaChannel, &DMA_InitStructure); /* TIM3 CC1 DMA Request enable */ - TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE); + TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE); - DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE); + DMA_ITConfig(dmaChannel, DMA_IT_TC, ENABLE); + dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); const hsvColor_t hsv_white = { 0, 255, 255}; ws2811Initialised = true; @@ -117,10 +126,10 @@ void ws2811LedStripDMAEnable(void) if (!ws2811Initialised) return; - DMA_SetCurrDataCounter(DMA1_Channel6, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred - TIM_SetCounter(TIM3, 0); - TIM_Cmd(TIM3, ENABLE); - DMA_Cmd(DMA1_Channel6, ENABLE); + DMA_SetCurrDataCounter(dmaChannel, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred + TIM_SetCounter(timer, 0); + TIM_Cmd(timer, ENABLE); + DMA_Cmd(dmaChannel, ENABLE); } #endif diff --git a/src/main/drivers/light_ws2811strip_stm32f30x.c b/src/main/drivers/light_ws2811strip_stm32f30x.c index 8a0b073c7..1e8c7a806 100644 --- a/src/main/drivers/light_ws2811strip_stm32f30x.c +++ b/src/main/drivers/light_ws2811strip_stm32f30x.c @@ -31,16 +31,13 @@ #include "rcc.h" #include "timer.h" -#ifndef WS2811_PIN -#define WS2811_PIN PB8 // TIM16_CH1 -#define WS2811_TIMER TIM16 -#define WS2811_DMA_CHANNEL DMA1_Channel3 -#define WS2811_DMA_HANDLER_IDENTIFER DMA1_CH3_HANDLER -#define WS2811_TIMER_GPIO_AF GPIO_AF_1 -#endif +#define WS2811_TIMER_HZ 24000000 +#define WS2811_TIMER_PERIOD 29 static IO_t ws2811IO = IO_NONE; bool ws2811Initialised = false; +static DMA_Channel_TypeDef *dmaChannel = NULL; +static TIM_TypeDef *timer = NULL; static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { @@ -50,51 +47,66 @@ static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { } } -void ws2811LedStripHardwareInit(void) +void ws2811LedStripHardwareInit(ioTag_t ioTag) { + if (!ioTag) { + return; + } + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; DMA_InitTypeDef DMA_InitStructure; - uint16_t prescalerValue; + const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY); + timer = timerHardware->tim; - dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); + if (timerHardware->dmaChannel == NULL) { + return; + } ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); - /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); - IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), WS2811_TIMER_GPIO_AF); + IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction); - RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE); + RCC_ClockCmd(timerRCC(timer), ENABLE); /* Compute the prescaler value */ - prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; + uint16_t prescalerValue = (uint16_t) (SystemCoreClock / WS2811_TIMER_HZ) - 1; + /* Time base configuration */ TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); - TIM_TimeBaseStructure.TIM_Period = 29; // 800kHz + TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure); + TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); /* PWM1 Mode configuration */ TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) { + TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; + TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; + TIM_OCInitStructure.TIM_OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPolarity_High : TIM_OCNPolarity_Low; + } else { + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; + TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High; + } TIM_OCInitStructure.TIM_Pulse = 0; - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; - TIM_OC1Init(WS2811_TIMER, &TIM_OCInitStructure); - TIM_OC1PreloadConfig(WS2811_TIMER, TIM_OCPreload_Enable); + TIM_OC1Init(timer, &TIM_OCInitStructure); + TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable); + TIM_CtrlPWMOutputs(timer, ENABLE); - TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE); + dmaChannel = timerHardware->dmaChannel; /* configure DMA */ /* DMA1 Channel Config */ - DMA_DeInit(WS2811_DMA_CHANNEL); + DMA_DeInit(dmaChannel); DMA_StructInit(&DMA_InitStructure); - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&WS2811_TIMER->CCR1; + DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel); DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ledStripDMABuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; @@ -106,11 +118,12 @@ void ws2811LedStripHardwareInit(void) DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; - DMA_Init(WS2811_DMA_CHANNEL, &DMA_InitStructure); + DMA_Init(dmaChannel, &DMA_InitStructure); - TIM_DMACmd(WS2811_TIMER, TIM_DMA_CC1, ENABLE); + TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE); - DMA_ITConfig(WS2811_DMA_CHANNEL, DMA_IT_TC, ENABLE); + DMA_ITConfig(dmaChannel, DMA_IT_TC, ENABLE); + dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); const hsvColor_t hsv_white = { 0, 255, 255}; ws2811Initialised = true; @@ -123,10 +136,10 @@ void ws2811LedStripDMAEnable(void) if (!ws2811Initialised) return; - DMA_SetCurrDataCounter(WS2811_DMA_CHANNEL, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred - TIM_SetCounter(WS2811_TIMER, 0); - TIM_Cmd(WS2811_TIMER, ENABLE); - DMA_Cmd(WS2811_DMA_CHANNEL, ENABLE); + DMA_SetCurrDataCounter(dmaChannel, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred + TIM_SetCounter(timer, 0); + TIM_Cmd(timer, ENABLE); + DMA_Cmd(dmaChannel, ENABLE); } #endif diff --git a/src/main/drivers/light_ws2811strip_stm32f4xx.c b/src/main/drivers/light_ws2811strip_stm32f4xx.c index 46bcdd0e4..4fd38325e 100644 --- a/src/main/drivers/light_ws2811strip_stm32f4xx.c +++ b/src/main/drivers/light_ws2811strip_stm32f4xx.c @@ -31,85 +31,93 @@ #include "rcc.h" #include "timer.h" #include "timer_stm32f4xx.h" +#include "io.h" -#if !defined(WS2811_PIN) -#define WS2811_PIN PA0 -#define WS2811_TIMER TIM5 -#define WS2811_DMA_HANDLER_IDENTIFER DMA1_ST2_HANDLER -#define WS2811_DMA_STREAM DMA1_Stream2 -#define WS2811_DMA_CHANNEL DMA_Channel_6 -#define WS2811_TIMER_CHANNEL TIM_Channel_1 -#define WS2811_TIMER_GPIO_AF GPIO_AF_TIM5 -#endif +#define WS2811_TIMER_HZ 84000000 +#define WS2811_TIMER_PERIOD 104 static IO_t ws2811IO = IO_NONE; -static uint16_t timDMASource = 0; bool ws2811Initialised = false; +static DMA_Stream_TypeDef *stream = NULL; +static TIM_TypeDef *timer = NULL; static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { ws2811LedDataTransferInProgress = 0; DMA_Cmd(descriptor->stream, DISABLE); - TIM_DMACmd(WS2811_TIMER, timDMASource, DISABLE); DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); } } -void ws2811LedStripHardwareInit(void) +void ws2811LedStripHardwareInit(ioTag_t ioTag) { + if (!ioTag) { + return; + } + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; DMA_InitTypeDef DMA_InitStructure; - uint16_t prescalerValue; + const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY); + timer = timerHardware->tim; - RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE); + if (timerHardware->dmaStream == NULL) { + return; + } - ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); + RCC_ClockCmd(timerRCC(timer), ENABLE); + + ws2811IO = IOGetByTag(ioTag); /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); - IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), WS2811_TIMER_GPIO_AF); + IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction); // Stop timer - TIM_Cmd(WS2811_TIMER, DISABLE); + TIM_Cmd(timer, DISABLE); /* Compute the prescaler value */ - prescalerValue = (uint16_t)(SystemCoreClock / 2 / 84000000) - 1; + uint16_t prescalerValue = (uint16_t)(SystemCoreClock / timerClockDivisor(timer) / WS2811_TIMER_HZ) - 1; /* Time base configuration */ - TIM_TimeBaseStructure.TIM_Period = 104; // 800kHz + TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); + TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; - TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure); + TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); /* PWM1 Mode configuration: Channel1 */ + TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; - TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; - TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High; - TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; - TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; + if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) { + TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; + TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset; + TIM_OCInitStructure.TIM_OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPolarity_High : TIM_OCNPolarity_Low; + } else { + TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; + TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; + TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High; + } TIM_OCInitStructure.TIM_Pulse = 0; - timerOCInit(WS2811_TIMER, WS2811_TIMER_CHANNEL, &TIM_OCInitStructure); - timerOCPreloadConfig(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_OCPreload_Enable); - timDMASource = timerDmaSource(WS2811_TIMER_CHANNEL); + timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure); + timerOCPreloadConfig(timer, timerHardware->channel, TIM_OCPreload_Enable); - TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE); - TIM_ARRPreloadConfig(WS2811_TIMER, ENABLE); + TIM_CtrlPWMOutputs(timer, ENABLE); + TIM_ARRPreloadConfig(timer, ENABLE); - TIM_CCxCmd(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_CCx_Enable); - TIM_Cmd(WS2811_TIMER, ENABLE); + TIM_CCxCmd(timer, timerHardware->channel, TIM_CCx_Enable); + TIM_Cmd(timer, ENABLE); + stream = timerHardware->dmaStream; /* configure DMA */ - DMA_Cmd(WS2811_DMA_STREAM, DISABLE); - DMA_DeInit(WS2811_DMA_STREAM); + DMA_Cmd(stream, DISABLE); + DMA_DeInit(stream); DMA_StructInit(&DMA_InitStructure); - DMA_InitStructure.DMA_Channel = WS2811_DMA_CHANNEL; - DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(WS2811_TIMER, WS2811_TIMER_CHANNEL); + DMA_InitStructure.DMA_Channel = timerHardware->dmaChannel; + DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel); DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ledStripDMABuffer; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; @@ -124,14 +132,15 @@ void ws2811LedStripHardwareInit(void) DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; - DMA_Init(WS2811_DMA_STREAM, &DMA_InitStructure); + DMA_Init(stream, &DMA_InitStructure); + TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE); - DMA_ITConfig(WS2811_DMA_STREAM, DMA_IT_TC, ENABLE); - DMA_ClearITPendingBit(WS2811_DMA_STREAM, dmaFlag_IT_TCIF(WS2811_DMA_STREAM)); + DMA_ITConfig(stream, DMA_IT_TC, ENABLE); + DMA_ClearITPendingBit(stream, dmaFlag_IT_TCIF(stream)); - dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); + dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); - const hsvColor_t hsv_white = { 0, 255, 255}; + const hsvColor_t hsv_white = { 0, 255, 255 }; ws2811Initialised = true; setStripColor(&hsv_white); ws2811UpdateStrip(); @@ -142,10 +151,10 @@ void ws2811LedStripDMAEnable(void) if (!ws2811Initialised) return; - DMA_SetCurrDataCounter(WS2811_DMA_STREAM, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred - TIM_SetCounter(WS2811_TIMER, 0); - DMA_Cmd(WS2811_DMA_STREAM, ENABLE); - TIM_DMACmd(WS2811_TIMER, timDMASource, ENABLE); + DMA_SetCurrDataCounter(stream, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred + TIM_SetCounter(timer, 0); + TIM_Cmd(timer, ENABLE); + DMA_Cmd(stream, ENABLE); } #endif diff --git a/src/main/drivers/pwm_output_stm32f3xx.c b/src/main/drivers/pwm_output_stm32f3xx.c index 5e7b8f758..8a1416106 100644 --- a/src/main/drivers/pwm_output_stm32f3xx.c +++ b/src/main/drivers/pwm_output_stm32f3xx.c @@ -156,7 +156,6 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High; } - TIM_OCInitStructure.TIM_Pulse = 0; timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure); diff --git a/src/main/drivers/pwm_output_stm32f4xx.c b/src/main/drivers/pwm_output_stm32f4xx.c index e2bf84e12..5e8287cfa 100644 --- a/src/main/drivers/pwm_output_stm32f4xx.c +++ b/src/main/drivers/pwm_output_stm32f4xx.c @@ -146,6 +146,7 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); } + TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) { TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; diff --git a/src/main/drivers/timer.c b/src/main/drivers/timer.c index 77096a1cb..c62739f20 100755 --- a/src/main/drivers/timer.c +++ b/src/main/drivers/timer.c @@ -810,6 +810,7 @@ volatile timCCR_t* timerCCR(TIM_TypeDef *tim, uint8_t channel) return (volatile timCCR_t*)((volatile char*)&tim->CCR1 + channel); } +#ifndef USE_HAL_DRIVER uint16_t timerDmaSource(uint8_t channel) { switch (channel) { @@ -823,4 +824,5 @@ uint16_t timerDmaSource(uint8_t channel) return TIM_DMA_CC4; } return 0; -} \ No newline at end of file +} +#endif diff --git a/src/main/drivers/timer.h b/src/main/drivers/timer.h index 9a86a9210..689602e80 100644 --- a/src/main/drivers/timer.h +++ b/src/main/drivers/timer.h @@ -55,6 +55,7 @@ typedef uint32_t timCNT_t; #endif typedef enum { + TIM_USE_ANY = 0x0, TIM_USE_PPM = 0x1, TIM_USE_PWM = 0x2, TIM_USE_MOTOR = 0x4, @@ -92,11 +93,11 @@ typedef struct timerHardware_s { #if defined(STM32F3) || defined(STM32F4) || defined(STM32F7) uint8_t alternateFunction; #endif -#if defined(USE_DSHOT) +#if defined(USE_DSHOT) || defined(LED_STRIP) #if defined(STM32F4) || defined(STM32F7) DMA_Stream_TypeDef *dmaStream; uint32_t dmaChannel; -#elif defined(STM32F3) +#elif defined(STM32F3) || defined(STM32F1) DMA_Channel_TypeDef *dmaChannel; #endif uint8_t dmaIrqHandler; diff --git a/src/main/drivers/timer_hal.c b/src/main/drivers/timer_hal.c index 8268bd349..cb9ef8bf5 100644 --- a/src/main/drivers/timer_hal.c +++ b/src/main/drivers/timer_hal.c @@ -867,3 +867,18 @@ const timerHardware_t *timerGetByTag(ioTag_t tag, timerUsageFlag_e flag) } return NULL; } + +uint16_t timerDmaSource(uint8_t channel) +{ + switch (channel) { + case TIM_CHANNEL_1: + return TIM_DMA_ID_CC1; + case TIM_CHANNEL_2: + return TIM_DMA_ID_CC2; + case TIM_CHANNEL_3: + return TIM_DMA_ID_CC3; + case TIM_CHANNEL_4: + return TIM_DMA_ID_CC4; + } + return 0; +} diff --git a/src/main/fc/config.c b/src/main/fc/config.c index c4668bf07..296df6570 100755 --- a/src/main/fc/config.c +++ b/src/main/fc/config.c @@ -42,6 +42,7 @@ #include "drivers/pwm_output.h" #include "drivers/max7456.h" #include "drivers/sound_beeper.h" +#include "drivers/light_ws2811strip.h" #include "fc/config.h" #include "fc/rc_controls.h" @@ -238,6 +239,26 @@ void resetSensorAlignment(sensorAlignmentConfig_t *sensorAlignmentConfig) sensorAlignmentConfig->mag_align = ALIGN_DEFAULT; } +#ifdef USE_LEDSTRIP +void resetLedStripConfig(ledStripConfig_t *ledStripConfig) +{ + applyDefaultColors(ledStripConfig->colors); + applyDefaultLedStripConfig(ledStripConfig->ledConfigs); + applyDefaultModeColors(ledStripConfig->modeColors); + applyDefaultSpecialColors(&(ledStripConfig->specialColors)); + ledStripConfig->ledstrip_visual_beeper = 0; + ledStripConfig->ledstrip_aux_channel = THROTTLE; + + for (int i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) { + if (timerHardware[i].usageFlags & TIM_USE_LED) { + ledStripConfig->ioTag = timerHardware[i].tag; + return; + } + } + ledStripConfig->ioTag = IO_TAG_NONE; +} +#endif + #ifdef USE_SERVOS void resetServoConfig(servoConfig_t *servoConfig) { @@ -597,6 +618,10 @@ void createDefaultConfig(master_t *config) #endif resetFlight3DConfig(&config->flight3DConfig); +#ifdef USE_LEDSTRIP + resetLedStripConfig(&config->ledStripConfig); +#endif + #ifdef GPS // gps/nav stuff config->gpsConfig.provider = GPS_NMEA; @@ -666,15 +691,6 @@ void createDefaultConfig(master_t *config) config->customMotorMixer[i].throttle = 0.0f; } -#ifdef LED_STRIP - applyDefaultColors(config->colors); - applyDefaultLedStripConfig(config->ledConfigs); - applyDefaultModeColors(config->modeColors); - applyDefaultSpecialColors(&(config->specialColors)); - config->ledstrip_visual_beeper = 0; - config->ledstrip_aux_channel = THROTTLE; -#endif - #ifdef VTX config->vtx_band = 4; //Fatshark/Airwaves config->vtx_channel = 1; //CH1 diff --git a/src/main/fc/fc_msp.c b/src/main/fc/fc_msp.c index 1662bc1f7..016c9ccaa 100755 --- a/src/main/fc/fc_msp.c +++ b/src/main/fc/fc_msp.c @@ -932,7 +932,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn #ifdef LED_STRIP case MSP_LED_COLORS: for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { - hsvColor_t *color = &masterConfig.colors[i]; + hsvColor_t *color = &masterConfig.ledStripConfig.colors[i]; sbufWriteU16(dst, color->h); sbufWriteU8(dst, color->s); sbufWriteU8(dst, color->v); @@ -941,7 +941,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn case MSP_LED_STRIP_CONFIG: for (i = 0; i < LED_MAX_STRIP_LENGTH; i++) { - ledConfig_t *ledConfig = &masterConfig.ledConfigs[i]; + ledConfig_t *ledConfig = &masterConfig.ledStripConfig.ledConfigs[i]; sbufWriteU32(dst, *ledConfig); } break; @@ -951,19 +951,19 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn for (int j = 0; j < LED_DIRECTION_COUNT; j++) { sbufWriteU8(dst, i); sbufWriteU8(dst, j); - sbufWriteU8(dst, masterConfig.modeColors[i].color[j]); + sbufWriteU8(dst, masterConfig.ledStripConfig.modeColors[i].color[j]); } } for (int j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) { sbufWriteU8(dst, LED_MODE_COUNT); sbufWriteU8(dst, j); - sbufWriteU8(dst, masterConfig.specialColors.color[j]); + sbufWriteU8(dst, masterConfig.ledStripConfig.specialColors.color[j]); } sbufWriteU8(dst, LED_AUX_CHANNEL); sbufWriteU8(dst, 0); - sbufWriteU8(dst, masterConfig.ledstrip_aux_channel); + sbufWriteU8(dst, masterConfig.ledStripConfig.ledstrip_aux_channel); break; #endif @@ -1656,7 +1656,7 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src) #ifdef LED_STRIP case MSP_SET_LED_COLORS: for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { - hsvColor_t *color = &masterConfig.colors[i]; + hsvColor_t *color = &masterConfig.ledStripConfig.colors[i]; color->h = sbufReadU16(src); color->s = sbufReadU8(src); color->v = sbufReadU8(src); @@ -1670,7 +1670,7 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src) return MSP_RESULT_ERROR; break; } - ledConfig_t *ledConfig = &masterConfig.ledConfigs[i]; + ledConfig_t *ledConfig = &masterConfig.ledStripConfig.ledConfigs[i]; *ledConfig = sbufReadU32(src); reevaluateLedConfig(); } diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c index 1892afa87..812d57a67 100644 --- a/src/main/io/ledstrip.c +++ b/src/main/io/ledstrip.c @@ -88,6 +88,7 @@ PG_REGISTER_WITH_RESET_FN(specialColorIndexes_t, specialColors, PG_SPECIAL_COLOR static bool ledStripInitialised = false; static bool ledStripEnabled = true; +static ledStripConfig_t * currentLedStripConfig; static void ledStripDisable(void); @@ -180,7 +181,7 @@ STATIC_UNIT_TESTED void determineLedStripDimensions(void) int maxY = 0; for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; maxX = MAX(ledGetX(ledConfig), maxX); maxY = MAX(ledGetY(ledConfig), maxY); @@ -202,7 +203,7 @@ STATIC_UNIT_TESTED void updateLedCount(void) int count = 0, countRing = 0, countScanner= 0; for (int ledIndex = 0; ledIndex < LED_MAX_STRIP_LENGTH; ledIndex++) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; if (!(*ledConfig)) break; @@ -232,7 +233,7 @@ void reevaluateLedConfig(void) // get specialColor by index static hsvColor_t* getSC(ledSpecialColorIds_e index) { - return &masterConfig.colors[masterConfig.specialColors.color[index]]; + return ¤tLedStripConfig->colors[currentLedStripConfig->specialColors.color[index]]; } static const char directionCodes[LED_DIRECTION_COUNT] = { 'N', 'E', 'S', 'W', 'U', 'D' }; @@ -256,7 +257,7 @@ bool parseLedStripConfig(int ledIndex, const char *config) }; static const char chunkSeparators[PARSE_STATE_COUNT] = {',', ':', ':', ':', '\0'}; - ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; memset(ledConfig, 0, sizeof(ledConfig_t)); int x = 0, y = 0, color = 0; // initialize to prevent warnings @@ -375,7 +376,7 @@ typedef enum { static quadrant_e getLedQuadrant(const int ledIndex) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; int x = ledGetX(ledConfig); int y = ledGetY(ledConfig); @@ -417,7 +418,7 @@ static const struct { static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIndexes_t *modeColors) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; quadrant_e quad = getLedQuadrant(ledIndex); for (unsigned i = 0; i < ARRAYLEN(directionQuadrantMap); i++) { @@ -425,7 +426,7 @@ static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIn quadrant_e quadMask = directionQuadrantMap[i].quadrantMask; if (ledGetDirectionBit(ledConfig, dir) && (quad & quadMask)) - return &masterConfig.colors[modeColors->color[dir]]; + return ¤tLedStripConfig->colors[modeColors->color[dir]]; } return NULL; } @@ -451,7 +452,7 @@ static const struct { static void applyLedFixedLayers() { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND); int fn = ledGetFunction(ledConfig); @@ -459,13 +460,13 @@ static void applyLedFixedLayers() switch (fn) { case LED_FUNCTION_COLOR: - color = masterConfig.colors[ledGetColor(ledConfig)]; + color = currentLedStripConfig->colors[ledGetColor(ledConfig)]; break; case LED_FUNCTION_FLIGHT_MODE: for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++) if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) { - hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &masterConfig.modeColors[flightModeToLed[i].ledMode]); + hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, ¤tLedStripConfig->modeColors[flightModeToLed[i].ledMode]); if (directionalColor) { color = *directionalColor; } @@ -506,7 +507,7 @@ static void applyLedFixedLayers() static void applyLedHsv(uint32_t mask, const hsvColor_t *color) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; if ((*ledConfig & mask) == mask) setLedHsv(ledIndex, color); } @@ -702,7 +703,7 @@ static void applyLedIndicatorLayer(bool updateNow, uint32_t *timer) } for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; if (ledGetOverlayBit(ledConfig, LED_OVERLAY_INDICATOR)) { if (getLedQuadrant(ledIndex) & quadrants) setLedHsv(ledIndex, flashColor); @@ -743,7 +744,7 @@ static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer) } for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; if (ledGetFunction(ledConfig) == LED_FUNCTION_THRUST_RING) { bool applyColor; @@ -754,7 +755,7 @@ static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer) } if (applyColor) { - const hsvColor_t *ringColor = &masterConfig.colors[ledGetColor(ledConfig)]; + const hsvColor_t *ringColor = ¤tLedStripConfig->colors[ledGetColor(ledConfig)]; setLedHsv(ledIndex, ringColor); } @@ -870,7 +871,7 @@ static void applyLedAnimationLayer(bool updateNow, uint32_t *timer) int nextRow = (frameCounter + 1 < animationFrames) ? frameCounter + 1 : 0; for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { - const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; + const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex]; if (ledGetY(ledConfig) == previousRow) { setLedHsv(ledIndex, getSC(LED_SCOLOR_ANIMATION)); @@ -932,7 +933,7 @@ void ledStripUpdate(uint32_t currentTime) return; } - if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(masterConfig.ledstrip_visual_beeper && isBeeperOn())) { + if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(currentLedStripConfig->ledstrip_visual_beeper && isBeeperOn())) { if (ledStripEnabled) { ledStripDisable(); ledStripEnabled = false; @@ -963,7 +964,7 @@ void ledStripUpdate(uint32_t currentTime) // apply all layers; triggered timed functions has to update timers scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 10, 100) : 10; - scaledAux = scaleRange(rcData[masterConfig.ledstrip_aux_channel], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, HSV_HUE_MAX + 1); + scaledAux = scaleRange(rcData[currentLedStripConfig->ledstrip_aux_channel], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, HSV_HUE_MAX + 1); applyLedFixedLayers(); @@ -979,7 +980,7 @@ bool parseColor(int index, const char *colorConfig) { const char *remainingCharacters = colorConfig; - hsvColor_t *color = &masterConfig.colors[index]; + hsvColor_t *color = ¤tLedStripConfig->colors[index]; bool result = true; static const uint16_t hsv_limit[HSV_COLOR_COMPONENT_COUNT] = { @@ -1032,15 +1033,15 @@ bool setModeColor(ledModeIndex_e modeIndex, int modeColorIndex, int colorIndex) if (modeIndex < LED_MODE_COUNT) { // modeIndex_e is unsigned, so one-sided test is enough if(modeColorIndex < 0 || modeColorIndex >= LED_DIRECTION_COUNT) return false; - masterConfig.modeColors[modeIndex].color[modeColorIndex] = colorIndex; + currentLedStripConfig->modeColors[modeIndex].color[modeColorIndex] = colorIndex; } else if (modeIndex == LED_SPECIAL) { if (modeColorIndex < 0 || modeColorIndex >= LED_SPECIAL_COLOR_COUNT) return false; - masterConfig.specialColors.color[modeColorIndex] = colorIndex; + currentLedStripConfig->specialColors.color[modeColorIndex] = colorIndex; } else if (modeIndex == LED_AUX_CHANNEL) { if (modeColorIndex < 0 || modeColorIndex >= 1) return false; - masterConfig.ledstrip_aux_channel = colorIndex; + currentLedStripConfig->ledstrip_aux_channel = colorIndex; } else { return false; } @@ -1098,21 +1099,26 @@ void applyDefaultSpecialColors(specialColorIndexes_t *specialColors) memcpy_fn(specialColors, &defaultSpecialColors, sizeof(defaultSpecialColors)); } -void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, modeColorIndexes_t *modeColorsToUse, specialColorIndexes_t *specialColorsToUse) +void ledStripInit(ledStripConfig_t *ledStripConfig) { - ledConfigs = ledConfigsToUse; - colors = colorsToUse; - modeColors = modeColorsToUse; - specialColors = *specialColorsToUse; + currentLedStripConfig = ledStripConfig; + + ledConfigs = currentLedStripConfig->ledConfigs; + colors = currentLedStripConfig->colors; + modeColors = currentLedStripConfig->modeColors; + specialColors = currentLedStripConfig->specialColors; ledStripInitialised = false; } void ledStripEnable(void) { + if (currentLedStripConfig == NULL) { + return; + } reevaluateLedConfig(); ledStripInitialised = true; - ws2811LedStripInit(); + ws2811LedStripInit(currentLedStripConfig->ioTag); } static void ledStripDisable(void) diff --git a/src/main/io/ledstrip.h b/src/main/io/ledstrip.h index de5439902..9b0d1d1c9 100644 --- a/src/main/io/ledstrip.h +++ b/src/main/io/ledstrip.h @@ -18,6 +18,7 @@ #pragma once #include "common/color.h" +#include "drivers/io.h" #define LED_MAX_STRIP_LENGTH 32 #define LED_CONFIGURABLE_COLOR_COUNT 16 @@ -135,6 +136,15 @@ typedef struct ledCounts_s { uint8_t ringSeqLen; } ledCounts_t; +typedef struct ledStripConfig_s { + ledConfig_t ledConfigs[LED_MAX_STRIP_LENGTH]; + hsvColor_t colors[LED_CONFIGURABLE_COLOR_COUNT]; + modeColorIndexes_t modeColors[LED_MODE_COUNT]; + specialColorIndexes_t specialColors; + uint8_t ledstrip_visual_beeper; // suppress LEDLOW mode if beeper is on + rc_alias_e ledstrip_aux_channel; + ioTag_t ioTag; +} ledStripConfig_t; ledConfig_t *ledConfigs; hsvColor_t *colors; @@ -166,7 +176,7 @@ bool parseLedStripConfig(int ledIndex, const char *config); void generateLedConfig(ledConfig_t *ledConfig, char *ledConfigBuffer, size_t bufferSize); void reevaluateLedConfig(void); -void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, modeColorIndexes_t *modeColorsToUse, specialColorIndexes_t *specialColorsToUse); +void ledStripInit(ledStripConfig_t *ledStripConfig); void ledStripEnable(void); void ledStripUpdate(uint32_t currentTime); diff --git a/src/main/io/serial_cli.c b/src/main/io/serial_cli.c index 5c6673498..72c9aeccb 100755 --- a/src/main/io/serial_cli.c +++ b/src/main/io/serial_cli.c @@ -935,7 +935,7 @@ const clivalue_t valueTable[] = { { "magzero_z", VAR_INT16 | MASTER_VALUE, &masterConfig.magZero.raw[Z], .config.minmax = { -32768, 32767 } }, #endif #ifdef LED_STRIP - { "ledstrip_visual_beeper", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.ledstrip_visual_beeper, .config.lookup = { TABLE_OFF_ON } }, + { "ledstrip_visual_beeper", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.ledStripConfig.ledstrip_visual_beeper, .config.lookup = { TABLE_OFF_ON } }, #endif #ifdef USE_RTC6705 { "vtx_channel", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_channel, .config.minmax = { 0, 39 } }, @@ -1705,8 +1705,8 @@ static void printLed(uint8_t dumpMask, master_t *defaultConfig) char ledConfigBuffer[20]; char ledConfigDefaultBuffer[20]; for (uint32_t i = 0; i < LED_MAX_STRIP_LENGTH; i++) { - ledConfig = masterConfig.ledConfigs[i]; - ledConfigDefault = defaultConfig->ledConfigs[i]; + ledConfig = masterConfig.ledStripConfig.ledConfigs[i]; + ledConfigDefault = defaultConfig->ledStripConfig.ledConfigs[i]; equalsDefault = ledConfig == ledConfigDefault; generateLedConfig(&ledConfig, ledConfigBuffer, sizeof(ledConfigBuffer)); generateLedConfig(&ledConfigDefault, ledConfigDefaultBuffer, sizeof(ledConfigDefaultBuffer)); @@ -1743,8 +1743,8 @@ static void printColor(uint8_t dumpMask, master_t *defaultConfig) hsvColor_t *colorDefault; bool equalsDefault; for (uint32_t i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { - color = &masterConfig.colors[i]; - colorDefault = &defaultConfig->colors[i]; + color = &masterConfig.ledStripConfig.colors[i]; + colorDefault = &defaultConfig->ledStripConfig.colors[i]; equalsDefault = color->h == colorDefault->h && color->s == colorDefault->s && color->v == colorDefault->v; @@ -1789,8 +1789,8 @@ static void printModeColor(uint8_t dumpMask, master_t *defaultConfig) { for (uint32_t i = 0; i < LED_MODE_COUNT; i++) { for (uint32_t j = 0; j < LED_DIRECTION_COUNT; j++) { - int colorIndex = masterConfig.modeColors[i].color[j]; - int colorIndexDefault = defaultConfig->modeColors[i].color[j]; + int colorIndex = masterConfig.ledStripConfig.modeColors[i].color[j]; + int colorIndexDefault = defaultConfig->ledStripConfig.modeColors[i].color[j]; const char *format = "mode_color %u %u %u\r\n"; cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndexDefault); cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndex); @@ -1799,14 +1799,14 @@ static void printModeColor(uint8_t dumpMask, master_t *defaultConfig) const char *format = "mode_color %u %u %u\r\n"; for (uint32_t j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) { - int colorIndex = masterConfig.specialColors.color[j]; - int colorIndexDefault = defaultConfig->specialColors.color[j]; + int colorIndex = masterConfig.ledStripConfig.specialColors.color[j]; + int colorIndexDefault = defaultConfig->ledStripConfig.specialColors.color[j]; cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndexDefault); cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndex); } - int ledStripAuxChannel = masterConfig.ledstrip_aux_channel; - int ledStripAuxChannelDefault = defaultConfig->ledstrip_aux_channel; + int ledStripAuxChannel = masterConfig.ledStripConfig.ledstrip_aux_channel; + int ledStripAuxChannelDefault = defaultConfig->ledStripConfig.ledstrip_aux_channel; cliDefaultPrintf(dumpMask, ledStripAuxChannel == ledStripAuxChannelDefault, format, LED_AUX_CHANNEL, 0, ledStripAuxChannelDefault); cliDumpPrintf(dumpMask, ledStripAuxChannel == ledStripAuxChannelDefault, format, LED_AUX_CHANNEL, 0, ledStripAuxChannel); } @@ -3743,19 +3743,22 @@ typedef struct { const cliResourceValue_t resourceTable[] = { #ifdef BEEPER - { OWNER_BEEPER, &masterConfig.beeperConfig.ioTag, 0 }, + { OWNER_BEEPER, &masterConfig.beeperConfig.ioTag, 0 }, #endif - { OWNER_MOTOR, &masterConfig.motorConfig.ioTags[0], MAX_SUPPORTED_MOTORS }, + { OWNER_MOTOR, &masterConfig.motorConfig.ioTags[0], MAX_SUPPORTED_MOTORS }, #ifdef USE_SERVOS - { OWNER_SERVO, &masterConfig.servoConfig.ioTags[0], MAX_SUPPORTED_SERVOS }, + { OWNER_SERVO, &masterConfig.servoConfig.ioTags[0], MAX_SUPPORTED_SERVOS }, #endif #ifndef SKIP_RX_PWM_PPM - { OWNER_PPMINPUT, &masterConfig.ppmConfig.ioTag, 0 }, - { OWNER_PWMINPUT, &masterConfig.pwmConfig.ioTags[0], PWM_INPUT_PORT_COUNT }, + { OWNER_PPMINPUT, &masterConfig.ppmConfig.ioTag, 0 }, + { OWNER_PWMINPUT, &masterConfig.pwmConfig.ioTags[0], PWM_INPUT_PORT_COUNT }, #endif #ifdef SONAR { OWNER_SONAR_TRIGGER, &masterConfig.sonarConfig.triggerTag, 0 }, - { OWNER_SONAR_ECHO, &masterConfig.sonarConfig.echoTag, 0 }, + { OWNER_SONAR_ECHO, &masterConfig.sonarConfig.echoTag, 0 }, +#endif +#ifdef LED_STRIP + { OWNER_LED_STRIP, &masterConfig.ledStripConfig.ioTag, 0 }, #endif }; diff --git a/src/main/main.c b/src/main/main.c index a6fccd0eb..6a0cdf251 100644 --- a/src/main/main.c +++ b/src/main/main.c @@ -482,7 +482,7 @@ void init(void) #endif #ifdef LED_STRIP - ledStripInit(masterConfig.ledConfigs, masterConfig.colors, masterConfig.modeColors, &masterConfig.specialColors); + ledStripInit(&masterConfig.ledStripConfig); if (feature(FEATURE_LED_STRIP)) { ledStripEnable();