1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-16 21:05:35 +03:00

Moving LED strip to be configurable via resource command

This commit is contained in:
blckmn 2016-11-05 13:35:20 +11:00
parent 3b506415c9
commit e56f915018
18 changed files with 281 additions and 214 deletions

View file

@ -161,12 +161,7 @@ typedef struct master_s {
#endif #endif
#ifdef LED_STRIP #ifdef LED_STRIP
ledConfig_t ledConfigs[LED_MAX_STRIP_LENGTH]; ledStripConfig_t ledStripConfig;
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;
#endif #endif
#ifdef TRANSPONDER #ifdef TRANSPONDER

View file

@ -37,6 +37,7 @@
#include "common/color.h" #include "common/color.h"
#include "common/colorconversion.h" #include "common/colorconversion.h"
#include "dma.h" #include "dma.h"
#include "io.h"
#include "light_ws2811strip.h" #include "light_ws2811strip.h"
#if defined(STM32F4) || defined(STM32F7) #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); memset(&ledStripDMABuffer, 0, WS2811_DMA_BUFFER_SIZE);
ws2811LedStripHardwareInit(); ws2811LedStripHardwareInit(ioTag);
ws2811UpdateStrip(); ws2811UpdateStrip();
} }

View file

@ -17,6 +17,8 @@
#pragma once #pragma once
#include "io.h"
#define WS2811_LED_STRIP_LENGTH 32 #define WS2811_LED_STRIP_LENGTH 32
#define WS2811_BITS_PER_LED 24 #define WS2811_BITS_PER_LED 24
#define WS2811_DELAY_BUFFER_LENGTH 42 // for 50us delay #define WS2811_DELAY_BUFFER_LENGTH 42 // for 50us delay
@ -36,9 +38,9 @@
#define BIT_COMPARE_0 9 // timer compare value for logical 0 #define BIT_COMPARE_0 9 // timer compare value for logical 0
#endif #endif
void ws2811LedStripInit(void); void ws2811LedStripInit(ioTag_t ioTag);
void ws2811LedStripHardwareInit(void); void ws2811LedStripHardwareInit(ioTag_t ioTag);
void ws2811LedStripDMAEnable(void); void ws2811LedStripDMAEnable(void);
void ws2811UpdateStrip(void); void ws2811UpdateStrip(void);

View file

@ -31,26 +31,15 @@
#include "rcc.h" #include "rcc.h"
#include "timer.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 IO_t ws2811IO = IO_NONE;
static uint16_t timDMASource = 0;
bool ws2811Initialised = false; bool ws2811Initialised = false;
static TIM_HandleTypeDef TimHandle; static TIM_HandleTypeDef TimHandle;
static uint16_t timerChannel = 0;
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) 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); //HAL_TIM_PWM_Stop_DMA(&TimHandle,WS2811_TIMER_CHANNEL);
ws2811LedDataTransferInProgress = 0; ws2811LedDataTransferInProgress = 0;
@ -62,9 +51,20 @@ void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor)
HAL_DMA_IRQHandler(TimHandle.hdma[descriptor->userParam]); 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.Prescaler = 1;
TimHandle.Init.Period = 135; // 800kHz TimHandle.Init.Period = 135; // 800kHz
@ -78,16 +78,14 @@ void ws2811LedStripHardwareInit(void)
static DMA_HandleTypeDef hdma_tim; static DMA_HandleTypeDef hdma_tim;
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); ws2811IO = IOGetByTag(ioTag);
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); 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(); __DMA1_CLK_ENABLE();
/* Set the parameters to be configured */ /* 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.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim.Init.MemInc = DMA_MINC_ENABLE; hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
@ -101,30 +99,17 @@ void ws2811LedStripHardwareInit(void)
hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE; hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
/* Set hdma_tim instance */ /* Set hdma_tim instance */
hdma_tim.Instance = WS2811_DMA_STREAM; hdma_tim.Instance = timerHardware->dmaStream;
switch (WS2811_TIMER_CHANNEL) { uint16_t dmaSource = timerDmaSource(timerChannel);
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;
}
/* Link hdma_tim to hdma[x] (channelx) */ /* 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 */ /* Initialize TIMx DMA handle */
if(HAL_DMA_Init(TimHandle.hdma[timDMASource]) != HAL_OK) if(HAL_DMA_Init(TimHandle.hdma[dmaSource]) != HAL_OK)
{ {
/* Initialization Error */ /* Initialization Error */
return; return;
@ -140,7 +125,7 @@ void ws2811LedStripHardwareInit(void)
TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET; TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;
TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE; 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 */ /* Configuration Error */
return; return;
@ -160,7 +145,7 @@ void ws2811LedStripDMAEnable(void)
return; 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 */ /* Starting PWM generation Error */
ws2811LedDataTransferInProgress = 0; ws2811LedDataTransferInProgress = 0;

View file

@ -30,8 +30,13 @@
#include "rcc.h" #include "rcc.h"
#include "timer.h" #include "timer.h"
#define WS2811_TIMER_HZ 24000000
#define WS2811_TIMER_PERIOD 29
static IO_t ws2811IO = IO_NONE; static IO_t ws2811IO = IO_NONE;
bool ws2811Initialised = false; bool ws2811Initialised = false;
static DMA_Channel_TypeDef *dmaChannel = NULL;
static TIM_TypeDef *timer = NULL;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) {
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { 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_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
DMA_InitTypeDef DMA_InitStructure; 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)); ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
IOConfigGPIO(ws2811IO, IO_CONFIG(GPIO_Speed_50MHz, GPIO_Mode_AF_PP)); IOConfigGPIO(ws2811IO, IO_CONFIG(GPIO_Speed_50MHz, GPIO_Mode_AF_PP));
RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE); RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE);
/* Compute the prescaler value */ /* Compute the prescaler value */
prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; uint16_t prescalerValue = (uint16_t) (SystemCoreClock / WS2811_TIMER_HZ) - 1;
/* Time base configuration */ /* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 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_Prescaler = prescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */ /* PWM1 Mode configuration: Channel1 */
TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCStructInit(&TIM_OCInitStructure);
@ -74,20 +85,17 @@ void ws2811LedStripHardwareInit(void)
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1Init(timer, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable);
TIM_CtrlPWMOutputs(TIM3, ENABLE); TIM_CtrlPWMOutputs(timer, ENABLE);
/* configure DMA */ /* configure DMA */
/* DMA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA1 Channel6 Config */ /* DMA1 Channel6 Config */
DMA_DeInit(DMA1_Channel6); DMA_DeInit(dmaChannel);
DMA_StructInit(&DMA_InitStructure); 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_MemoryBaseAddr = (uint32_t)ledStripDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; 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_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel6, &DMA_InitStructure); DMA_Init(dmaChannel, &DMA_InitStructure);
/* TIM3 CC1 DMA Request enable */ /* 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}; const hsvColor_t hsv_white = { 0, 255, 255};
ws2811Initialised = true; ws2811Initialised = true;
@ -117,10 +126,10 @@ void ws2811LedStripDMAEnable(void)
if (!ws2811Initialised) if (!ws2811Initialised)
return; return;
DMA_SetCurrDataCounter(DMA1_Channel6, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred DMA_SetCurrDataCounter(dmaChannel, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(TIM3, 0); TIM_SetCounter(timer, 0);
TIM_Cmd(TIM3, ENABLE); TIM_Cmd(timer, ENABLE);
DMA_Cmd(DMA1_Channel6, ENABLE); DMA_Cmd(dmaChannel, ENABLE);
} }
#endif #endif

View file

@ -31,16 +31,13 @@
#include "rcc.h" #include "rcc.h"
#include "timer.h" #include "timer.h"
#ifndef WS2811_PIN #define WS2811_TIMER_HZ 24000000
#define WS2811_PIN PB8 // TIM16_CH1 #define WS2811_TIMER_PERIOD 29
#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
static IO_t ws2811IO = IO_NONE; static IO_t ws2811IO = IO_NONE;
bool ws2811Initialised = false; bool ws2811Initialised = false;
static DMA_Channel_TypeDef *dmaChannel = NULL;
static TIM_TypeDef *timer = NULL;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) {
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { 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_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
DMA_InitTypeDef DMA_InitStructure; 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)); ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); 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 */ /* Compute the prescaler value */
prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; uint16_t prescalerValue = (uint16_t) (SystemCoreClock / WS2811_TIMER_HZ) - 1;
/* Time base configuration */ /* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); 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_Prescaler = prescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration */ /* PWM1 Mode configuration */
TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 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_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(timer, &TIM_OCInitStructure);
TIM_OC1Init(WS2811_TIMER, &TIM_OCInitStructure); TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable);
TIM_OC1PreloadConfig(WS2811_TIMER, TIM_OCPreload_Enable);
TIM_CtrlPWMOutputs(timer, ENABLE);
TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE); dmaChannel = timerHardware->dmaChannel;
/* configure DMA */ /* configure DMA */
/* DMA1 Channel Config */ /* DMA1 Channel Config */
DMA_DeInit(WS2811_DMA_CHANNEL); DMA_DeInit(dmaChannel);
DMA_StructInit(&DMA_InitStructure); 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_MemoryBaseAddr = (uint32_t)ledStripDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; 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_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 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}; const hsvColor_t hsv_white = { 0, 255, 255};
ws2811Initialised = true; ws2811Initialised = true;
@ -123,10 +136,10 @@ void ws2811LedStripDMAEnable(void)
if (!ws2811Initialised) if (!ws2811Initialised)
return; return;
DMA_SetCurrDataCounter(WS2811_DMA_CHANNEL, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred DMA_SetCurrDataCounter(dmaChannel, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(WS2811_TIMER, 0); TIM_SetCounter(timer, 0);
TIM_Cmd(WS2811_TIMER, ENABLE); TIM_Cmd(timer, ENABLE);
DMA_Cmd(WS2811_DMA_CHANNEL, ENABLE); DMA_Cmd(dmaChannel, ENABLE);
} }
#endif #endif

View file

@ -31,85 +31,93 @@
#include "rcc.h" #include "rcc.h"
#include "timer.h" #include "timer.h"
#include "timer_stm32f4xx.h" #include "timer_stm32f4xx.h"
#include "io.h"
#if !defined(WS2811_PIN) #define WS2811_TIMER_HZ 84000000
#define WS2811_PIN PA0 #define WS2811_TIMER_PERIOD 104
#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
static IO_t ws2811IO = IO_NONE; static IO_t ws2811IO = IO_NONE;
static uint16_t timDMASource = 0;
bool ws2811Initialised = false; bool ws2811Initialised = false;
static DMA_Stream_TypeDef *stream = NULL;
static TIM_TypeDef *timer = NULL;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
{ {
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
ws2811LedDataTransferInProgress = 0; ws2811LedDataTransferInProgress = 0;
DMA_Cmd(descriptor->stream, DISABLE); DMA_Cmd(descriptor->stream, DISABLE);
TIM_DMACmd(WS2811_TIMER, timDMASource, DISABLE);
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
} }
} }
void ws2811LedStripHardwareInit(void) void ws2811LedStripHardwareInit(ioTag_t ioTag)
{ {
if (!ioTag) {
return;
}
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
DMA_InitTypeDef DMA_InitStructure; 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 */ /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); 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 // Stop timer
TIM_Cmd(WS2811_TIMER, DISABLE); TIM_Cmd(timer, DISABLE);
/* Compute the prescaler value */ /* 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 */ /* 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_Prescaler = prescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */ /* PWM1 Mode configuration: Channel1 */
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPolarity_High : TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; } else {
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; 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_Pulse = 0;
timerOCInit(WS2811_TIMER, WS2811_TIMER_CHANNEL, &TIM_OCInitStructure); timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);
timerOCPreloadConfig(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_OCPreload_Enable); timerOCPreloadConfig(timer, timerHardware->channel, TIM_OCPreload_Enable);
timDMASource = timerDmaSource(WS2811_TIMER_CHANNEL);
TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE); TIM_CtrlPWMOutputs(timer, ENABLE);
TIM_ARRPreloadConfig(WS2811_TIMER, ENABLE); TIM_ARRPreloadConfig(timer, ENABLE);
TIM_CCxCmd(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_CCx_Enable); TIM_CCxCmd(timer, timerHardware->channel, TIM_CCx_Enable);
TIM_Cmd(WS2811_TIMER, ENABLE); TIM_Cmd(timer, ENABLE);
stream = timerHardware->dmaStream;
/* configure DMA */ /* configure DMA */
DMA_Cmd(WS2811_DMA_STREAM, DISABLE); DMA_Cmd(stream, DISABLE);
DMA_DeInit(WS2811_DMA_STREAM); DMA_DeInit(stream);
DMA_StructInit(&DMA_InitStructure); DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_Channel = WS2811_DMA_CHANNEL; DMA_InitStructure.DMA_Channel = timerHardware->dmaChannel;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(WS2811_TIMER, WS2811_TIMER_CHANNEL); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ledStripDMABuffer; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ledStripDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; 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_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_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_ITConfig(stream, DMA_IT_TC, ENABLE);
DMA_ClearITPendingBit(WS2811_DMA_STREAM, dmaFlag_IT_TCIF(WS2811_DMA_STREAM)); 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; ws2811Initialised = true;
setStripColor(&hsv_white); setStripColor(&hsv_white);
ws2811UpdateStrip(); ws2811UpdateStrip();
@ -142,10 +151,10 @@ void ws2811LedStripDMAEnable(void)
if (!ws2811Initialised) if (!ws2811Initialised)
return; return;
DMA_SetCurrDataCounter(WS2811_DMA_STREAM, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred DMA_SetCurrDataCounter(stream, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(WS2811_TIMER, 0); TIM_SetCounter(timer, 0);
DMA_Cmd(WS2811_DMA_STREAM, ENABLE); TIM_Cmd(timer, ENABLE);
TIM_DMACmd(WS2811_TIMER, timDMASource, ENABLE); DMA_Cmd(stream, ENABLE);
} }
#endif #endif

View file

@ -156,7 +156,6 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; 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_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High;
} }
TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_Pulse = 0;
timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure); timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);

View file

@ -146,6 +146,7 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
} }
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) { if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

View file

@ -810,6 +810,7 @@ volatile timCCR_t* timerCCR(TIM_TypeDef *tim, uint8_t channel)
return (volatile timCCR_t*)((volatile char*)&tim->CCR1 + channel); return (volatile timCCR_t*)((volatile char*)&tim->CCR1 + channel);
} }
#ifndef USE_HAL_DRIVER
uint16_t timerDmaSource(uint8_t channel) uint16_t timerDmaSource(uint8_t channel)
{ {
switch (channel) { switch (channel) {
@ -823,4 +824,5 @@ uint16_t timerDmaSource(uint8_t channel)
return TIM_DMA_CC4; return TIM_DMA_CC4;
} }
return 0; return 0;
} }
#endif

View file

@ -55,6 +55,7 @@ typedef uint32_t timCNT_t;
#endif #endif
typedef enum { typedef enum {
TIM_USE_ANY = 0x0,
TIM_USE_PPM = 0x1, TIM_USE_PPM = 0x1,
TIM_USE_PWM = 0x2, TIM_USE_PWM = 0x2,
TIM_USE_MOTOR = 0x4, TIM_USE_MOTOR = 0x4,
@ -92,11 +93,11 @@ typedef struct timerHardware_s {
#if defined(STM32F3) || defined(STM32F4) || defined(STM32F7) #if defined(STM32F3) || defined(STM32F4) || defined(STM32F7)
uint8_t alternateFunction; uint8_t alternateFunction;
#endif #endif
#if defined(USE_DSHOT) #if defined(USE_DSHOT) || defined(LED_STRIP)
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7)
DMA_Stream_TypeDef *dmaStream; DMA_Stream_TypeDef *dmaStream;
uint32_t dmaChannel; uint32_t dmaChannel;
#elif defined(STM32F3) #elif defined(STM32F3) || defined(STM32F1)
DMA_Channel_TypeDef *dmaChannel; DMA_Channel_TypeDef *dmaChannel;
#endif #endif
uint8_t dmaIrqHandler; uint8_t dmaIrqHandler;

View file

@ -867,3 +867,18 @@ const timerHardware_t *timerGetByTag(ioTag_t tag, timerUsageFlag_e flag)
} }
return NULL; 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;
}

View file

@ -42,6 +42,7 @@
#include "drivers/pwm_output.h" #include "drivers/pwm_output.h"
#include "drivers/max7456.h" #include "drivers/max7456.h"
#include "drivers/sound_beeper.h" #include "drivers/sound_beeper.h"
#include "drivers/light_ws2811strip.h"
#include "fc/config.h" #include "fc/config.h"
#include "fc/rc_controls.h" #include "fc/rc_controls.h"
@ -238,6 +239,26 @@ void resetSensorAlignment(sensorAlignmentConfig_t *sensorAlignmentConfig)
sensorAlignmentConfig->mag_align = ALIGN_DEFAULT; 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 #ifdef USE_SERVOS
void resetServoConfig(servoConfig_t *servoConfig) void resetServoConfig(servoConfig_t *servoConfig)
{ {
@ -597,6 +618,10 @@ void createDefaultConfig(master_t *config)
#endif #endif
resetFlight3DConfig(&config->flight3DConfig); resetFlight3DConfig(&config->flight3DConfig);
#ifdef USE_LEDSTRIP
resetLedStripConfig(&config->ledStripConfig);
#endif
#ifdef GPS #ifdef GPS
// gps/nav stuff // gps/nav stuff
config->gpsConfig.provider = GPS_NMEA; config->gpsConfig.provider = GPS_NMEA;
@ -666,15 +691,6 @@ void createDefaultConfig(master_t *config)
config->customMotorMixer[i].throttle = 0.0f; 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 #ifdef VTX
config->vtx_band = 4; //Fatshark/Airwaves config->vtx_band = 4; //Fatshark/Airwaves
config->vtx_channel = 1; //CH1 config->vtx_channel = 1; //CH1

View file

@ -932,7 +932,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
#ifdef LED_STRIP #ifdef LED_STRIP
case MSP_LED_COLORS: case MSP_LED_COLORS:
for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { 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); sbufWriteU16(dst, color->h);
sbufWriteU8(dst, color->s); sbufWriteU8(dst, color->s);
sbufWriteU8(dst, color->v); sbufWriteU8(dst, color->v);
@ -941,7 +941,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
case MSP_LED_STRIP_CONFIG: case MSP_LED_STRIP_CONFIG:
for (i = 0; i < LED_MAX_STRIP_LENGTH; i++) { 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); sbufWriteU32(dst, *ledConfig);
} }
break; break;
@ -951,19 +951,19 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
for (int j = 0; j < LED_DIRECTION_COUNT; j++) { for (int j = 0; j < LED_DIRECTION_COUNT; j++) {
sbufWriteU8(dst, i); sbufWriteU8(dst, i);
sbufWriteU8(dst, j); 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++) { for (int j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) {
sbufWriteU8(dst, LED_MODE_COUNT); sbufWriteU8(dst, LED_MODE_COUNT);
sbufWriteU8(dst, j); sbufWriteU8(dst, j);
sbufWriteU8(dst, masterConfig.specialColors.color[j]); sbufWriteU8(dst, masterConfig.ledStripConfig.specialColors.color[j]);
} }
sbufWriteU8(dst, LED_AUX_CHANNEL); sbufWriteU8(dst, LED_AUX_CHANNEL);
sbufWriteU8(dst, 0); sbufWriteU8(dst, 0);
sbufWriteU8(dst, masterConfig.ledstrip_aux_channel); sbufWriteU8(dst, masterConfig.ledStripConfig.ledstrip_aux_channel);
break; break;
#endif #endif
@ -1656,7 +1656,7 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
#ifdef LED_STRIP #ifdef LED_STRIP
case MSP_SET_LED_COLORS: case MSP_SET_LED_COLORS:
for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { 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->h = sbufReadU16(src);
color->s = sbufReadU8(src); color->s = sbufReadU8(src);
color->v = sbufReadU8(src); color->v = sbufReadU8(src);
@ -1670,7 +1670,7 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
return MSP_RESULT_ERROR; return MSP_RESULT_ERROR;
break; break;
} }
ledConfig_t *ledConfig = &masterConfig.ledConfigs[i]; ledConfig_t *ledConfig = &masterConfig.ledStripConfig.ledConfigs[i];
*ledConfig = sbufReadU32(src); *ledConfig = sbufReadU32(src);
reevaluateLedConfig(); reevaluateLedConfig();
} }

