Moving LED strip to be configurable via resource command
This commit is contained in:
parent
3b506415c9
commit
e56f915018
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue