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
#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

View File

@ -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();
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;

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);
}
#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

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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 = &currentLedStripConfig->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 = &currentLedStripConfig->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 &currentLedStripConfig->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 = &currentLedStripConfig->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 = &currentLedStripConfig->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 = &currentLedStripConfig->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 &currentLedStripConfig->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 = &currentLedStripConfig->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, &currentLedStripConfig->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 = &currentLedStripConfig->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 = &currentLedStripConfig->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 = &currentLedStripConfig->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 = &currentLedStripConfig->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 = &currentLedStripConfig->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 = &currentLedStripConfig->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)

View File

@ -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);

View File

@ -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
};

View File

@ -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();