View file

@ -88,6 +88,7 @@ PG_REGISTER_WITH_RESET_FN(specialColorIndexes_t, specialColors, PG_SPECIAL_COLOR
static bool ledStripInitialised = false; static bool ledStripInitialised = false;
static bool ledStripEnabled = true; static bool ledStripEnabled = true;
static ledStripConfig_t * currentLedStripConfig;
static void ledStripDisable(void); static void ledStripDisable(void);
@ -180,7 +181,7 @@ STATIC_UNIT_TESTED void determineLedStripDimensions(void)
int maxY = 0; int maxY = 0;
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
maxX = MAX(ledGetX(ledConfig), maxX); maxX = MAX(ledGetX(ledConfig), maxX);
maxY = MAX(ledGetY(ledConfig), maxY); maxY = MAX(ledGetY(ledConfig), maxY);
@ -202,7 +203,7 @@ STATIC_UNIT_TESTED void updateLedCount(void)
int count = 0, countRing = 0, countScanner= 0; int count = 0, countRing = 0, countScanner= 0;
for (int ledIndex = 0; ledIndex < LED_MAX_STRIP_LENGTH; ledIndex++) { for (int ledIndex = 0; ledIndex < LED_MAX_STRIP_LENGTH; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if (!(*ledConfig)) if (!(*ledConfig))
break; break;
@ -232,7 +233,7 @@ void reevaluateLedConfig(void)
// get specialColor by index // get specialColor by index
static hsvColor_t* getSC(ledSpecialColorIds_e index) static hsvColor_t* getSC(ledSpecialColorIds_e index)
{ {
return &masterConfig.colors[masterConfig.specialColors.color[index]]; return &currentLedStripConfig->colors[currentLedStripConfig->specialColors.color[index]];
} }
static const char directionCodes[LED_DIRECTION_COUNT] = { 'N', 'E', 'S', 'W', 'U', 'D' }; 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'}; static const char chunkSeparators[PARSE_STATE_COUNT] = {',', ':', ':', ':', '\0'};
ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
memset(ledConfig, 0, sizeof(ledConfig_t)); memset(ledConfig, 0, sizeof(ledConfig_t));
int x = 0, y = 0, color = 0; // initialize to prevent warnings int x = 0, y = 0, color = 0; // initialize to prevent warnings
@ -375,7 +376,7 @@ typedef enum {
static quadrant_e getLedQuadrant(const int ledIndex) static quadrant_e getLedQuadrant(const int ledIndex)
{ {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
int x = ledGetX(ledConfig); int x = ledGetX(ledConfig);
int y = ledGetY(ledConfig); int y = ledGetY(ledConfig);
@ -417,7 +418,7 @@ static const struct {
static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIndexes_t *modeColors) static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIndexes_t *modeColors)
{ {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
quadrant_e quad = getLedQuadrant(ledIndex); quadrant_e quad = getLedQuadrant(ledIndex);
for (unsigned i = 0; i < ARRAYLEN(directionQuadrantMap); i++) { 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; quadrant_e quadMask = directionQuadrantMap[i].quadrantMask;
if (ledGetDirectionBit(ledConfig, dir) && (quad & quadMask)) if (ledGetDirectionBit(ledConfig, dir) && (quad & quadMask))
return &masterConfig.colors[modeColors->color[dir]]; return &currentLedStripConfig->colors[modeColors->color[dir]];
} }
return NULL; return NULL;
} }
@ -451,7 +452,7 @@ static const struct {
static void applyLedFixedLayers() static void applyLedFixedLayers()
{ {
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND); hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND);
int fn = ledGetFunction(ledConfig); int fn = ledGetFunction(ledConfig);
@ -459,13 +460,13 @@ static void applyLedFixedLayers()
switch (fn) { switch (fn) {
case LED_FUNCTION_COLOR: case LED_FUNCTION_COLOR:
color = masterConfig.colors[ledGetColor(ledConfig)]; color = currentLedStripConfig->colors[ledGetColor(ledConfig)];
break; break;
case LED_FUNCTION_FLIGHT_MODE: case LED_FUNCTION_FLIGHT_MODE:
for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++) for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++)
if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) { if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) {
hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &masterConfig.modeColors[flightModeToLed[i].ledMode]); hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &currentLedStripConfig->modeColors[flightModeToLed[i].ledMode]);
if (directionalColor) { if (directionalColor) {
color = *directionalColor; color = *directionalColor;
} }
@ -506,7 +507,7 @@ static void applyLedFixedLayers()
static void applyLedHsv(uint32_t mask, const hsvColor_t *color) static void applyLedHsv(uint32_t mask, const hsvColor_t *color)
{ {
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if ((*ledConfig & mask) == mask) if ((*ledConfig & mask) == mask)
setLedHsv(ledIndex, color); setLedHsv(ledIndex, color);
} }
@ -702,7 +703,7 @@ static void applyLedIndicatorLayer(bool updateNow, uint32_t *timer)
} }
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if (ledGetOverlayBit(ledConfig, LED_OVERLAY_INDICATOR)) { if (ledGetOverlayBit(ledConfig, LED_OVERLAY_INDICATOR)) {
if (getLedQuadrant(ledIndex) & quadrants) if (getLedQuadrant(ledIndex) & quadrants)
setLedHsv(ledIndex, flashColor); setLedHsv(ledIndex, flashColor);
@ -743,7 +744,7 @@ static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer)
} }
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if (ledGetFunction(ledConfig) == LED_FUNCTION_THRUST_RING) { if (ledGetFunction(ledConfig) == LED_FUNCTION_THRUST_RING) {
bool applyColor; bool applyColor;
@ -754,7 +755,7 @@ static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer)
} }
if (applyColor) { if (applyColor) {
const hsvColor_t *ringColor = &masterConfig.colors[ledGetColor(ledConfig)]; const hsvColor_t *ringColor = &currentLedStripConfig->colors[ledGetColor(ledConfig)];
setLedHsv(ledIndex, ringColor); setLedHsv(ledIndex, ringColor);
} }
@ -870,7 +871,7 @@ static void applyLedAnimationLayer(bool updateNow, uint32_t *timer)
int nextRow = (frameCounter + 1 < animationFrames) ? frameCounter + 1 : 0; int nextRow = (frameCounter + 1 < animationFrames) ? frameCounter + 1 : 0;
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if (ledGetY(ledConfig) == previousRow) { if (ledGetY(ledConfig) == previousRow) {
setLedHsv(ledIndex, getSC(LED_SCOLOR_ANIMATION)); setLedHsv(ledIndex, getSC(LED_SCOLOR_ANIMATION));
@ -932,7 +933,7 @@ void ledStripUpdate(uint32_t currentTime)
return; 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) { if (ledStripEnabled) {
ledStripDisable(); ledStripDisable();
ledStripEnabled = false; ledStripEnabled = false;
@ -963,7 +964,7 @@ void ledStripUpdate(uint32_t currentTime)
// apply all layers; triggered timed functions has to update timers // 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; 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(); applyLedFixedLayers();
@ -979,7 +980,7 @@ bool parseColor(int index, const char *colorConfig)
{ {
const char *remainingCharacters = colorConfig; const char *remainingCharacters = colorConfig;
hsvColor_t *color = &masterConfig.colors[index]; hsvColor_t *color = &currentLedStripConfig->colors[index];
bool result = true; bool result = true;
static const uint16_t hsv_limit[HSV_COLOR_COMPONENT_COUNT] = { 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 (modeIndex < LED_MODE_COUNT) { // modeIndex_e is unsigned, so one-sided test is enough
if(modeColorIndex < 0 || modeColorIndex >= LED_DIRECTION_COUNT) if(modeColorIndex < 0 || modeColorIndex >= LED_DIRECTION_COUNT)
return false; return false;
masterConfig.modeColors[modeIndex].color[modeColorIndex] = colorIndex; currentLedStripConfig->modeColors[modeIndex].color[modeColorIndex] = colorIndex;
} else if (modeIndex == LED_SPECIAL) { } else if (modeIndex == LED_SPECIAL) {
if (modeColorIndex < 0 || modeColorIndex >= LED_SPECIAL_COLOR_COUNT) if (modeColorIndex < 0 || modeColorIndex >= LED_SPECIAL_COLOR_COUNT)
return false; return false;
masterConfig.specialColors.color[modeColorIndex] = colorIndex; currentLedStripConfig->specialColors.color[modeColorIndex] = colorIndex;
} else if (modeIndex == LED_AUX_CHANNEL) { } else if (modeIndex == LED_AUX_CHANNEL) {
if (modeColorIndex < 0 || modeColorIndex >= 1) if (modeColorIndex < 0 || modeColorIndex >= 1)
return false; return false;
masterConfig.ledstrip_aux_channel = colorIndex; currentLedStripConfig->ledstrip_aux_channel = colorIndex;
} else { } else {
return false; return false;
} }
@ -1098,21 +1099,26 @@ void applyDefaultSpecialColors(specialColorIndexes_t *specialColors)
memcpy_fn(specialColors, &defaultSpecialColors, sizeof(defaultSpecialColors)); 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; currentLedStripConfig = ledStripConfig;
colors = colorsToUse;
modeColors = modeColorsToUse; ledConfigs = currentLedStripConfig->ledConfigs;
specialColors = *specialColorsToUse; colors = currentLedStripConfig->colors;
modeColors = currentLedStripConfig->modeColors;
specialColors = currentLedStripConfig->specialColors;
ledStripInitialised = false; ledStripInitialised = false;
} }
void ledStripEnable(void) void ledStripEnable(void)
{ {
if (currentLedStripConfig == NULL) {
return;
}
reevaluateLedConfig(); reevaluateLedConfig();
ledStripInitialised = true; ledStripInitialised = true;
ws2811LedStripInit(); ws2811LedStripInit(currentLedStripConfig->ioTag);
} }
static void ledStripDisable(void) static void ledStripDisable(void)

View file

@ -18,6 +18,7 @@
#pragma once #pragma once
#include "common/color.h" #include "common/color.h"
#include "drivers/io.h"
#define LED_MAX_STRIP_LENGTH 32 #define LED_MAX_STRIP_LENGTH 32
#define LED_CONFIGURABLE_COLOR_COUNT 16 #define LED_CONFIGURABLE_COLOR_COUNT 16
@ -135,6 +136,15 @@ typedef struct ledCounts_s {
uint8_t ringSeqLen; uint8_t ringSeqLen;
} ledCounts_t; } 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; ledConfig_t *ledConfigs;
hsvColor_t *colors; 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 generateLedConfig(ledConfig_t *ledConfig, char *ledConfigBuffer, size_t bufferSize);
void reevaluateLedConfig(void); 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 ledStripEnable(void);
void ledStripUpdate(uint32_t currentTime); void ledStripUpdate(uint32_t currentTime);

View file

@ -935,7 +935,7 @@ const clivalue_t valueTable[] = {
{ "magzero_z", VAR_INT16 | MASTER_VALUE, &masterConfig.magZero.raw[Z], .config.minmax = { -32768, 32767 } }, { "magzero_z", VAR_INT16 | MASTER_VALUE, &masterConfig.magZero.raw[Z], .config.minmax = { -32768, 32767 } },
#endif #endif
#ifdef LED_STRIP #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 #endif
#ifdef USE_RTC6705 #ifdef USE_RTC6705
{ "vtx_channel", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_channel, .config.minmax = { 0, 39 } }, { "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 ledConfigBuffer[20];
char ledConfigDefaultBuffer[20]; char ledConfigDefaultBuffer[20];
for (uint32_t i = 0; i < LED_MAX_STRIP_LENGTH; i++) { for (uint32_t i = 0; i < LED_MAX_STRIP_LENGTH; i++) {
ledConfig = masterConfig.ledConfigs[i]; ledConfig = masterConfig.ledStripConfig.ledConfigs[i];
ledConfigDefault = defaultConfig->ledConfigs[i]; ledConfigDefault = defaultConfig->ledStripConfig.ledConfigs[i];
equalsDefault = ledConfig == ledConfigDefault; equalsDefault = ledConfig == ledConfigDefault;
generateLedConfig(&ledConfig, ledConfigBuffer, sizeof(ledConfigBuffer)); generateLedConfig(&ledConfig, ledConfigBuffer, sizeof(ledConfigBuffer));
generateLedConfig(&ledConfigDefault, ledConfigDefaultBuffer, sizeof(ledConfigDefaultBuffer)); generateLedConfig(&ledConfigDefault, ledConfigDefaultBuffer, sizeof(ledConfigDefaultBuffer));
@ -1743,8 +1743,8 @@ static void printColor(uint8_t dumpMask, master_t *defaultConfig)
hsvColor_t *colorDefault; hsvColor_t *colorDefault;
bool equalsDefault; bool equalsDefault;
for (uint32_t i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { for (uint32_t i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
color = &masterConfig.colors[i]; color = &masterConfig.ledStripConfig.colors[i];
colorDefault = &defaultConfig->colors[i]; colorDefault = &defaultConfig->ledStripConfig.colors[i];
equalsDefault = color->h == colorDefault->h equalsDefault = color->h == colorDefault->h
&& color->s == colorDefault->s && color->s == colorDefault->s
&& color->v == colorDefault->v; && 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 i = 0; i < LED_MODE_COUNT; i++) {
for (uint32_t j = 0; j < LED_DIRECTION_COUNT; j++) { for (uint32_t j = 0; j < LED_DIRECTION_COUNT; j++) {
int colorIndex = masterConfig.modeColors[i].color[j]; int colorIndex = masterConfig.ledStripConfig.modeColors[i].color[j];
int colorIndexDefault = defaultConfig->modeColors[i].color[j]; int colorIndexDefault = defaultConfig->ledStripConfig.modeColors[i].color[j];
const char *format = "mode_color %u %u %u\r\n"; const char *format = "mode_color %u %u %u\r\n";
cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndexDefault); cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndexDefault);
cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndex); 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"; const char *format = "mode_color %u %u %u\r\n";
for (uint32_t j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) { for (uint32_t j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) {
int colorIndex = masterConfig.specialColors.color[j]; int colorIndex = masterConfig.ledStripConfig.specialColors.color[j];
int colorIndexDefault = defaultConfig->specialColors.color[j]; int colorIndexDefault = defaultConfig->ledStripConfig.specialColors.color[j];
cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndexDefault); cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndexDefault);
cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndex); cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndex);
} }
int ledStripAuxChannel = masterConfig.ledstrip_aux_channel; int ledStripAuxChannel = masterConfig.ledStripConfig.ledstrip_aux_channel;
int ledStripAuxChannelDefault = defaultConfig->ledstrip_aux_channel; int ledStripAuxChannelDefault = defaultConfig->ledStripConfig.ledstrip_aux_channel;
cliDefaultPrintf(dumpMask, ledStripAuxChannel == ledStripAuxChannelDefault, format, LED_AUX_CHANNEL, 0, ledStripAuxChannelDefault); cliDefaultPrintf(dumpMask, ledStripAuxChannel == ledStripAuxChannelDefault, format, LED_AUX_CHANNEL, 0, ledStripAuxChannelDefault);
cliDumpPrintf(dumpMask, ledStripAuxChannel == ledStripAuxChannelDefault, format, LED_AUX_CHANNEL, 0, ledStripAuxChannel); cliDumpPrintf(dumpMask, ledStripAuxChannel == ledStripAuxChannelDefault, format, LED_AUX_CHANNEL, 0, ledStripAuxChannel);
} }
@ -3743,19 +3743,22 @@ typedef struct {
const cliResourceValue_t resourceTable[] = { const cliResourceValue_t resourceTable[] = {
#ifdef BEEPER #ifdef BEEPER
{ OWNER_BEEPER, &masterConfig.beeperConfig.ioTag, 0 }, { OWNER_BEEPER, &masterConfig.beeperConfig.ioTag, 0 },
#endif #endif
{ OWNER_MOTOR, &masterConfig.motorConfig.ioTags[0], MAX_SUPPORTED_MOTORS }, { OWNER_MOTOR, &masterConfig.motorConfig.ioTags[0], MAX_SUPPORTED_MOTORS },
#ifdef USE_SERVOS #ifdef USE_SERVOS
{ OWNER_SERVO, &masterConfig.servoConfig.ioTags[0], MAX_SUPPORTED_SERVOS }, { OWNER_SERVO, &masterConfig.servoConfig.ioTags[0], MAX_SUPPORTED_SERVOS },
#endif #endif
#ifndef SKIP_RX_PWM_PPM #ifndef SKIP_RX_PWM_PPM
{ OWNER_PPMINPUT, &masterConfig.ppmConfig.ioTag, 0 }, { OWNER_PPMINPUT, &masterConfig.ppmConfig.ioTag, 0 },
{ OWNER_PWMINPUT, &masterConfig.pwmConfig.ioTags[0], PWM_INPUT_PORT_COUNT }, { OWNER_PWMINPUT, &masterConfig.pwmConfig.ioTags[0], PWM_INPUT_PORT_COUNT },
#endif #endif
#ifdef SONAR #ifdef SONAR
{ OWNER_SONAR_TRIGGER, &masterConfig.sonarConfig.triggerTag, 0 }, { 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 #endif
}; };

View file

@ -482,7 +482,7 @@ void init(void)
#endif #endif
#ifdef LED_STRIP #ifdef LED_STRIP
ledStripInit(masterConfig.ledConfigs, masterConfig.colors, masterConfig.modeColors, &masterConfig.specialColors); ledStripInit(&masterConfig.ledStripConfig);
if (feature(FEATURE_LED_STRIP)) { if (feature(FEATURE_LED_STRIP)) {
ledStripEnable(); ledStripEnable();