1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-19 22:35:23 +03:00

Merge remote-tracking branch 'betaflight/master' into bfdev-osd-cms-separation-poc

This commit is contained in:
jflyper 2016-11-06 02:43:24 +09:00
commit e9a2f2b2c1
42 changed files with 640 additions and 344 deletions

View file

@ -736,11 +736,7 @@ OPTIMIZE = -O0
LTO_FLAGS = $(OPTIMIZE) LTO_FLAGS = $(OPTIMIZE)
else else
OPTIMIZE = -Os OPTIMIZE = -Os
ifeq ($(TARGET),$(filter $(TARGET),$(F1_TARGETS)))
LTO_FLAGS = -flto -fuse-linker-plugin $(OPTIMIZE) LTO_FLAGS = -flto -fuse-linker-plugin $(OPTIMIZE)
else
LTO_FLAGS = -fuse-linker-plugin $(OPTIMIZE)
endif
endif endif
DEBUG_FLAGS = -ggdb3 -DDEBUG DEBUG_FLAGS = -ggdb3 -DDEBUG

View file

@ -1169,7 +1169,7 @@ static bool blackboxWriteSysinfo()
switch (xmitState.headerIndex) { switch (xmitState.headerIndex) {
BLACKBOX_PRINT_HEADER_LINE("Firmware type:%s", "Cleanflight"); BLACKBOX_PRINT_HEADER_LINE("Firmware type:%s", "Cleanflight");
BLACKBOX_PRINT_HEADER_LINE("Firmware revision:Betaflight %s (%s) %s", FC_VERSION_STRING, shortGitRevision, targetName); BLACKBOX_PRINT_HEADER_LINE("Firmware revision:%s %s (%s) %s", FC_FIRMWARE_NAME, FC_VERSION_STRING, shortGitRevision, targetName);
BLACKBOX_PRINT_HEADER_LINE("Firmware date:%s %s", buildDate, buildTime); BLACKBOX_PRINT_HEADER_LINE("Firmware date:%s %s", buildDate, buildTime);
BLACKBOX_PRINT_HEADER_LINE("Craft name:%s", masterConfig.name); BLACKBOX_PRINT_HEADER_LINE("Craft name:%s", masterConfig.name);
BLACKBOX_PRINT_HEADER_LINE("P interval:%d/%d", masterConfig.blackbox_rate_num, masterConfig.blackbox_rate_denom); BLACKBOX_PRINT_HEADER_LINE("P interval:%d/%d", masterConfig.blackbox_rate_num, masterConfig.blackbox_rate_denom);

View file

@ -15,6 +15,7 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define FC_FIRMWARE_NAME "Betaflight"
#define FC_VERSION_MAJOR 3 // increment when a major release is made (big new feature, etc) #define FC_VERSION_MAJOR 3 // increment when a major release is made (big new feature, etc)
#define FC_VERSION_MINOR 1 // increment when a minor release is made (small new feature, change etc) #define FC_VERSION_MINOR 1 // increment when a minor release is made (small new feature, change etc)
#define FC_VERSION_PATCH_LEVEL 0 // increment when a bug is fixed #define FC_VERSION_PATCH_LEVEL 0 // increment when a bug is fixed

View file

@ -162,11 +162,7 @@ typedef struct master_s {
#endif #endif
#ifdef LED_STRIP #ifdef LED_STRIP
ledConfig_t ledConfigs[LED_MAX_STRIP_LENGTH]; ledStripConfig_t ledStripConfig;
hsvColor_t colors[LED_CONFIGURABLE_COLOR_COUNT];
modeColorIndexes_t modeColors[LED_MODE_COUNT];
specialColorIndexes_t specialColors;
uint8_t ledstrip_visual_beeper; // suppress LEDLOW mode if beeper is on
#endif #endif
#ifdef TRANSPONDER #ifdef TRANSPONDER

View file

@ -15,9 +15,12 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once
#define MPU6500_WHO_AM_I_CONST (0x70) #define MPU6500_WHO_AM_I_CONST (0x70)
#define MPU9250_WHO_AM_I_CONST (0x71) #define MPU9250_WHO_AM_I_CONST (0x71)
#define ICM20608G_WHO_AM_I_CONST (0xAF) #define ICM20608G_WHO_AM_I_CONST (0xAF)
#define ICM20602_WHO_AM_I_CONST (0x12)
#define MPU6500_BIT_RESET (0x80) #define MPU6500_BIT_RESET (0x80)
#define MPU6500_BIT_INT_ANYRD_2CLEAR (1 << 4) #define MPU6500_BIT_INT_ANYRD_2CLEAR (1 << 4)
@ -25,8 +28,6 @@
#define MPU6500_BIT_I2C_IF_DIS (1 << 4) #define MPU6500_BIT_I2C_IF_DIS (1 << 4)
#define MPU6500_BIT_RAW_RDY_EN (0x01) #define MPU6500_BIT_RAW_RDY_EN (0x01)
#pragma once
bool mpu6500AccDetect(acc_t *acc); bool mpu6500AccDetect(acc_t *acc);
bool mpu6500GyroDetect(gyro_t *gyro); bool mpu6500GyroDetect(gyro_t *gyro);

View file

@ -84,7 +84,10 @@ bool mpu6500SpiDetect(void)
mpu6500ReadRegister(MPU_RA_WHO_AM_I, 1, &tmp); mpu6500ReadRegister(MPU_RA_WHO_AM_I, 1, &tmp);
if (tmp == MPU6500_WHO_AM_I_CONST || tmp == MPU9250_WHO_AM_I_CONST || tmp == ICM20608G_WHO_AM_I_CONST) { if (tmp == MPU6500_WHO_AM_I_CONST ||
tmp == MPU9250_WHO_AM_I_CONST ||
tmp == ICM20608G_WHO_AM_I_CONST ||
tmp == ICM20602_WHO_AM_I_CONST) {
return true; return true;
} }

View file

@ -15,6 +15,7 @@
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>. * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once
struct dmaChannelDescriptor_s; struct dmaChannelDescriptor_s;
typedef void (*dmaCallbackHandlerFuncPtr)(struct dmaChannelDescriptor_s *channelDescriptor); typedef void (*dmaCallbackHandlerFuncPtr)(struct dmaChannelDescriptor_s *channelDescriptor);

View file

@ -8,7 +8,7 @@ typedef uint8_t ioTag_t; // packet tag to specify IO pin
typedef void* IO_t; // type specifying IO pin. Currently ioRec_t pointer, but this may change typedef void* IO_t; // type specifying IO pin. Currently ioRec_t pointer, but this may change
// NONE initializer for ioTag_t variables // NONE initializer for ioTag_t variables
#define IO_TAG_NONE ((ioTag_t)0) #define IO_TAG_NONE IO_TAG(NONE)
// NONE initializer for IO_t variable // NONE initializer for IO_t variable
#define IO_NONE ((IO_t)0) #define IO_NONE ((IO_t)0)

View file

@ -37,6 +37,7 @@
#include "common/color.h" #include "common/color.h"
#include "common/colorconversion.h" #include "common/colorconversion.h"
#include "dma.h" #include "dma.h"
#include "io.h"
#include "light_ws2811strip.h" #include "light_ws2811strip.h"
#if defined(STM32F4) || defined(STM32F7) #if defined(STM32F4) || defined(STM32F7)
@ -84,10 +85,10 @@ void setStripColors(const hsvColor_t *colors)
} }
} }
void ws2811LedStripInit(void) void ws2811LedStripInit(ioTag_t ioTag)
{ {
memset(&ledStripDMABuffer, 0, WS2811_DMA_BUFFER_SIZE); memset(&ledStripDMABuffer, 0, WS2811_DMA_BUFFER_SIZE);
ws2811LedStripHardwareInit(); ws2811LedStripHardwareInit(ioTag);
ws2811UpdateStrip(); ws2811UpdateStrip();
} }

View file

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

View file

@ -31,26 +31,15 @@
#include "rcc.h" #include "rcc.h"
#include "timer.h" #include "timer.h"
#if !defined(WS2811_PIN)
#define WS2811_PIN PA0
#define WS2811_TIMER TIM5
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_ST2_HANDLER
#define WS2811_DMA_STREAM DMA1_Stream2
#define WS2811_DMA_IT DMA_IT_TCIF2
#define WS2811_DMA_CHANNEL DMA_Channel_6
#define WS2811_TIMER_CHANNEL TIM_Channel_1
#define WS2811_TIMER_GPIO_AF GPIO_AF2_TIM5
#endif
static IO_t ws2811IO = IO_NONE; static IO_t ws2811IO = IO_NONE;
static uint16_t timDMASource = 0;
bool ws2811Initialised = false; bool ws2811Initialised = false;
static TIM_HandleTypeDef TimHandle; static TIM_HandleTypeDef TimHandle;
static uint16_t timerChannel = 0;
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim) void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{ {
if(htim->Instance==WS2811_TIMER) if(htim->Instance == TimHandle.Instance)
{ {
//HAL_TIM_PWM_Stop_DMA(&TimHandle,WS2811_TIMER_CHANNEL); //HAL_TIM_PWM_Stop_DMA(&TimHandle,WS2811_TIMER_CHANNEL);
ws2811LedDataTransferInProgress = 0; ws2811LedDataTransferInProgress = 0;
@ -62,9 +51,20 @@ void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor)
HAL_DMA_IRQHandler(TimHandle.hdma[descriptor->userParam]); HAL_DMA_IRQHandler(TimHandle.hdma[descriptor->userParam]);
} }
void ws2811LedStripHardwareInit(void) void ws2811LedStripHardwareInit(ioTag_t ioTag)
{ {
TimHandle.Instance = WS2811_TIMER; if (!ioTag) {
return;
}
const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
TIM_TypeDef *timer = timerHardware->tim;
timerChannel = timerHardware->channel;
if (timerHardware->dmaStream == NULL) {
return;
}
TimHandle.Instance = timer;
TimHandle.Init.Prescaler = 1; TimHandle.Init.Prescaler = 1;
TimHandle.Init.Period = 135; // 800kHz TimHandle.Init.Period = 135; // 800kHz
@ -78,16 +78,14 @@ void ws2811LedStripHardwareInit(void)
static DMA_HandleTypeDef hdma_tim; static DMA_HandleTypeDef hdma_tim;
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); ws2811IO = IOGetByTag(ioTag);
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), WS2811_TIMER_GPIO_AF); IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), timerHardware->alternateFunction);
__DMA1_CLK_ENABLE(); __DMA1_CLK_ENABLE();
/* Set the parameters to be configured */ /* Set the parameters to be configured */
hdma_tim.Init.Channel = WS2811_DMA_CHANNEL; hdma_tim.Init.Channel = timerHardware->dmaChannel;
hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim.Init.MemInc = DMA_MINC_ENABLE; hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
@ -101,30 +99,17 @@ void ws2811LedStripHardwareInit(void)
hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE; hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
/* Set hdma_tim instance */ /* Set hdma_tim instance */
hdma_tim.Instance = WS2811_DMA_STREAM; hdma_tim.Instance = timerHardware->dmaStream;
switch (WS2811_TIMER_CHANNEL) { uint16_t dmaSource = timerDmaSource(timerChannel);
case TIM_CHANNEL_1:
timDMASource = TIM_DMA_ID_CC1;
break;
case TIM_CHANNEL_2:
timDMASource = TIM_DMA_ID_CC2;
break;
case TIM_CHANNEL_3:
timDMASource = TIM_DMA_ID_CC3;
break;
case TIM_CHANNEL_4:
timDMASource = TIM_DMA_ID_CC4;
break;
}
/* Link hdma_tim to hdma[x] (channelx) */ /* Link hdma_tim to hdma[x] (channelx) */
__HAL_LINKDMA(&TimHandle, hdma[timDMASource], hdma_tim); __HAL_LINKDMA(&TimHandle, hdma[dmaSource], hdma_tim);
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, timDMASource); dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, dmaSource);
/* Initialize TIMx DMA handle */ /* Initialize TIMx DMA handle */
if(HAL_DMA_Init(TimHandle.hdma[timDMASource]) != HAL_OK) if(HAL_DMA_Init(TimHandle.hdma[dmaSource]) != HAL_OK)
{ {
/* Initialization Error */ /* Initialization Error */
return; return;
@ -140,7 +125,7 @@ void ws2811LedStripHardwareInit(void)
TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET; TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;
TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE; TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE;
if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, WS2811_TIMER_CHANNEL) != HAL_OK) if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, timerChannel) != HAL_OK)
{ {
/* Configuration Error */ /* Configuration Error */
return; return;
@ -160,7 +145,7 @@ void ws2811LedStripDMAEnable(void)
return; return;
} }
if( HAL_TIM_PWM_Start_DMA(&TimHandle, WS2811_TIMER_CHANNEL, ledStripDMABuffer, WS2811_DMA_BUFFER_SIZE) != HAL_OK) if( HAL_TIM_PWM_Start_DMA(&TimHandle, timerChannel, ledStripDMABuffer, WS2811_DMA_BUFFER_SIZE) != HAL_OK)
{ {
/* Starting PWM generation Error */ /* Starting PWM generation Error */
ws2811LedDataTransferInProgress = 0; ws2811LedDataTransferInProgress = 0;

View file

@ -30,10 +30,16 @@
#include "rcc.h" #include "rcc.h"
#include "timer.h" #include "timer.h"
#define WS2811_TIMER_HZ 24000000
#define WS2811_TIMER_PERIOD 29
static IO_t ws2811IO = IO_NONE; static IO_t ws2811IO = IO_NONE;
bool ws2811Initialised = false; bool ws2811Initialised = false;
static DMA_Channel_TypeDef *dmaChannel = NULL;
static TIM_TypeDef *timer = NULL;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
{
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
ws2811LedDataTransferInProgress = 0; ws2811LedDataTransferInProgress = 0;
DMA_Cmd(descriptor->channel, DISABLE); DMA_Cmd(descriptor->channel, DISABLE);
@ -41,32 +47,38 @@ static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) {
} }
} }
void ws2811LedStripHardwareInit(void) void ws2811LedStripHardwareInit(ioTag_t ioTag)
{ {
if (!ioTag) {
return;
}
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
uint16_t prescalerValue; const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
timer = timerHardware->tim;
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); if (timerHardware->dmaChannel == NULL) {
return;
}
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
IOConfigGPIO(ws2811IO, IO_CONFIG(GPIO_Speed_50MHz, GPIO_Mode_AF_PP)); IOConfigGPIO(ws2811IO, IO_CONFIG(GPIO_Speed_50MHz, GPIO_Mode_AF_PP));
RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE); RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE);
/* Compute the prescaler value */ /* Compute the prescaler value */
prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; uint16_t prescalerValue = (uint16_t) (SystemCoreClock / WS2811_TIMER_HZ) - 1;
/* Time base configuration */ /* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 29; // 800kHz TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz
TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue; TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */ /* PWM1 Mode configuration: Channel1 */
TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCStructInit(&TIM_OCInitStructure);
@ -74,20 +86,17 @@ void ws2811LedStripHardwareInit(void)
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1Init(timer, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable);
TIM_CtrlPWMOutputs(TIM3, ENABLE); TIM_CtrlPWMOutputs(timer, ENABLE);
/* configure DMA */ /* configure DMA */
/* DMA clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* DMA1 Channel6 Config */ /* DMA1 Channel6 Config */
DMA_DeInit(DMA1_Channel6); DMA_DeInit(dmaChannel);
DMA_StructInit(&DMA_InitStructure); DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM3->CCR1; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ledStripDMABuffer; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ledStripDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE;
@ -99,12 +108,13 @@ void ws2811LedStripHardwareInit(void)
DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel6, &DMA_InitStructure); DMA_Init(dmaChannel, &DMA_InitStructure);
/* TIM3 CC1 DMA Request enable */ /* TIM3 CC1 DMA Request enable */
TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE); TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE);
DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE); DMA_ITConfig(dmaChannel, DMA_IT_TC, ENABLE);
dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
const hsvColor_t hsv_white = { 0, 255, 255}; const hsvColor_t hsv_white = { 0, 255, 255};
ws2811Initialised = true; ws2811Initialised = true;
@ -117,10 +127,10 @@ void ws2811LedStripDMAEnable(void)
if (!ws2811Initialised) if (!ws2811Initialised)
return; return;
DMA_SetCurrDataCounter(DMA1_Channel6, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred DMA_SetCurrDataCounter(dmaChannel, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(TIM3, 0); TIM_SetCounter(timer, 0);
TIM_Cmd(TIM3, ENABLE); TIM_Cmd(timer, ENABLE);
DMA_Cmd(DMA1_Channel6, ENABLE); DMA_Cmd(dmaChannel, ENABLE);
} }
#endif #endif

View file

@ -31,18 +31,16 @@
#include "rcc.h" #include "rcc.h"
#include "timer.h" #include "timer.h"
#ifndef WS2811_PIN #define WS2811_TIMER_HZ 24000000
#define WS2811_PIN PB8 // TIM16_CH1 #define WS2811_TIMER_PERIOD 29
#define WS2811_TIMER TIM16
#define WS2811_DMA_CHANNEL DMA1_Channel3
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_CH3_HANDLER
#define WS2811_TIMER_GPIO_AF GPIO_AF_1
#endif
static IO_t ws2811IO = IO_NONE; static IO_t ws2811IO = IO_NONE;
bool ws2811Initialised = false; bool ws2811Initialised = false;
static DMA_Channel_TypeDef *dmaChannel = NULL;
static TIM_TypeDef *timer = NULL;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) { static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
{
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
ws2811LedDataTransferInProgress = 0; ws2811LedDataTransferInProgress = 0;
DMA_Cmd(descriptor->channel, DISABLE); DMA_Cmd(descriptor->channel, DISABLE);
@ -50,51 +48,66 @@ static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) {
} }
} }
void ws2811LedStripHardwareInit(void) void ws2811LedStripHardwareInit(ioTag_t ioTag)
{ {
if (!ioTag) {
return;
}
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
uint16_t prescalerValue; const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
timer = timerHardware->tim;
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); if (timerHardware->dmaChannel == NULL) {
return;
}
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), WS2811_TIMER_GPIO_AF); IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction);
RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE); RCC_ClockCmd(timerRCC(timer), ENABLE);
/* Compute the prescaler value */ /* Compute the prescaler value */
prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1; uint16_t prescalerValue = (uint16_t) (SystemCoreClock / WS2811_TIMER_HZ) - 1;
/* Time base configuration */ /* Time base configuration */
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = 29; // 800kHz TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz
TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue; TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration */ /* PWM1 Mode configuration */
TIM_OCStructInit(&TIM_OCInitStructure); TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPolarity_High : TIM_OCNPolarity_Low;
} else {
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High;
}
TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(timer, &TIM_OCInitStructure);
TIM_OC1Init(WS2811_TIMER, &TIM_OCInitStructure); TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable);
TIM_OC1PreloadConfig(WS2811_TIMER, TIM_OCPreload_Enable);
TIM_CtrlPWMOutputs(timer, ENABLE);
TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE); dmaChannel = timerHardware->dmaChannel;
/* configure DMA */ /* configure DMA */
/* DMA1 Channel Config */ /* DMA1 Channel Config */
DMA_DeInit(WS2811_DMA_CHANNEL); DMA_DeInit(dmaChannel);
DMA_StructInit(&DMA_InitStructure); DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&WS2811_TIMER->CCR1; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ledStripDMABuffer; DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ledStripDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE;
@ -106,11 +119,12 @@ void ws2811LedStripHardwareInit(void)
DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(WS2811_DMA_CHANNEL, &DMA_InitStructure); DMA_Init(dmaChannel, &DMA_InitStructure);
TIM_DMACmd(WS2811_TIMER, TIM_DMA_CC1, ENABLE); TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE);
DMA_ITConfig(WS2811_DMA_CHANNEL, DMA_IT_TC, ENABLE); DMA_ITConfig(dmaChannel, DMA_IT_TC, ENABLE);
dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
const hsvColor_t hsv_white = { 0, 255, 255}; const hsvColor_t hsv_white = { 0, 255, 255};
ws2811Initialised = true; ws2811Initialised = true;
@ -123,10 +137,10 @@ void ws2811LedStripDMAEnable(void)
if (!ws2811Initialised) if (!ws2811Initialised)
return; return;
DMA_SetCurrDataCounter(WS2811_DMA_CHANNEL, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred DMA_SetCurrDataCounter(dmaChannel, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(WS2811_TIMER, 0); TIM_SetCounter(timer, 0);
TIM_Cmd(WS2811_TIMER, ENABLE); TIM_Cmd(timer, ENABLE);
DMA_Cmd(WS2811_DMA_CHANNEL, ENABLE); DMA_Cmd(dmaChannel, ENABLE);
} }
#endif #endif

View file

@ -31,85 +31,93 @@
#include "rcc.h" #include "rcc.h"
#include "timer.h" #include "timer.h"
#include "timer_stm32f4xx.h" #include "timer_stm32f4xx.h"
#include "io.h"
#if !defined(WS2811_PIN) #define WS2811_TIMER_HZ 84000000
#define WS2811_PIN PA0 #define WS2811_TIMER_PERIOD 104
#define WS2811_TIMER TIM5
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_ST2_HANDLER
#define WS2811_DMA_STREAM DMA1_Stream2
#define WS2811_DMA_CHANNEL DMA_Channel_6
#define WS2811_TIMER_CHANNEL TIM_Channel_1
#define WS2811_TIMER_GPIO_AF GPIO_AF_TIM5
#endif
static IO_t ws2811IO = IO_NONE; static IO_t ws2811IO = IO_NONE;
static uint16_t timDMASource = 0;
bool ws2811Initialised = false; bool ws2811Initialised = false;
static DMA_Stream_TypeDef *stream = NULL;
static TIM_TypeDef *timer = NULL;
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
{ {
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
ws2811LedDataTransferInProgress = 0; ws2811LedDataTransferInProgress = 0;
DMA_Cmd(descriptor->stream, DISABLE); DMA_Cmd(descriptor->stream, DISABLE);
TIM_DMACmd(WS2811_TIMER, timDMASource, DISABLE);
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF); DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
} }
} }
void ws2811LedStripHardwareInit(void) void ws2811LedStripHardwareInit(ioTag_t ioTag)
{ {
if (!ioTag) {
return;
}
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure;
DMA_InitTypeDef DMA_InitStructure; DMA_InitTypeDef DMA_InitStructure;
uint16_t prescalerValue; const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
timer = timerHardware->tim;
RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE); if (timerHardware->dmaStream == NULL) {
return;
}
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); RCC_ClockCmd(timerRCC(timer), ENABLE);
ws2811IO = IOGetByTag(ioTag);
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), WS2811_TIMER_GPIO_AF); IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction);
// Stop timer // Stop timer
TIM_Cmd(WS2811_TIMER, DISABLE); TIM_Cmd(timer, DISABLE);
/* Compute the prescaler value */ /* Compute the prescaler value */
prescalerValue = (uint16_t)(SystemCoreClock / 2 / 84000000) - 1; uint16_t prescalerValue = (uint16_t)(SystemCoreClock / timerClockDivisor(timer) / WS2811_TIMER_HZ) - 1;
/* Time base configuration */ /* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 104; // 800kHz TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz
TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue; TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel1 */ /* PWM1 Mode configuration: Channel1 */
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset; if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High; TIM_OCInitStructure.TIM_OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPolarity_High : TIM_OCNPolarity_Low;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; } else {
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High;
}
TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_Pulse = 0;
timerOCInit(WS2811_TIMER, WS2811_TIMER_CHANNEL, &TIM_OCInitStructure); timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);
timerOCPreloadConfig(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_OCPreload_Enable); timerOCPreloadConfig(timer, timerHardware->channel, TIM_OCPreload_Enable);
timDMASource = timerDmaSource(WS2811_TIMER_CHANNEL);
TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE); TIM_CtrlPWMOutputs(timer, ENABLE);
TIM_ARRPreloadConfig(WS2811_TIMER, ENABLE); TIM_ARRPreloadConfig(timer, ENABLE);
TIM_CCxCmd(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_CCx_Enable); TIM_CCxCmd(timer, timerHardware->channel, TIM_CCx_Enable);
TIM_Cmd(WS2811_TIMER, ENABLE); TIM_Cmd(timer, ENABLE);
stream = timerHardware->dmaStream;
/* configure DMA */ /* configure DMA */
DMA_Cmd(WS2811_DMA_STREAM, DISABLE); DMA_Cmd(stream, DISABLE);
DMA_DeInit(WS2811_DMA_STREAM); DMA_DeInit(stream);
DMA_StructInit(&DMA_InitStructure); DMA_StructInit(&DMA_InitStructure);
DMA_InitStructure.DMA_Channel = WS2811_DMA_CHANNEL; DMA_InitStructure.DMA_Channel = timerHardware->dmaChannel;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(WS2811_TIMER, WS2811_TIMER_CHANNEL); DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ledStripDMABuffer; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ledStripDMABuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE; DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE;
@ -124,14 +132,15 @@ void ws2811LedStripHardwareInit(void)
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(WS2811_DMA_STREAM, &DMA_InitStructure); DMA_Init(stream, &DMA_InitStructure);
TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE);
DMA_ITConfig(WS2811_DMA_STREAM, DMA_IT_TC, ENABLE); DMA_ITConfig(stream, DMA_IT_TC, ENABLE);
DMA_ClearITPendingBit(WS2811_DMA_STREAM, dmaFlag_IT_TCIF(WS2811_DMA_STREAM)); DMA_ClearITPendingBit(stream, dmaFlag_IT_TCIF(stream));
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0); dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
const hsvColor_t hsv_white = { 0, 255, 255}; const hsvColor_t hsv_white = { 0, 255, 255 };
ws2811Initialised = true; ws2811Initialised = true;
setStripColor(&hsv_white); setStripColor(&hsv_white);
ws2811UpdateStrip(); ws2811UpdateStrip();
@ -142,10 +151,10 @@ void ws2811LedStripDMAEnable(void)
if (!ws2811Initialised) if (!ws2811Initialised)
return; return;
DMA_SetCurrDataCounter(WS2811_DMA_STREAM, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred DMA_SetCurrDataCounter(stream, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
TIM_SetCounter(WS2811_TIMER, 0); TIM_SetCounter(timer, 0);
DMA_Cmd(WS2811_DMA_STREAM, ENABLE); TIM_Cmd(timer, ENABLE);
TIM_DMACmd(WS2811_TIMER, timDMASource, ENABLE); DMA_Cmd(stream, ENABLE);
} }
#endif #endif

View file

@ -208,7 +208,7 @@ void motorInit(const motorConfig_t *motorConfig, uint16_t idlePulse, uint8_t mot
break; break;
} }
const timerHardware_t *timerHardware = timerGetByTag(tag, TIM_USE_MOTOR); const timerHardware_t *timerHardware = timerGetByTag(tag, TIM_USE_ANY);
if (timerHardware == NULL) { if (timerHardware == NULL) {
/* flag failure and disable ability to arm */ /* flag failure and disable ability to arm */
@ -271,7 +271,7 @@ void servoInit(const servoConfig_t *servoConfig)
IOInit(servos[servoIndex].io, OWNER_SERVO, RESOURCE_OUTPUT, RESOURCE_INDEX(servoIndex)); IOInit(servos[servoIndex].io, OWNER_SERVO, RESOURCE_OUTPUT, RESOURCE_INDEX(servoIndex));
IOConfigGPIO(servos[servoIndex].io, IOCFG_AF_PP); IOConfigGPIO(servos[servoIndex].io, IOCFG_AF_PP);
const timerHardware_t *timer = timerGetByTag(tag, TIM_USE_SERVO); const timerHardware_t *timer = timerGetByTag(tag, TIM_USE_ANY);
if (timer == NULL) { if (timer == NULL) {
/* flag failure and disable ability to arm */ /* flag failure and disable ability to arm */

View file

@ -119,7 +119,8 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
if (configureTimer) { if (configureTimer) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
RCC_ClockCmd(timerRCC(timer), ENABLE); RCC_ClockCmd(timerRCC(timer), ENABLE);
TIM_Cmd(timer, DISABLE); TIM_Cmd(timer, DISABLE);
@ -139,6 +140,7 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)((SystemCoreClock / timerClockDivisor(timer) / hz) - 1); TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t)((SystemCoreClock / timerClockDivisor(timer) / hz) - 1);
TIM_TimeBaseStructure.TIM_Period = MOTOR_BITLENGTH; TIM_TimeBaseStructure.TIM_Period = MOTOR_BITLENGTH;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
} }
@ -154,7 +156,6 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High; TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High;
} }
TIM_OCInitStructure.TIM_Pulse = 0; TIM_OCInitStructure.TIM_Pulse = 0;
timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure); timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);

View file

@ -120,7 +120,8 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
if (configureTimer) { if (configureTimer) {
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
RCC_ClockCmd(timerRCC(timer), ENABLE); RCC_ClockCmd(timerRCC(timer), ENABLE);
TIM_Cmd(timer, DISABLE); TIM_Cmd(timer, DISABLE);
@ -140,10 +141,12 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1; TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1;
TIM_TimeBaseStructure.TIM_Period = MOTOR_BITLENGTH; TIM_TimeBaseStructure.TIM_Period = MOTOR_BITLENGTH;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure); TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
} }
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) { if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;

View file

@ -145,6 +145,7 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
motor->TimHandle.Instance = timerHardware->tim; motor->TimHandle.Instance = timerHardware->tim;
motor->TimHandle.Init.Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1;; motor->TimHandle.Init.Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1;;
motor->TimHandle.Init.Period = MOTOR_BITLENGTH; motor->TimHandle.Init.Period = MOTOR_BITLENGTH;
motor->TimHandle.Init.RepetitionCounter = 0;
motor->TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; motor->TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
motor->TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; motor->TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_PWM_Init(&motor->TimHandle) != HAL_OK) if(HAL_TIM_PWM_Init(&motor->TimHandle) != HAL_OK)

View file

@ -17,6 +17,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include "platform.h" #include "platform.h"
@ -25,6 +26,13 @@ typedef enum {
BAUDRATE_KISS = 38400 BAUDRATE_KISS = 38400
} escBaudRate_e; } escBaudRate_e;
typedef enum {
PROTOCOL_SIMONK = 0,
PROTOCOL_BLHELI = 1,
PROTOCOL_KISS = 2,
PROTOCOL_KISSALL = 3
} escProtocol_e;
#if defined(USE_ESCSERIAL) #if defined(USE_ESCSERIAL)
#include "build/build_config.h" #include "build/build_config.h"
@ -80,11 +88,19 @@ typedef struct escSerial_s {
uint8_t escSerialPortIndex; uint8_t escSerialPortIndex;
uint8_t mode; uint8_t mode;
uint8_t outputCount;
timerCCHandlerRec_t timerCb; timerCCHandlerRec_t timerCb;
timerCCHandlerRec_t edgeCb; timerCCHandlerRec_t edgeCb;
} escSerial_t; } escSerial_t;
typedef struct {
IO_t io;
uint8_t inverted;
} escOutputs_t;
escOutputs_t escOutputs[MAX_SUPPORTED_MOTORS];
extern timerHardware_t* serialTimerHardware; extern timerHardware_t* serialTimerHardware;
extern escSerial_t escSerialPorts[]; extern escSerial_t escSerialPorts[];
@ -97,14 +113,36 @@ void onSerialTimerEsc(timerCCHandlerRec_t *cbRec, captureCompare_t capture);
void onSerialRxPinChangeEsc(timerCCHandlerRec_t *cbRec, captureCompare_t capture); void onSerialRxPinChangeEsc(timerCCHandlerRec_t *cbRec, captureCompare_t capture);
void onSerialTimerBL(timerCCHandlerRec_t *cbRec, captureCompare_t capture); void onSerialTimerBL(timerCCHandlerRec_t *cbRec, captureCompare_t capture);
void onSerialRxPinChangeBL(timerCCHandlerRec_t *cbRec, captureCompare_t capture); void onSerialRxPinChangeBL(timerCCHandlerRec_t *cbRec, captureCompare_t capture);
static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity); static void escSerialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity);
void setTxSignalEsc(escSerial_t *escSerial, uint8_t state) void setTxSignalEsc(escSerial_t *escSerial, uint8_t state)
{ {
if (state) { if((escSerial->mode = PROTOCOL_KISSALL))
IOHi(escSerial->txIO); {
} else { for (volatile uint8_t i = 0; i < escSerial->outputCount; i++) {
IOLo(escSerial->txIO); uint8_t state_temp = state;
if(escOutputs[i].inverted) {
state_temp ^= ENABLE;
}
if (state_temp) {
IOHi(escOutputs[i].io);
} else {
IOLo(escOutputs[i].io);
}
}
}
else
{
if(escSerial->rxTimerHardware->output & TIMER_OUTPUT_INVERTED) {
state ^= ENABLE;
}
if (state) {
IOHi(escSerial->txIO);
} else {
IOLo(escSerial->txIO);
}
} }
} }
@ -118,7 +156,7 @@ static void escSerialGPIOConfig(ioTag_t tag, ioConfig_t cfg)
IOConfigGPIO(IOGetByTag(tag), cfg); IOConfigGPIO(IOGetByTag(tag), cfg);
} }
void serialInputPortConfigEsc(const timerHardware_t *timerHardwarePtr) void escSerialInputPortConfig(const timerHardware_t *timerHardwarePtr)
{ {
#ifdef STM32F10X #ifdef STM32F10X
escSerialGPIOConfig(timerHardwarePtr->tag, IOCFG_IPU); escSerialGPIOConfig(timerHardwarePtr->tag, IOCFG_IPU);
@ -164,12 +202,12 @@ static void serialTimerRxConfigBL(const timerHardware_t *timerHardwarePtr, uint8
uint8_t mhz = SystemCoreClock / 2000000; uint8_t mhz = SystemCoreClock / 2000000;
TIM_DeInit(timerHardwarePtr->tim); TIM_DeInit(timerHardwarePtr->tim);
timerConfigure(timerHardwarePtr, 0xFFFF, mhz); timerConfigure(timerHardwarePtr, 0xFFFF, mhz);
serialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, (options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling); escSerialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, (options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling);
timerChCCHandlerInit(&escSerialPorts[reference].edgeCb, onSerialRxPinChangeBL); timerChCCHandlerInit(&escSerialPorts[reference].edgeCb, onSerialRxPinChangeBL);
timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].edgeCb, NULL); timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].edgeCb, NULL);
} }
static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference) static void escSerialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference)
{ {
uint32_t timerPeriod=34; uint32_t timerPeriod=34;
TIM_DeInit(timerHardwarePtr->tim); TIM_DeInit(timerHardwarePtr->tim);
@ -178,7 +216,7 @@ static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t
timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].timerCb, NULL); timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].timerCb, NULL);
} }
static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity) static void escSerialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity)
{ {
TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitTypeDef TIM_ICInitStructure;
@ -192,17 +230,17 @@ static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity)
TIM_ICInit(tim, &TIM_ICInitStructure); TIM_ICInit(tim, &TIM_ICInitStructure);
} }
static void serialTimerRxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference) static void escSerialTimerRxConfig(const timerHardware_t *timerHardwarePtr, uint8_t reference)
{ {
// start bit is usually a FALLING signal // start bit is usually a FALLING signal
TIM_DeInit(timerHardwarePtr->tim); TIM_DeInit(timerHardwarePtr->tim);
timerConfigure(timerHardwarePtr, 0xFFFF, 1); timerConfigure(timerHardwarePtr, 0xFFFF, 1);
serialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Falling); escSerialICConfig(timerHardwarePtr->tim, timerHardwarePtr->channel, TIM_ICPolarity_Falling);
timerChCCHandlerInit(&escSerialPorts[reference].edgeCb, onSerialRxPinChangeEsc); timerChCCHandlerInit(&escSerialPorts[reference].edgeCb, onSerialRxPinChangeEsc);
timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].edgeCb, NULL); timerChConfigCallbacks(timerHardwarePtr, &escSerialPorts[reference].edgeCb, NULL);
} }
static void serialOutputPortConfig(const timerHardware_t *timerHardwarePtr) static void escSerialOutputPortConfig(const timerHardware_t *timerHardwarePtr)
{ {
escSerialGPIOConfig(timerHardwarePtr->tag, IOCFG_OUT_PP); escSerialGPIOConfig(timerHardwarePtr->tag, IOCFG_OUT_PP);
timerChITConfig(timerHardwarePtr,DISABLE); timerChITConfig(timerHardwarePtr,DISABLE);
@ -225,7 +263,11 @@ serialPort_t *openEscSerial(escSerialPortIndex_e portIndex, serialReceiveCallbac
{ {
escSerial_t *escSerial = &(escSerialPorts[portIndex]); escSerial_t *escSerial = &(escSerialPorts[portIndex]);
escSerial->rxTimerHardware = &(timerHardware[output]); if(mode != PROTOCOL_KISSALL){
escSerial->rxTimerHardware = &(timerHardware[output]);
}
escSerial->mode = mode;
escSerial->txTimerHardware = &(timerHardware[ESCSERIAL_TIMER_TX_HARDWARE]); escSerial->txTimerHardware = &(timerHardware[ESCSERIAL_TIMER_TX_HARDWARE]);
escSerial->port.vTable = escSerialVTable; escSerial->port.vTable = escSerialVTable;
@ -247,30 +289,56 @@ serialPort_t *openEscSerial(escSerialPortIndex_e portIndex, serialReceiveCallbac
escSerial->escSerialPortIndex = portIndex; escSerial->escSerialPortIndex = portIndex;
escSerial->txIO = IOGetByTag(escSerial->rxTimerHardware->tag); if(mode != PROTOCOL_KISSALL)
serialInputPortConfigEsc(escSerial->rxTimerHardware); {
escSerial->txIO = IOGetByTag(escSerial->rxTimerHardware->tag);
setTxSignalEsc(escSerial, ENABLE); escSerialInputPortConfig(escSerial->rxTimerHardware);
setTxSignalEsc(escSerial, ENABLE);
}
delay(50); delay(50);
if(mode==0){ if(mode==PROTOCOL_SIMONK){
serialTimerTxConfig(escSerial->txTimerHardware, portIndex); escSerialTimerTxConfig(escSerial->txTimerHardware, portIndex);
serialTimerRxConfig(escSerial->rxTimerHardware, portIndex); escSerialTimerRxConfig(escSerial->rxTimerHardware, portIndex);
} }
else if(mode==1){ else if(mode==PROTOCOL_BLHELI){
serialTimerTxConfigBL(escSerial->txTimerHardware, portIndex, baud); serialTimerTxConfigBL(escSerial->txTimerHardware, portIndex, baud);
serialTimerRxConfigBL(escSerial->rxTimerHardware, portIndex, options); serialTimerRxConfigBL(escSerial->rxTimerHardware, portIndex, options);
} }
else if(mode==2) { else if(mode==PROTOCOL_KISS) {
serialOutputPortConfig(escSerial->rxTimerHardware); // rx is the pin used escSerialOutputPortConfig(escSerial->rxTimerHardware); // rx is the pin used
serialTimerTxConfigBL(escSerial->txTimerHardware, portIndex, baud);
}
else if(mode==PROTOCOL_KISSALL) {
escSerial->outputCount = 0;
memset(&escOutputs, 0, sizeof(escOutputs));
pwmOutputPort_t *pwmMotors = pwmGetMotors();
for (volatile uint8_t i = 0; i < MAX_SUPPORTED_MOTORS; i++) {
if (pwmMotors[i].enabled) {
if (pwmMotors[i].io != IO_NONE) {
for (volatile uint8_t j = 0; j < USABLE_TIMER_CHANNEL_COUNT; j++) {
if(pwmMotors[i].io == IOGetByTag(timerHardware[j].tag))
{
escSerialOutputPortConfig(&timerHardware[j]);
if(timerHardware[j].output & TIMER_OUTPUT_INVERTED) {
escOutputs[escSerial->outputCount].inverted = 1;
}
break;
}
}
escOutputs[escSerial->outputCount].io = pwmMotors[i].io;
escSerial->outputCount++;
}
}
}
setTxSignalEsc(escSerial, ENABLE);
serialTimerTxConfigBL(escSerial->txTimerHardware, portIndex, baud); serialTimerTxConfigBL(escSerial->txTimerHardware, portIndex, baud);
} }
escSerial->mode = mode;
return &escSerial->port; return &escSerial->port;
} }
void serialInputPortDeConfig(const timerHardware_t *timerHardwarePtr) void escSerialInputPortDeConfig(const timerHardware_t *timerHardwarePtr)
{ {
timerChClearCCFlag(timerHardwarePtr); timerChClearCCFlag(timerHardwarePtr);
timerChITConfig(timerHardwarePtr,DISABLE); timerChITConfig(timerHardwarePtr,DISABLE);
@ -284,7 +352,7 @@ void closeEscSerial(escSerialPortIndex_e portIndex, uint16_t output)
escSerial->rxTimerHardware = &(timerHardware[output]); escSerial->rxTimerHardware = &(timerHardware[output]);
escSerial->txTimerHardware = &(timerHardware[ESCSERIAL_TIMER_TX_HARDWARE]); escSerial->txTimerHardware = &(timerHardware[ESCSERIAL_TIMER_TX_HARDWARE]);
serialInputPortDeConfig(escSerial->rxTimerHardware); escSerialInputPortDeConfig(escSerial->rxTimerHardware);
timerChConfigCallbacks(escSerial->txTimerHardware,NULL,NULL); timerChConfigCallbacks(escSerial->txTimerHardware,NULL,NULL);
timerChConfigCallbacks(escSerial->rxTimerHardware,NULL,NULL); timerChConfigCallbacks(escSerial->rxTimerHardware,NULL,NULL);
TIM_DeInit(escSerial->txTimerHardware->tim); TIM_DeInit(escSerial->txTimerHardware->tim);
@ -339,7 +407,7 @@ reload:
escSerial->isTransmittingData = true; escSerial->isTransmittingData = true;
//set output //set output
serialOutputPortConfig(escSerial->rxTimerHardware); escSerialOutputPortConfig(escSerial->rxTimerHardware);
return; return;
} }
@ -383,7 +451,7 @@ reload:
if (isEscSerialTransmitBufferEmpty((serialPort_t *)escSerial)) { if (isEscSerialTransmitBufferEmpty((serialPort_t *)escSerial)) {
escSerial->isTransmittingData = false; escSerial->isTransmittingData = false;
serialInputPortConfigEsc(escSerial->rxTimerHardware); escSerialInputPortConfig(escSerial->rxTimerHardware);
} }
} }
@ -417,7 +485,9 @@ void processTxStateBL(escSerial_t *escSerial)
//set output //set output
serialOutputPortConfig(escSerial->rxTimerHardware); if(escSerial->mode==PROTOCOL_BLHELI) {
escSerialOutputPortConfig(escSerial->rxTimerHardware);
}
return; return;
} }
@ -432,9 +502,9 @@ void processTxStateBL(escSerial_t *escSerial)
escSerial->isTransmittingData = false; escSerial->isTransmittingData = false;
if (isEscSerialTransmitBufferEmpty((serialPort_t *)escSerial)) { if (isEscSerialTransmitBufferEmpty((serialPort_t *)escSerial)) {
if(escSerial->mode==1) if(escSerial->mode==PROTOCOL_BLHELI)
{ {
serialInputPortConfigEsc(escSerial->rxTimerHardware); escSerialInputPortConfig(escSerial->rxTimerHardware);
} }
} }
} }
@ -463,7 +533,7 @@ void prepareForNextRxByteBL(escSerial_t *escSerial)
escSerial->isSearchingForStartBit = true; escSerial->isSearchingForStartBit = true;
if (escSerial->rxEdge == LEADING) { if (escSerial->rxEdge == LEADING) {
escSerial->rxEdge = TRAILING; escSerial->rxEdge = TRAILING;
serialICConfig( escSerialICConfig(
escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->tim,
escSerial->rxTimerHardware->channel, escSerial->rxTimerHardware->channel,
(escSerial->port.options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling (escSerial->port.options & SERIAL_INVERTED) ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling
@ -551,7 +621,7 @@ void onSerialRxPinChangeBL(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
escSerial->transmissionErrors++; escSerial->transmissionErrors++;
} }
serialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising); escSerialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising);
escSerial->rxEdge = LEADING; escSerial->rxEdge = LEADING;
escSerial->rxBitIndex = 0; escSerial->rxBitIndex = 0;
@ -569,10 +639,10 @@ void onSerialRxPinChangeBL(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
if (escSerial->rxEdge == TRAILING) { if (escSerial->rxEdge == TRAILING) {
escSerial->rxEdge = LEADING; escSerial->rxEdge = LEADING;
serialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising); escSerialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Falling : TIM_ICPolarity_Rising);
} else { } else {
escSerial->rxEdge = TRAILING; escSerial->rxEdge = TRAILING;
serialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling); escSerialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, inverted ? TIM_ICPolarity_Rising : TIM_ICPolarity_Falling);
} }
} }
/*-------------------------BL*/ /*-------------------------BL*/
@ -605,7 +675,7 @@ void onSerialTimerEsc(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
{ {
escSerial->isReceivingData=0; escSerial->isReceivingData=0;
escSerial->receiveTimeout=0; escSerial->receiveTimeout=0;
serialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, TIM_ICPolarity_Falling); escSerialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, TIM_ICPolarity_Falling);
} }
} }
@ -655,7 +725,7 @@ void onSerialRxPinChangeEsc(timerCCHandlerRec_t *cbRec, captureCompare_t capture
bits=1; bits=1;
escSerial->internalRxBuffer = 0x80; escSerial->internalRxBuffer = 0x80;
serialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, TIM_ICPolarity_Rising); escSerialICConfig(escSerial->rxTimerHardware->tim, escSerial->rxTimerHardware->channel, TIM_ICPolarity_Rising);
} }
} }
escSerial->receiveTimeout = 0; escSerial->receiveTimeout = 0;
@ -763,7 +833,7 @@ void escSerialInitialize()
for (volatile uint8_t i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) { for (volatile uint8_t i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) {
// set outputs to pullup // set outputs to pullup
if(timerHardware[i].output==1) if(timerHardware[i].output & TIMER_OUTPUT_ENABLED)
{ {
escSerialGPIOConfig(timerHardware[i].tag, IOCFG_IPU); //GPIO_Mode_IPU escSerialGPIOConfig(timerHardware[i].tag, IOCFG_IPU); //GPIO_Mode_IPU
} }
@ -844,27 +914,34 @@ static bool ProcessExitCommand(uint8_t c)
void escEnablePassthrough(serialPort_t *escPassthroughPort, uint16_t output, uint8_t mode) void escEnablePassthrough(serialPort_t *escPassthroughPort, uint16_t output, uint8_t mode)
{ {
bool exitEsc = false; bool exitEsc = false;
uint8_t motor_output = 0;
LED0_OFF; LED0_OFF;
LED1_OFF; LED1_OFF;
//StopPwmAllMotors(); //StopPwmAllMotors();
pwmDisableMotors(); pwmDisableMotors();
passPort = escPassthroughPort; passPort = escPassthroughPort;
uint8_t first_output = 0; uint32_t escBaudrate = (mode == PROTOCOL_KISS) ? BAUDRATE_KISS : BAUDRATE_NORMAL;
for (volatile uint8_t i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) {
if(timerHardware[i].output==1) if((mode == PROTOCOL_KISS) && (output == 255)){
{ motor_output = 255;
first_output=i; mode = PROTOCOL_KISSALL;
break;
}
} }
else {
uint8_t first_output = 0;
for (volatile uint8_t i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) {
if(timerHardware[i].output & TIMER_OUTPUT_ENABLED)
{
first_output=i;
break;
}
}
//doesn't work with messy timertable //doesn't work with messy timertable
uint8_t motor_output=first_output+output-1; motor_output=first_output+output-1;
if(motor_output >=USABLE_TIMER_CHANNEL_COUNT) if(motor_output >=USABLE_TIMER_CHANNEL_COUNT)
return; return;
}
uint32_t escBaudrate = (mode == 2) ? BAUDRATE_KISS : BAUDRATE_NORMAL;
escPort = openEscSerial(ESCSERIAL1, NULL, motor_output, escBaudrate, 0, mode); escPort = openEscSerial(ESCSERIAL1, NULL, motor_output, escBaudrate, 0, mode);
uint8_t ch; uint8_t ch;
@ -898,7 +975,7 @@ void escEnablePassthrough(serialPort_t *escPassthroughPort, uint16_t output, uin
closeEscSerial(ESCSERIAL1, output); closeEscSerial(ESCSERIAL1, output);
return; return;
} }
if(mode==1){ if(mode==PROTOCOL_BLHELI){
serialWrite(escPassthroughPort, ch); // blheli loopback serialWrite(escPassthroughPort, ch); // blheli loopback
} }
serialWrite(escPort, ch); serialWrite(escPort, ch);

View file

@ -759,7 +759,7 @@ const timerHardware_t *timerGetByTag(ioTag_t tag, timerUsageFlag_e flag)
{ {
for (int i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) { for (int i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) {
if (timerHardware[i].tag == tag) { if (timerHardware[i].tag == tag) {
if (timerHardware[i].usageFlags & flag) { if (timerHardware[i].usageFlags & flag || flag == 0) {
return &timerHardware[i]; return &timerHardware[i];
} }
} }
@ -810,6 +810,7 @@ volatile timCCR_t* timerCCR(TIM_TypeDef *tim, uint8_t channel)
return (volatile timCCR_t*)((volatile char*)&tim->CCR1 + channel); return (volatile timCCR_t*)((volatile char*)&tim->CCR1 + channel);
} }
#ifndef USE_HAL_DRIVER
uint16_t timerDmaSource(uint8_t channel) uint16_t timerDmaSource(uint8_t channel)
{ {
switch (channel) { switch (channel) {
@ -823,4 +824,5 @@ uint16_t timerDmaSource(uint8_t channel)
return TIM_DMA_CC4; return TIM_DMA_CC4;
} }
return 0; return 0;
} }
#endif

View file

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

View file

@ -867,3 +867,18 @@ const timerHardware_t *timerGetByTag(ioTag_t tag, timerUsageFlag_e flag)
} }
return NULL; return NULL;
} }
uint16_t timerDmaSource(uint8_t channel)
{
switch (channel) {
case TIM_CHANNEL_1:
return TIM_DMA_ID_CC1;
case TIM_CHANNEL_2:
return TIM_DMA_ID_CC2;
case TIM_CHANNEL_3:
return TIM_DMA_ID_CC3;
case TIM_CHANNEL_4:
return TIM_DMA_ID_CC4;
}
return 0;
}

View file

@ -42,6 +42,7 @@
#include "drivers/pwm_output.h" #include "drivers/pwm_output.h"
#include "drivers/max7456.h" #include "drivers/max7456.h"
#include "drivers/sound_beeper.h" #include "drivers/sound_beeper.h"
#include "drivers/light_ws2811strip.h"
#include "fc/config.h" #include "fc/config.h"
#include "fc/rc_controls.h" #include "fc/rc_controls.h"
@ -239,6 +240,26 @@ void resetSensorAlignment(sensorAlignmentConfig_t *sensorAlignmentConfig)
sensorAlignmentConfig->mag_align = ALIGN_DEFAULT; sensorAlignmentConfig->mag_align = ALIGN_DEFAULT;
} }
#ifdef LED_STRIP
void resetLedStripConfig(ledStripConfig_t *ledStripConfig)
{
applyDefaultColors(ledStripConfig->colors);
applyDefaultLedStripConfig(ledStripConfig->ledConfigs);
applyDefaultModeColors(ledStripConfig->modeColors);
applyDefaultSpecialColors(&(ledStripConfig->specialColors));
ledStripConfig->ledstrip_visual_beeper = 0;
ledStripConfig->ledstrip_aux_channel = THROTTLE;
for (int i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) {
if (timerHardware[i].usageFlags & TIM_USE_LED) {
ledStripConfig->ioTag = timerHardware[i].tag;
return;
}
}
ledStripConfig->ioTag = IO_TAG_NONE;
}
#endif
#ifdef USE_SERVOS #ifdef USE_SERVOS
void resetServoConfig(servoConfig_t *servoConfig) void resetServoConfig(servoConfig_t *servoConfig)
{ {
@ -598,6 +619,10 @@ void createDefaultConfig(master_t *config)
#endif #endif
resetFlight3DConfig(&config->flight3DConfig); resetFlight3DConfig(&config->flight3DConfig);
#ifdef LED_STRIP
resetLedStripConfig(&config->ledStripConfig);
#endif
#ifdef GPS #ifdef GPS
// gps/nav stuff // gps/nav stuff
config->gpsConfig.provider = GPS_NMEA; config->gpsConfig.provider = GPS_NMEA;
@ -667,14 +692,6 @@ void createDefaultConfig(master_t *config)
config->customMotorMixer[i].throttle = 0.0f; config->customMotorMixer[i].throttle = 0.0f;
} }
#ifdef LED_STRIP
applyDefaultColors(config->colors);
applyDefaultLedStripConfig(config->ledConfigs);
applyDefaultModeColors(config->modeColors);
applyDefaultSpecialColors(&(config->specialColors));
config->ledstrip_visual_beeper = 0;
#endif
#ifdef VTX #ifdef VTX
config->vtx_band = 4; //Fatshark/Airwaves config->vtx_band = 4; //Fatshark/Airwaves
config->vtx_channel = 1; //CH1 config->vtx_channel = 1; //CH1

View file

@ -930,7 +930,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
#ifdef LED_STRIP #ifdef LED_STRIP
case MSP_LED_COLORS: case MSP_LED_COLORS:
for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
hsvColor_t *color = &masterConfig.colors[i]; hsvColor_t *color = &masterConfig.ledStripConfig.colors[i];
sbufWriteU16(dst, color->h); sbufWriteU16(dst, color->h);
sbufWriteU8(dst, color->s); sbufWriteU8(dst, color->s);
sbufWriteU8(dst, color->v); sbufWriteU8(dst, color->v);
@ -939,7 +939,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
case MSP_LED_STRIP_CONFIG: case MSP_LED_STRIP_CONFIG:
for (i = 0; i < LED_MAX_STRIP_LENGTH; i++) { for (i = 0; i < LED_MAX_STRIP_LENGTH; i++) {
ledConfig_t *ledConfig = &masterConfig.ledConfigs[i]; ledConfig_t *ledConfig = &masterConfig.ledStripConfig.ledConfigs[i];
sbufWriteU32(dst, *ledConfig); sbufWriteU32(dst, *ledConfig);
} }
break; break;
@ -949,15 +949,20 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
for (int j = 0; j < LED_DIRECTION_COUNT; j++) { for (int j = 0; j < LED_DIRECTION_COUNT; j++) {
sbufWriteU8(dst, i); sbufWriteU8(dst, i);
sbufWriteU8(dst, j); sbufWriteU8(dst, j);
sbufWriteU8(dst, masterConfig.modeColors[i].color[j]); sbufWriteU8(dst, masterConfig.ledStripConfig.modeColors[i].color[j]);
} }
} }
for (int j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) { for (int j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) {
sbufWriteU8(dst, LED_MODE_COUNT); sbufWriteU8(dst, LED_MODE_COUNT);
sbufWriteU8(dst, j); sbufWriteU8(dst, j);
sbufWriteU8(dst, masterConfig.specialColors.color[j]); sbufWriteU8(dst, masterConfig.ledStripConfig.specialColors.color[j]);
} }
sbufWriteU8(dst, LED_AUX_CHANNEL);
sbufWriteU8(dst, 0);
sbufWriteU8(dst, masterConfig.ledStripConfig.ledstrip_aux_channel);
break; break;
#endif #endif
@ -1649,7 +1654,7 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
#ifdef LED_STRIP #ifdef LED_STRIP
case MSP_SET_LED_COLORS: case MSP_SET_LED_COLORS:
for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
hsvColor_t *color = &masterConfig.colors[i]; hsvColor_t *color = &masterConfig.ledStripConfig.colors[i];
color->h = sbufReadU16(src); color->h = sbufReadU16(src);
color->s = sbufReadU8(src); color->s = sbufReadU8(src);
color->v = sbufReadU8(src); color->v = sbufReadU8(src);
@ -1663,7 +1668,7 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
return MSP_RESULT_ERROR; return MSP_RESULT_ERROR;
break; break;
} }
ledConfig_t *ledConfig = &masterConfig.ledConfigs[i]; ledConfig_t *ledConfig = &masterConfig.ledStripConfig.ledConfigs[i];
*ledConfig = sbufReadU32(src); *ledConfig = sbufReadU32(src);
reevaluateLedConfig(); reevaluateLedConfig();
} }

View file

@ -86,6 +86,7 @@ PG_REGISTER_WITH_RESET_FN(specialColorIndexes_t, specialColors, PG_SPECIAL_COLOR
static bool ledStripInitialised = false; static bool ledStripInitialised = false;
static bool ledStripEnabled = true; static bool ledStripEnabled = true;
static ledStripConfig_t * currentLedStripConfig;
static void ledStripDisable(void); static void ledStripDisable(void);
@ -168,6 +169,7 @@ static const specialColorIndexes_t defaultSpecialColors[] = {
}; };
static int scaledThrottle; static int scaledThrottle;
static int scaledAux;
static void updateLedRingCounts(void); static void updateLedRingCounts(void);
@ -177,7 +179,7 @@ STATIC_UNIT_TESTED void determineLedStripDimensions(void)
int maxY = 0; int maxY = 0;
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
maxX = MAX(ledGetX(ledConfig), maxX); maxX = MAX(ledGetX(ledConfig), maxX);
maxY = MAX(ledGetY(ledConfig), maxY); maxY = MAX(ledGetY(ledConfig), maxY);
@ -199,7 +201,7 @@ STATIC_UNIT_TESTED void updateLedCount(void)
int count = 0, countRing = 0, countScanner= 0; int count = 0, countRing = 0, countScanner= 0;
for (int ledIndex = 0; ledIndex < LED_MAX_STRIP_LENGTH; ledIndex++) { for (int ledIndex = 0; ledIndex < LED_MAX_STRIP_LENGTH; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if (!(*ledConfig)) if (!(*ledConfig))
break; break;
@ -229,7 +231,7 @@ void reevaluateLedConfig(void)
// get specialColor by index // get specialColor by index
static hsvColor_t* getSC(ledSpecialColorIds_e index) static hsvColor_t* getSC(ledSpecialColorIds_e index)
{ {
return &masterConfig.colors[masterConfig.specialColors.color[index]]; return &currentLedStripConfig->colors[currentLedStripConfig->specialColors.color[index]];
} }
static const char directionCodes[LED_DIRECTION_COUNT] = { 'N', 'E', 'S', 'W', 'U', 'D' }; static const char directionCodes[LED_DIRECTION_COUNT] = { 'N', 'E', 'S', 'W', 'U', 'D' };
@ -251,9 +253,9 @@ bool parseLedStripConfig(int ledIndex, const char *config)
RING_COLORS, RING_COLORS,
PARSE_STATE_COUNT PARSE_STATE_COUNT
}; };
static const char chunkSeparators[PARSE_STATE_COUNT] = {',', ':', ':',':', '\0'}; static const char chunkSeparators[PARSE_STATE_COUNT] = {',', ':', ':', ':', '\0'};
ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
memset(ledConfig, 0, sizeof(ledConfig_t)); memset(ledConfig, 0, sizeof(ledConfig_t));
int x = 0, y = 0, color = 0; // initialize to prevent warnings int x = 0, y = 0, color = 0; // initialize to prevent warnings
@ -372,7 +374,7 @@ typedef enum {
static quadrant_e getLedQuadrant(const int ledIndex) static quadrant_e getLedQuadrant(const int ledIndex)
{ {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
int x = ledGetX(ledConfig); int x = ledGetX(ledConfig);
int y = ledGetY(ledConfig); int y = ledGetY(ledConfig);
@ -414,7 +416,7 @@ static const struct {
static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIndexes_t *modeColors) static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIndexes_t *modeColors)
{ {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
quadrant_e quad = getLedQuadrant(ledIndex); quadrant_e quad = getLedQuadrant(ledIndex);
for (unsigned i = 0; i < ARRAYLEN(directionQuadrantMap); i++) { for (unsigned i = 0; i < ARRAYLEN(directionQuadrantMap); i++) {
@ -422,7 +424,7 @@ static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIn
quadrant_e quadMask = directionQuadrantMap[i].quadrantMask; quadrant_e quadMask = directionQuadrantMap[i].quadrantMask;
if (ledGetDirectionBit(ledConfig, dir) && (quad & quadMask)) if (ledGetDirectionBit(ledConfig, dir) && (quad & quadMask))
return &masterConfig.colors[modeColors->color[dir]]; return &currentLedStripConfig->colors[modeColors->color[dir]];
} }
return NULL; return NULL;
} }
@ -448,7 +450,7 @@ static const struct {
static void applyLedFixedLayers() static void applyLedFixedLayers()
{ {
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND); hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND);
int fn = ledGetFunction(ledConfig); int fn = ledGetFunction(ledConfig);
@ -456,13 +458,13 @@ static void applyLedFixedLayers()
switch (fn) { switch (fn) {
case LED_FUNCTION_COLOR: case LED_FUNCTION_COLOR:
color = masterConfig.colors[ledGetColor(ledConfig)]; color = currentLedStripConfig->colors[ledGetColor(ledConfig)];
break; break;
case LED_FUNCTION_FLIGHT_MODE: case LED_FUNCTION_FLIGHT_MODE:
for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++) for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++)
if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) { if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) {
hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &masterConfig.modeColors[flightModeToLed[i].ledMode]); hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &currentLedStripConfig->modeColors[flightModeToLed[i].ledMode]);
if (directionalColor) { if (directionalColor) {
color = *directionalColor; color = *directionalColor;
} }
@ -490,7 +492,7 @@ static void applyLedFixedLayers()
} }
if (ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) { if (ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) {
hOffset += ((scaledThrottle - 10) * 4) / 3; hOffset += scaledAux;
} }
color.h = (color.h + hOffset) % (HSV_HUE_MAX + 1); color.h = (color.h + hOffset) % (HSV_HUE_MAX + 1);
@ -503,7 +505,7 @@ static void applyLedFixedLayers()
static void applyLedHsv(uint32_t mask, const hsvColor_t *color) static void applyLedHsv(uint32_t mask, const hsvColor_t *color)
{ {
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if ((*ledConfig & mask) == mask) if ((*ledConfig & mask) == mask)
setLedHsv(ledIndex, color); setLedHsv(ledIndex, color);
} }
@ -699,7 +701,7 @@ static void applyLedIndicatorLayer(bool updateNow, uint32_t *timer)
} }
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if (ledGetOverlayBit(ledConfig, LED_OVERLAY_INDICATOR)) { if (ledGetOverlayBit(ledConfig, LED_OVERLAY_INDICATOR)) {
if (getLedQuadrant(ledIndex) & quadrants) if (getLedQuadrant(ledIndex) & quadrants)
setLedHsv(ledIndex, flashColor); setLedHsv(ledIndex, flashColor);
@ -740,7 +742,7 @@ static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer)
} }
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if (ledGetFunction(ledConfig) == LED_FUNCTION_THRUST_RING) { if (ledGetFunction(ledConfig) == LED_FUNCTION_THRUST_RING) {
bool applyColor; bool applyColor;
@ -751,7 +753,7 @@ static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer)
} }
if (applyColor) { if (applyColor) {
const hsvColor_t *ringColor = &masterConfig.colors[ledGetColor(ledConfig)]; const hsvColor_t *ringColor = &currentLedStripConfig->colors[ledGetColor(ledConfig)];
setLedHsv(ledIndex, ringColor); setLedHsv(ledIndex, ringColor);
} }
@ -867,7 +869,7 @@ static void applyLedAnimationLayer(bool updateNow, uint32_t *timer)
int nextRow = (frameCounter + 1 < animationFrames) ? frameCounter + 1 : 0; int nextRow = (frameCounter + 1 < animationFrames) ? frameCounter + 1 : 0;
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) { for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex]; const ledConfig_t *ledConfig = &currentLedStripConfig->ledConfigs[ledIndex];
if (ledGetY(ledConfig) == previousRow) { if (ledGetY(ledConfig) == previousRow) {
setLedHsv(ledIndex, getSC(LED_SCOLOR_ANIMATION)); setLedHsv(ledIndex, getSC(LED_SCOLOR_ANIMATION));
@ -929,7 +931,7 @@ void ledStripUpdate(uint32_t currentTime)
return; return;
} }
if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(masterConfig.ledstrip_visual_beeper && isBeeperOn())) { if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(currentLedStripConfig->ledstrip_visual_beeper && isBeeperOn())) {
if (ledStripEnabled) { if (ledStripEnabled) {
ledStripDisable(); ledStripDisable();
ledStripEnabled = false; ledStripEnabled = false;
@ -960,6 +962,7 @@ void ledStripUpdate(uint32_t currentTime)
// apply all layers; triggered timed functions has to update timers // apply all layers; triggered timed functions has to update timers
scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 10, 100) : 10; scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 10, 100) : 10;
scaledAux = scaleRange(rcData[currentLedStripConfig->ledstrip_aux_channel], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, HSV_HUE_MAX + 1);
applyLedFixedLayers(); applyLedFixedLayers();
@ -975,7 +978,7 @@ bool parseColor(int index, const char *colorConfig)
{ {
const char *remainingCharacters = colorConfig; const char *remainingCharacters = colorConfig;
hsvColor_t *color = &masterConfig.colors[index]; hsvColor_t *color = &currentLedStripConfig->colors[index];
bool result = true; bool result = true;
static const uint16_t hsv_limit[HSV_COLOR_COMPONENT_COUNT] = { static const uint16_t hsv_limit[HSV_COLOR_COMPONENT_COUNT] = {
@ -1028,11 +1031,15 @@ bool setModeColor(ledModeIndex_e modeIndex, int modeColorIndex, int colorIndex)
if (modeIndex < LED_MODE_COUNT) { // modeIndex_e is unsigned, so one-sided test is enough if (modeIndex < LED_MODE_COUNT) { // modeIndex_e is unsigned, so one-sided test is enough
if(modeColorIndex < 0 || modeColorIndex >= LED_DIRECTION_COUNT) if(modeColorIndex < 0 || modeColorIndex >= LED_DIRECTION_COUNT)
return false; return false;
masterConfig.modeColors[modeIndex].color[modeColorIndex] = colorIndex; currentLedStripConfig->modeColors[modeIndex].color[modeColorIndex] = colorIndex;
} else if (modeIndex == LED_SPECIAL) { } else if (modeIndex == LED_SPECIAL) {
if (modeColorIndex < 0 || modeColorIndex >= LED_SPECIAL_COLOR_COUNT) if (modeColorIndex < 0 || modeColorIndex >= LED_SPECIAL_COLOR_COUNT)
return false; return false;
masterConfig.specialColors.color[modeColorIndex] = colorIndex; currentLedStripConfig->specialColors.color[modeColorIndex] = colorIndex;
} else if (modeIndex == LED_AUX_CHANNEL) {
if (modeColorIndex < 0 || modeColorIndex >= 1)
return false;
currentLedStripConfig->ledstrip_aux_channel = colorIndex;
} else { } else {
return false; return false;
} }
@ -1090,21 +1097,26 @@ void applyDefaultSpecialColors(specialColorIndexes_t *specialColors)
memcpy_fn(specialColors, &defaultSpecialColors, sizeof(defaultSpecialColors)); memcpy_fn(specialColors, &defaultSpecialColors, sizeof(defaultSpecialColors));
} }
void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, modeColorIndexes_t *modeColorsToUse, specialColorIndexes_t *specialColorsToUse) void ledStripInit(ledStripConfig_t *ledStripConfig)
{ {
ledConfigs = ledConfigsToUse; currentLedStripConfig = ledStripConfig;
colors = colorsToUse;
modeColors = modeColorsToUse; ledConfigs = currentLedStripConfig->ledConfigs;
specialColors = *specialColorsToUse; colors = currentLedStripConfig->colors;
modeColors = currentLedStripConfig->modeColors;
specialColors = currentLedStripConfig->specialColors;
ledStripInitialised = false; ledStripInitialised = false;
} }
void ledStripEnable(void) void ledStripEnable(void)
{ {
if (currentLedStripConfig == NULL) {
return;
}
reevaluateLedConfig(); reevaluateLedConfig();
ledStripInitialised = true; ledStripInitialised = true;
ws2811LedStripInit(); ws2811LedStripInit(currentLedStripConfig->ioTag);
} }
static void ledStripDisable(void) static void ledStripDisable(void)

View file

@ -18,6 +18,7 @@
#pragma once #pragma once
#include "common/color.h" #include "common/color.h"
#include "drivers/io_types.h"
#define LED_MAX_STRIP_LENGTH 32 #define LED_MAX_STRIP_LENGTH 32
#define LED_CONFIGURABLE_COLOR_COUNT 16 #define LED_CONFIGURABLE_COLOR_COUNT 16
@ -75,7 +76,8 @@ typedef enum {
LED_MODE_ANGLE, LED_MODE_ANGLE,
LED_MODE_MAG, LED_MODE_MAG,
LED_MODE_BARO, LED_MODE_BARO,
LED_SPECIAL LED_SPECIAL,
LED_AUX_CHANNEL
} ledModeIndex_e; } ledModeIndex_e;
typedef enum { typedef enum {
@ -134,6 +136,15 @@ typedef struct ledCounts_s {
uint8_t ringSeqLen; uint8_t ringSeqLen;
} ledCounts_t; } ledCounts_t;
typedef struct ledStripConfig_s {
ledConfig_t ledConfigs[LED_MAX_STRIP_LENGTH];
hsvColor_t colors[LED_CONFIGURABLE_COLOR_COUNT];
modeColorIndexes_t modeColors[LED_MODE_COUNT];
specialColorIndexes_t specialColors;
uint8_t ledstrip_visual_beeper; // suppress LEDLOW mode if beeper is on
rc_alias_e ledstrip_aux_channel;
ioTag_t ioTag;
} ledStripConfig_t;
ledConfig_t *ledConfigs; ledConfig_t *ledConfigs;
hsvColor_t *colors; hsvColor_t *colors;
@ -165,7 +176,7 @@ bool parseLedStripConfig(int ledIndex, const char *config);
void generateLedConfig(ledConfig_t *ledConfig, char *ledConfigBuffer, size_t bufferSize); void generateLedConfig(ledConfig_t *ledConfig, char *ledConfigBuffer, size_t bufferSize);
void reevaluateLedConfig(void); void reevaluateLedConfig(void);
void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, modeColorIndexes_t *modeColorsToUse, specialColorIndexes_t *specialColorsToUse); void ledStripInit(ledStripConfig_t *ledStripConfig);
void ledStripEnable(void); void ledStripEnable(void);
void ledStripUpdate(uint32_t currentTime); void ledStripUpdate(uint32_t currentTime);

View file

@ -936,7 +936,7 @@ const clivalue_t valueTable[] = {
{ "magzero_z", VAR_INT16 | MASTER_VALUE, &masterConfig.magZero.raw[Z], .config.minmax = { -32768, 32767 } }, { "magzero_z", VAR_INT16 | MASTER_VALUE, &masterConfig.magZero.raw[Z], .config.minmax = { -32768, 32767 } },
#endif #endif
#ifdef LED_STRIP #ifdef LED_STRIP
{ "ledstrip_visual_beeper", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.ledstrip_visual_beeper, .config.lookup = { TABLE_OFF_ON } }, { "ledstrip_visual_beeper", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.ledStripConfig.ledstrip_visual_beeper, .config.lookup = { TABLE_OFF_ON } },
#endif #endif
#ifdef USE_RTC6705 #ifdef USE_RTC6705
{ "vtx_channel", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_channel, .config.minmax = { 0, 39 } }, { "vtx_channel", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_channel, .config.minmax = { 0, 39 } },
@ -1707,8 +1707,8 @@ static void printLed(uint8_t dumpMask, master_t *defaultConfig)
char ledConfigBuffer[20]; char ledConfigBuffer[20];
char ledConfigDefaultBuffer[20]; char ledConfigDefaultBuffer[20];
for (uint32_t i = 0; i < LED_MAX_STRIP_LENGTH; i++) { for (uint32_t i = 0; i < LED_MAX_STRIP_LENGTH; i++) {
ledConfig = masterConfig.ledConfigs[i]; ledConfig = masterConfig.ledStripConfig.ledConfigs[i];
ledConfigDefault = defaultConfig->ledConfigs[i]; ledConfigDefault = defaultConfig->ledStripConfig.ledConfigs[i];
equalsDefault = ledConfig == ledConfigDefault; equalsDefault = ledConfig == ledConfigDefault;
generateLedConfig(&ledConfig, ledConfigBuffer, sizeof(ledConfigBuffer)); generateLedConfig(&ledConfig, ledConfigBuffer, sizeof(ledConfigBuffer));
generateLedConfig(&ledConfigDefault, ledConfigDefaultBuffer, sizeof(ledConfigDefaultBuffer)); generateLedConfig(&ledConfigDefault, ledConfigDefaultBuffer, sizeof(ledConfigDefaultBuffer));
@ -1745,8 +1745,8 @@ static void printColor(uint8_t dumpMask, master_t *defaultConfig)
hsvColor_t *colorDefault; hsvColor_t *colorDefault;
bool equalsDefault; bool equalsDefault;
for (uint32_t i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) { for (uint32_t i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
color = &masterConfig.colors[i]; color = &masterConfig.ledStripConfig.colors[i];
colorDefault = &defaultConfig->colors[i]; colorDefault = &defaultConfig->ledStripConfig.colors[i];
equalsDefault = color->h == colorDefault->h equalsDefault = color->h == colorDefault->h
&& color->s == colorDefault->s && color->s == colorDefault->s
&& color->v == colorDefault->v; && color->v == colorDefault->v;
@ -1791,21 +1791,26 @@ static void printModeColor(uint8_t dumpMask, master_t *defaultConfig)
{ {
for (uint32_t i = 0; i < LED_MODE_COUNT; i++) { for (uint32_t i = 0; i < LED_MODE_COUNT; i++) {
for (uint32_t j = 0; j < LED_DIRECTION_COUNT; j++) { for (uint32_t j = 0; j < LED_DIRECTION_COUNT; j++) {
int colorIndex = masterConfig.modeColors[i].color[j]; int colorIndex = masterConfig.ledStripConfig.modeColors[i].color[j];
int colorIndexDefault = defaultConfig->modeColors[i].color[j]; int colorIndexDefault = defaultConfig->ledStripConfig.modeColors[i].color[j];
const char *format = "mode_color %u %u %u\r\n"; const char *format = "mode_color %u %u %u\r\n";
cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndexDefault); cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndexDefault);
cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndex); cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndex);
} }
} }
const char *format = "mode_color %u %u %u\r\n";
for (uint32_t j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) { for (uint32_t j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) {
int colorIndex = masterConfig.specialColors.color[j]; int colorIndex = masterConfig.ledStripConfig.specialColors.color[j];
int colorIndexDefault = defaultConfig->specialColors.color[j]; int colorIndexDefault = defaultConfig->ledStripConfig.specialColors.color[j];
const char *format = "mode_color %u %u %u\r\n";
cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndexDefault); cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndexDefault);
cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndex); cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndex);
} }
int ledStripAuxChannel = masterConfig.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);
} }
static void cliModeColor(char *cmdline) static void cliModeColor(char *cmdline)
@ -2997,12 +3002,18 @@ static void cliEscPassthrough(char *cmdline)
break; break;
case 1: case 1:
index = atoi(pch); index = atoi(pch);
if ((index >= 0) && (index < USABLE_TIMER_CHANNEL_COUNT)) { if(mode == 2 && index == 255)
printf("passthru at pwm output %d enabled\r\n", index); {
printf("passthru on all pwm outputs enabled\r\n");
} }
else { else{
printf("invalid pwm output, valid range: 1 to %d\r\n", USABLE_TIMER_CHANNEL_COUNT); if ((index >= 0) && (index < USABLE_TIMER_CHANNEL_COUNT)) {
return; printf("passthru at pwm output %d enabled\r\n", index);
}
else {
printf("invalid pwm output, valid range: 1 to %d\r\n", USABLE_TIMER_CHANNEL_COUNT);
return;
}
} }
break; break;
} }
@ -3610,7 +3621,8 @@ static void cliVersion(char *cmdline)
{ {
UNUSED(cmdline); UNUSED(cmdline);
cliPrintf("# BetaFlight/%s %s %s / %s (%s)\r\n", cliPrintf("# %s/%s %s %s / %s (%s)\r\n",
FC_FIRMWARE_NAME,
targetName, targetName,
FC_VERSION_STRING, FC_VERSION_STRING,
buildDate, buildDate,
@ -3739,19 +3751,22 @@ typedef struct {
const cliResourceValue_t resourceTable[] = { const cliResourceValue_t resourceTable[] = {
#ifdef BEEPER #ifdef BEEPER
{ OWNER_BEEPER, &masterConfig.beeperConfig.ioTag, 0 }, { OWNER_BEEPER, &masterConfig.beeperConfig.ioTag, 0 },
#endif #endif
{ OWNER_MOTOR, &masterConfig.motorConfig.ioTags[0], MAX_SUPPORTED_MOTORS }, { OWNER_MOTOR, &masterConfig.motorConfig.ioTags[0], MAX_SUPPORTED_MOTORS },
#ifdef USE_SERVOS #ifdef USE_SERVOS
{ OWNER_SERVO, &masterConfig.servoConfig.ioTags[0], MAX_SUPPORTED_SERVOS }, { OWNER_SERVO, &masterConfig.servoConfig.ioTags[0], MAX_SUPPORTED_SERVOS },
#endif #endif
#ifndef SKIP_RX_PWM_PPM #ifndef SKIP_RX_PWM_PPM
{ OWNER_PPMINPUT, &masterConfig.ppmConfig.ioTag, 0 }, { OWNER_PPMINPUT, &masterConfig.ppmConfig.ioTag, 0 },
{ OWNER_PWMINPUT, &masterConfig.pwmConfig.ioTags[0], PWM_INPUT_PORT_COUNT }, { OWNER_PWMINPUT, &masterConfig.pwmConfig.ioTags[0], PWM_INPUT_PORT_COUNT },
#endif #endif
#ifdef SONAR #ifdef SONAR
{ OWNER_SONAR_TRIGGER, &masterConfig.sonarConfig.triggerTag, 0 }, { OWNER_SONAR_TRIGGER, &masterConfig.sonarConfig.triggerTag, 0 },
{ OWNER_SONAR_ECHO, &masterConfig.sonarConfig.echoTag, 0 }, { OWNER_SONAR_ECHO, &masterConfig.sonarConfig.echoTag, 0 },
#endif
#ifdef LED_STRIP
{ OWNER_LED_STRIP, &masterConfig.ledStripConfig.ioTag, 0 },
#endif #endif
}; };

View file

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

View file

@ -59,7 +59,7 @@
#define MSP_PROTOCOL_VERSION 0 #define MSP_PROTOCOL_VERSION 0
#define API_VERSION_MAJOR 1 // increment when major changes are made #define API_VERSION_MAJOR 1 // increment when major changes are made
#define API_VERSION_MINOR 21 // increment when any change is made, reset to zero when major changes are released after changing API_VERSION_MAJOR #define API_VERSION_MINOR 22 // increment when any change is made, reset to zero when major changes are released after changing API_VERSION_MAJOR
#define API_VERSION_LENGTH 2 #define API_VERSION_LENGTH 2

View file

@ -24,10 +24,10 @@
#include "drivers/timer.h" #include "drivers/timer.h"
const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = {
{ TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_INVERTED, GPIO_AF_6, DMA1_Channel2, DMA1_CH2_HANDLER },
{ TIM8, IO_TAG(PB0), TIM_Channel_2, TIM8_CC_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_N_CHANNEL | TIMER_OUTPUT_INVERTED, GPIO_AF_4, DMA2_Channel5, DMA2_CH5_HANDLER },
{ TIM1, IO_TAG(PB14), TIM_Channel_2, TIM1_CC_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_N_CHANNEL | TIMER_OUTPUT_INVERTED, GPIO_AF_6, DMA1_Channel3, DMA1_CH3_HANDLER }, { TIM1, IO_TAG(PB14), TIM_Channel_2, TIM1_CC_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_N_CHANNEL | TIMER_OUTPUT_INVERTED, GPIO_AF_6, DMA1_Channel3, DMA1_CH3_HANDLER },
{ TIM8, IO_TAG(PB0), TIM_Channel_2, TIM8_CC_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_N_CHANNEL | TIMER_OUTPUT_INVERTED, GPIO_AF_4, DMA2_Channel5, DMA2_CH5_HANDLER },
{ TIM15, IO_TAG(PB15), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_N_CHANNEL | TIMER_OUTPUT_INVERTED, GPIO_AF_2, DMA1_Channel5, DMA1_CH5_HANDLER }, { TIM15, IO_TAG(PB15), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_N_CHANNEL | TIMER_OUTPUT_INVERTED, GPIO_AF_2, DMA1_Channel5, DMA1_CH5_HANDLER },
{ TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_INVERTED, GPIO_AF_6, DMA1_Channel2, DMA1_CH2_HANDLER },
{ TIM3, IO_TAG(PA6), TIM_Channel_1, TIM3_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_INVERTED, GPIO_AF_2, DMA1_Channel6, DMA1_CH6_HANDLER }, { TIM3, IO_TAG(PA6), TIM_Channel_1, TIM3_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_INVERTED, GPIO_AF_2, DMA1_Channel6, DMA1_CH6_HANDLER },
{ TIM17, IO_TAG(PA7), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_INVERTED, GPIO_AF_1, DMA1_Channel7, DMA1_CH7_HANDLER }, { TIM17, IO_TAG(PA7), TIM_Channel_1, TIM1_TRG_COM_TIM17_IRQn, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED | TIMER_OUTPUT_INVERTED, GPIO_AF_1, DMA1_Channel7, DMA1_CH7_HANDLER },

View file

@ -0,0 +1 @@
# LUXR_RACE is new version

View file

@ -21,18 +21,21 @@
#include "drivers/io.h" #include "drivers/io.h"
#include "drivers/timer.h" #include "drivers/timer.h"
#include "drivers/dma.h"
const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = {
{ TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, TIM_USE_PPM, 0, GPIO_AF_6 }, // PWM1 - PA8 { TIM1, IO_TAG(PA8), TIM_Channel_1, TIM1_CC_IRQn, TIM_USE_PPM, 0, GPIO_AF_6, NULL, 0 }, // PWM1 - PA8
{ TIM3, IO_TAG(PC6), TIM_Channel_1, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2 }, // PWM2 - PC6 { TIM3, IO_TAG(PC6), TIM_Channel_1, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2, DMA1_Channel6, DMA1_CH6_HANDLER }, // PWM2 - PC6
{ TIM3, IO_TAG(PC7), TIM_Channel_2, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2 }, // PWM3 - PC7 { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_4, DMA2_Channel5, DMA2_CH5_HANDLER }, // PWM3 - PC7
{ TIM3, IO_TAG(PC8), TIM_Channel_3, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2 }, // PMW4 - PC8 { TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_4, DMA2_Channel1, DMA2_CH1_HANDLER }, // PMW4 - PC8
{ TIM3, IO_TAG(PC9), TIM_Channel_4, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2 }, // PWM5 - PC9 { TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_4, DMA2_Channel2, DMA2_CH2_HANDLER }, // PWM5 - PC9
{ TIM2, IO_TAG(PA0), TIM_Channel_1, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM6 - PA0 #ifndef LUXV2_RACE
{ TIM2, IO_TAG(PA1), TIM_Channel_2, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM7 - PA1 { TIM2, IO_TAG(PA0), TIM_Channel_1, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM6 - PA0
{ TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM8 - PA2 { TIM2, IO_TAG(PA1), TIM_Channel_2, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM7 - PA1
{ TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM9 - PA3 { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM8 - PA2
{ TIM15, IO_TAG(PB14), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM10 - PB14 { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM9 - PA3
{ TIM15, IO_TAG(PB15), TIM_Channel_2, TIM1_BRK_TIM15_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM11 - PB15 { TIM15, IO_TAG(PB14), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM10 - PB14
{ TIM15, IO_TAG(PB15), TIM_Channel_2, TIM1_BRK_TIM15_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM11 - PB15
#endif
}; };

View file

@ -17,16 +17,26 @@
#pragma once #pragma once
#ifdef LUXV2_RACE
#define TARGET_BOARD_IDENTIFIER "LUXR"
#else
#define TARGET_BOARD_IDENTIFIER "LUX" #define TARGET_BOARD_IDENTIFIER "LUX"
#endif
#define BOARD_HAS_VOLTAGE_DIVIDER #define BOARD_HAS_VOLTAGE_DIVIDER
#define CONFIG_FASTLOOP_PREFERRED_ACC ACC_DEFAULT #define CONFIG_FASTLOOP_PREFERRED_ACC ACC_DEFAULT
#define LED0 PC15 #define LED0 PC15
#define LED1 PC14 #define LED1 PC14
#ifndef LUXV2_RACE
#define LED2 PC13 #define LED2 PC13
#endif
#ifdef LUXV2_RACE
#define BEEPER PB9
#else
#define BEEPER PB13 #define BEEPER PB13
#endif
#define BEEPER_INVERTED #define BEEPER_INVERTED
// MPU6500 interrupt // MPU6500 interrupt
@ -36,26 +46,72 @@
#define USE_MPU_DATA_READY_SIGNAL #define USE_MPU_DATA_READY_SIGNAL
#define ENSURE_MPU_DATA_READY_IS_LOW #define ENSURE_MPU_DATA_READY_IS_LOW
#define USE_DSHOT
#define USE_SPI #define USE_SPI
#define USE_SPI_DEVICE_1 #define USE_SPI_DEVICE_1
#ifdef LUXV2_RACE
#define USE_SPI_DEVICE_2
#endif
#define SPI1_SCK_PIN PB3 #define SPI1_SCK_PIN PB3
#define SPI1_MISO_PIN PB4 #define SPI1_MISO_PIN PB4
#define SPI1_MOSI_PIN PB5 #define SPI1_MOSI_PIN PB5
//#ifndef LUXV2_RACE
#define SPI1_NSS_PIN PA4 #define SPI1_NSS_PIN PA4
//#endif
#ifdef LUXV2_RACE
#define SPI2_NSS_PIN PB12
#define SPI2_SCK_PIN PB13
#define SPI2_MISO_PIN PB14
#define SPI2_MOSI_PIN PB15
#define USE_SDCARD
#define USE_SDCARD_SPI2
#define SDCARD_DETECT_INVERTED
#define SDCARD_DETECT_PIN PC13
#define SDCARD_SPI_INSTANCE SPI2
#define SDCARD_SPI_CS_PIN SPI2_NSS_PIN
// SPI2 is on the APB1 bus whose clock runs at 36MHz. Divide to under 400kHz for init:
#define SDCARD_SPI_INITIALIZATION_CLOCK_DIVIDER 128
// Divide to under 25MHz for normal operation:
#define SDCARD_SPI_FULL_SPEED_CLOCK_DIVIDER 2
// Note, this is the same DMA channel as UART1_RX. Luckily we don't use DMA for USART Rx.
#define SDCARD_DMA_CHANNEL_TX DMA1_Channel5
#define SDCARD_DMA_CHANNEL_TX_COMPLETE_FLAG DMA1_FLAG_TC5
#endif
#define MPU6000_CS_PIN SPI1_NSS_PIN
#define MPU6000_SPI_INSTANCE SPI1
#define MPU6500_CS_PIN SPI1_NSS_PIN #define MPU6500_CS_PIN SPI1_NSS_PIN
#define MPU6500_SPI_INSTANCE SPI1 #define MPU6500_SPI_INSTANCE SPI1
#define GYRO #define GYRO
#ifdef LUXV2_RACE
#define USE_GYRO_MPU6000
#define USE_GYRO_SPI_MPU6000
#define GYRO_MPU6000_ALIGN CW270_DEG
#else
#define USE_GYRO_MPU6500 #define USE_GYRO_MPU6500
#define USE_GYRO_SPI_MPU6500 #define USE_GYRO_SPI_MPU6500
#define GYRO_MPU6500_ALIGN CW270_DEG #define GYRO_MPU6500_ALIGN CW270_DEG
#endif
#define ACC #define ACC
#ifdef LUXV2_RACE
#define USE_ACC_MPU6000
#define USE_ACC_SPI_MPU6000
#define ACC_MPU6000_ALIGN CW270_DEG
#else
#define USE_ACC_MPU6500 #define USE_ACC_MPU6500
#define USE_ACC_SPI_MPU6500 #define USE_ACC_SPI_MPU6500
#define ACC_MPU6500_ALIGN CW270_DEG #define ACC_MPU6500_ALIGN CW270_DEG
#endif
#define USB_IO #define USB_IO
@ -63,7 +119,13 @@
#define USE_UART1 #define USE_UART1
#define USE_UART2 #define USE_UART2
#define USE_UART3 #define USE_UART3
#ifdef LUXV2_RACE
#define USE_UART4
#define USE_UART5
#define SERIAL_PORT_COUNT 6
#else
#define SERIAL_PORT_COUNT 4 #define SERIAL_PORT_COUNT 4
#endif
#define UART1_TX_PIN PC4 #define UART1_TX_PIN PC4
#define UART1_RX_PIN PC5 #define UART1_RX_PIN PC5
@ -74,8 +136,7 @@
#define UART3_TX_PIN PB10 #define UART3_TX_PIN PB10
#define UART3_RX_PIN PB11 #define UART3_RX_PIN PB11
#define USE_I2C #undef USE_I2C
#define I2C_DEVICE (I2CDEV_2)
#define USE_ADC #define USE_ADC
#define ADC_INSTANCE ADC1 #define ADC_INSTANCE ADC1
@ -95,6 +156,11 @@
#define DEFAULT_RX_FEATURE FEATURE_RX_PPM #define DEFAULT_RX_FEATURE FEATURE_RX_PPM
#ifdef LUXV2_RACE
#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT
#define DEFAULT_FEATURES FEATURE_BLACKBOX
#endif
#define SPEKTRUM_BIND #define SPEKTRUM_BIND
// USART1, PC5 // USART1, PC5
#define BIND_PIN PC5 #define BIND_PIN PC5
@ -108,6 +174,10 @@
#define TARGET_IO_PORTD (BIT(2)) #define TARGET_IO_PORTD (BIT(2))
#define TARGET_IO_PORTF (BIT(0)|BIT(1)|BIT(4)) #define TARGET_IO_PORTF (BIT(0)|BIT(1)|BIT(4))
#ifdef LUXV2_RACE
#define USABLE_TIMER_CHANNEL_COUNT 5
#else
#define USABLE_TIMER_CHANNEL_COUNT 11 #define USABLE_TIMER_CHANNEL_COUNT 11
#define USED_TIMERS (TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(15)) #endif
#define USED_TIMERS (TIM_N(1) | TIM_N(2) | TIM_N(3) | TIM_N(8) | TIM_N(15))

View file

@ -1,9 +1,9 @@
F3_TARGETS += $(TARGET) F3_TARGETS += $(TARGET)
FEATURES = VCP FEATURES = VCP SDCARD
TARGET_SRC = \ TARGET_SRC = \
drivers/accgyro_mpu.c \ drivers/accgyro_mpu.c \
drivers/accgyro_mpu6500.c \ drivers/accgyro_mpu6500.c \
drivers/accgyro_spi_mpu6500.c \ drivers/accgyro_spi_mpu6500.c \
drivers/accgyro_mpu6500.c drivers/accgyro_mpu6500.c \
drivers/accgyro_spi_mpu6000.c

View file

View file

View file

@ -30,10 +30,14 @@ const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = {
{ TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, TIM_USE_PWM, 0, GPIO_AF_TIM8, NULL, 0, 0 }, // S4_IN { TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, TIM_USE_PWM, 0, GPIO_AF_TIM8, NULL, 0, 0 }, // S4_IN
{ TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, TIM_USE_PWM, 0, GPIO_AF_TIM8, NULL, 0, 0 }, // S5_IN { TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, TIM_USE_PWM, 0, GPIO_AF_TIM8, NULL, 0, 0 }, // S5_IN
{ TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, TIM_USE_PWM, 0, GPIO_AF_TIM8, NULL, 0, 0 }, // S6_IN { TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, TIM_USE_PWM, 0, GPIO_AF_TIM8, NULL, 0, 0 }, // S6_IN
{ TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, TIM_USE_PWM, 1, GPIO_AF_TIM3, DMA1_Stream7, DMA_Channel_5, DMA1_ST7_HANDLER }, // S1_OUT { TIM3, IO_TAG(PB0), TIM_Channel_3, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM3, DMA1_Stream7, DMA_Channel_5, DMA1_ST7_HANDLER }, // S1_OUT
{ TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM3, DMA1_Stream2, DMA_Channel_5, DMA1_ST2_HANDLER }, // S2_OUT { TIM3, IO_TAG(PB1), TIM_Channel_4, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM3, DMA1_Stream2, DMA_Channel_5, DMA1_ST2_HANDLER }, // S2_OUT
{ TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM2, DMA1_Stream6, DMA_Channel_3, DMA1_ST6_HANDLER }, // S3_OUT { TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM2, DMA1_Stream6, DMA_Channel_3, DMA1_ST6_HANDLER }, // S3_OUT
{ TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM2, DMA1_Stream1, DMA_Channel_3, DMA1_ST1_HANDLER }, // S4_OUT { TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM2, DMA1_Stream1, DMA_Channel_3, DMA1_ST1_HANDLER }, // S4_OUT
{ TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, TIM_USE_MOTOR | TIM_USE_LED, 1, GPIO_AF_TIM5, DMA1_Stream4, DMA_Channel_6, DMA1_ST4_HANDLER }, // S5_OUT #ifdef REVOLT
{ TIM4, IO_TAG(PB6), TIM_Channel_1, TIM4_IRQn, TIM_USE_LED, 0, GPIO_AF_TIM4, DMA1_Stream0, DMA_Channel_2, DMA1_ST0_HANDLER }, // LED for REVOLT
#else
{ TIM5, IO_TAG(PA1), TIM_Channel_2, TIM5_IRQn, TIM_USE_MOTOR | TIM_USE_LED, 1, GPIO_AF_TIM5, DMA1_Stream4, DMA_Channel_6, DMA1_ST4_HANDLER }, // S5_OUT / LED for REVO
{ TIM5, IO_TAG(PA0), TIM_Channel_1, TIM5_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM5, DMA1_Stream2, DMA_Channel_6, DMA1_ST2_HANDLER }, // S6_OUT { TIM5, IO_TAG(PA0), TIM_Channel_1, TIM5_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_TIM5, DMA1_Stream2, DMA_Channel_6, DMA1_ST2_HANDLER }, // S6_OUT
#endif
}; };

View file

@ -17,43 +17,71 @@
#pragma once #pragma once
#define TARGET_BOARD_IDENTIFIER "REVO"
#define CONFIG_START_FLASH_ADDRESS (0x08080000) //0x08080000 to 0x080A0000 (FLASH_Sector_8) #define CONFIG_START_FLASH_ADDRESS (0x08080000) //0x08080000 to 0x080A0000 (FLASH_Sector_8)
#if defined(AIRBOTF4)
#define TARGET_BOARD_IDENTIFIER "AIR4"
#define USBD_PRODUCT_STRING "AirbotF4"
#elif defined(REVOLT)
#define TARGET_BOARD_IDENTIFIER "RVLT"
#define USBD_PRODUCT_STRING "Revolt"
#else
#define TARGET_BOARD_IDENTIFIER "REVO"
#define USBD_PRODUCT_STRING "Revolution" #define USBD_PRODUCT_STRING "Revolution"
#ifdef OPBL #ifdef OPBL
#define USBD_SERIALNUMBER_STRING "0x8020000" #define USBD_SERIALNUMBER_STRING "0x8020000"
#endif #endif
#endif
#define USE_DSHOT #define USE_DSHOT
#define LED0 PB5 #define LED0 PB5
// Disable LED1, conflicts with AirbotF4/Flip32F4 beeper // Disable LED1, conflicts with AirbotF4/Flip32F4/Revolt beeper
//#define LED1 PB4 #if defined(AIRBOTF4) || defined(REVOLT)
#define BEEPER PB4 #define BEEPER PB4
#define BEEPER_INVERTED #define BEEPER_INVERTED
#else
#define LED1 PB4
// Leave beeper here but with none as io - so disabled unless mapped.
#define BEEPER NONE
#endif
#define INVERTER PC0 // PC0 used as inverter select GPIO // PC0 used as inverter select GPIO
#define INVERTER PC0
#define INVERTER_USART USART1 #define INVERTER_USART USART1
#define MPU6000_CS_PIN PA4 #define MPU6000_CS_PIN PA4
#define MPU6000_SPI_INSTANCE SPI1 #define MPU6000_SPI_INSTANCE SPI1
#define MPU6500_CS_PIN PA4
#define MPU6500_SPI_INSTANCE SPI1
#define ACC #define ACC
#define USE_ACC_SPI_MPU6000 #define USE_ACC_SPI_MPU6000
#define GYRO_MPU6000_ALIGN CW270_DEG #define GYRO_MPU6000_ALIGN CW270_DEG
#define USE_ACC_MPU6500
#define USE_ACC_SPI_MPU6500
#define ACC_MPU6500_ALIGN CW270_DEG
#define GYRO #define GYRO
#define USE_GYRO_SPI_MPU6000 #define USE_GYRO_SPI_MPU6000
#define ACC_MPU6000_ALIGN CW270_DEG #define ACC_MPU6000_ALIGN CW270_DEG
#define USE_GYRO_MPU6500
#define USE_GYRO_SPI_MPU6500
#define GYRO_MPU9250_ALIGN CW270_DEG
// MPU6000 interrupts // MPU6000 interrupts
#define USE_EXTI #define USE_EXTI
#define MPU_INT_EXTI PC4 #define MPU_INT_EXTI PC4
#define USE_MPU_DATA_READY_SIGNAL #define USE_MPU_DATA_READY_SIGNAL
#if !defined(AIRBOTF4) && !defined(REVOLT)
#define MAG #define MAG
#define USE_MAG_HMC5883 #define USE_MAG_HMC5883
#define MAG_HMC5883_ALIGN CW90_DEG #define MAG_HMC5883_ALIGN CW90_DEG
@ -67,6 +95,7 @@
//#define PITOT //#define PITOT
//#define USE_PITOT_MS4525 //#define USE_PITOT_MS4525
//#define MS4525_BUS I2C_DEVICE_EXT //#define MS4525_BUS I2C_DEVICE_EXT
#endif
#define M25P16_CS_PIN PB3 #define M25P16_CS_PIN PB3
#define M25P16_SPI_INSTANCE SPI3 #define M25P16_SPI_INSTANCE SPI3
@ -78,8 +107,8 @@
#define VBUS_SENSING_PIN PC5 #define VBUS_SENSING_PIN PC5
#define USE_UART1 #define USE_UART1
#define UART1_RX_PIN PA10 #define UART1_RX_PIN PA10
#define UART1_TX_PIN PA9 #define UART1_TX_PIN PA9
#define UART1_AHB1_PERIPHERALS RCC_AHB1Periph_DMA2 #define UART1_AHB1_PERIPHERALS RCC_AHB1Periph_DMA2
#define USE_UART3 #define USE_UART3
@ -106,7 +135,7 @@
#define SPI3_MOSI_PIN PC12 #define SPI3_MOSI_PIN PC12
#define USE_I2C #define USE_I2C
#define I2C_DEVICE (I2CDEV_1) #define I2C_DEVICE (I2CDEV_1)
#define USE_ADC #define USE_ADC
#define CURRENT_METER_ADC_PIN PC1 #define CURRENT_METER_ADC_PIN PC1
@ -126,7 +155,7 @@
#define WS2811_DMA_FLAG DMA_FLAG_TCIF4 #define WS2811_DMA_FLAG DMA_FLAG_TCIF4
#define WS2811_DMA_IT DMA_IT_TCIF4 #define WS2811_DMA_IT DMA_IT_TCIF4
#define SENSORS_SET (SENSOR_ACC) #define SENSORS_SET (SENSOR_ACC)
#define DEFAULT_RX_FEATURE FEATURE_RX_SERIAL #define DEFAULT_RX_FEATURE FEATURE_RX_SERIAL
#define DEFAULT_FEATURES (FEATURE_BLACKBOX) #define DEFAULT_FEATURES (FEATURE_BLACKBOX)
@ -140,7 +169,12 @@
#define TARGET_IO_PORTA 0xffff #define TARGET_IO_PORTA 0xffff
#define TARGET_IO_PORTB 0xffff #define TARGET_IO_PORTB 0xffff
#define TARGET_IO_PORTC 0xffff #define TARGET_IO_PORTC 0xffff
#define TARGET_IO_PORTD 0xffff #define TARGET_IO_PORTD (BIT(2))
#ifdef REVOLT
#define USABLE_TIMER_CHANNEL_COUNT 11
#else
#define USABLE_TIMER_CHANNEL_COUNT 12 #define USABLE_TIMER_CHANNEL_COUNT 12
#endif
#define USED_TIMERS ( TIM_N(2) | TIM_N(3) | TIM_N(5) | TIM_N(12) | TIM_N(8) | TIM_N(9) ) #define USED_TIMERS ( TIM_N(2) | TIM_N(3) | TIM_N(5) | TIM_N(12) | TIM_N(8) | TIM_N(9) )

View file

@ -3,6 +3,8 @@ FEATURES += VCP ONBOARDFLASH
TARGET_SRC = \ TARGET_SRC = \
drivers/accgyro_spi_mpu6000.c \ drivers/accgyro_spi_mpu6000.c \
drivers/accgyro_mpu6500.c \
drivers/accgyro_spi_mpu6500.c \
drivers/barometer_ms5611.c \ drivers/barometer_ms5611.c \
drivers/compass_hmc5883l.c \ drivers/compass_hmc5883l.c \
io/cms.c \ io/cms.c \

View file

@ -625,8 +625,10 @@ void handleSmartPortTelemetry(void)
#ifdef GPS #ifdef GPS
case FSSP_DATAID_SPEED : case FSSP_DATAID_SPEED :
if (sensors(SENSOR_GPS) && STATE(GPS_FIX)) { if (sensors(SENSOR_GPS) && STATE(GPS_FIX)) {
uint32_t tmpui = (GPS_speed * 36 + 36 / 2) / 100; //convert to knots: 1cm/s = 0.0194384449 knots
smartPortSendPackage(id, tmpui); // given in 0.1 m/s, provide in KM/H //Speed should be sent in knots/1000 (GPS speed is in cm/s)
uint32_t tmpui = GPS_speed * 1944 / 100;
smartPortSendPackage(id, tmpui);
smartPortHasRequest = 0; smartPortHasRequest = 0;
} }
break; break;

View file

@ -26,6 +26,7 @@
#include "usbd_conf.h" #include "usbd_conf.h"
#include "usb_regs.h" #include "usb_regs.h"
#include "platform.h" #include "platform.h"
#include "build/version.h"
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{ * @{
@ -57,7 +58,7 @@
* @{ * @{
*/ */
#define USBD_LANGID_STRING 0x409 #define USBD_LANGID_STRING 0x409
#define USBD_MANUFACTURER_STRING "BetaFlight" #define USBD_MANUFACTURER_STRING FC_FIRMWARE_NAME
#ifdef USBD_PRODUCT_STRING #ifdef USBD_PRODUCT_STRING
#define USBD_PRODUCT_HS_STRING USBD_PRODUCT_STRING #define USBD_PRODUCT_HS_STRING USBD_PRODUCT_STRING

View file

@ -16,11 +16,13 @@ REPLY_FRAME_ID = 0x32
-- Sequence number for next MSP/SPORT packet -- Sequence number for next MSP/SPORT packet
local sportMspSeq = 0 local sportMspSeq = 0
local sportMspRemoteSeq = 0
local mspRxBuf = {} local mspRxBuf = {}
local mspRxIdx = 1 local mspRxIdx = 1
local mspRxCRC = 0 local mspRxCRC = 0
local mspStarted = false local mspStarted = false
local mspLastReq = 0
-- Stats -- Stats
mspRequestsSent = 0 mspRequestsSent = 0
@ -55,7 +57,8 @@ local function mspSendRequest(cmd)
value = bit32.band(cmd,0xFF) -- MSP command value = bit32.band(cmd,0xFF) -- MSP command
value = value + bit32.lshift(cmd,8) -- CRC value = value + bit32.lshift(cmd,8) -- CRC
mspRequestsSent = requestsSent + 1 mspLastReq = cmd
mspRequestsSent = mspRequestsSent + 1
return sportTelemetryPush(LOCAL_SENSOR_ID, REQUEST_FRAME_ID, dataId, value) return sportTelemetryPush(LOCAL_SENSOR_ID, REQUEST_FRAME_ID, dataId, value)
end end
@ -90,7 +93,7 @@ local function mspReceivedReply(payload)
mspRxBuf = {} mspRxBuf = {}
mspRxSize = payload[idx] mspRxSize = payload[idx]
mspRxCRC = mspRxSize mspRxCRC = bit32.bxor(mspRxSize,mspLastReq)
idx = idx + 1 idx = idx + 1
mspStarted = true mspStarted = true
@ -100,7 +103,7 @@ local function mspReceivedReply(payload)
mspOutOfOrder = mspOutOfOrder + 1 mspOutOfOrder = mspOutOfOrder + 1
return nil return nil
elseif bit32.band(lastSeq+1,0x0F) ~= seq then elseif bit32.band(sportMspRemoteSeq + 1, 0x0F) ~= seq then
mspOutOfOrder = mspOutOfOrder + 1 mspOutOfOrder = mspOutOfOrder + 1
mspStarted = false mspStarted = false
return nil return nil
@ -114,7 +117,7 @@ local function mspReceivedReply(payload)
end end
if idx > 6 then if idx > 6 then
lastRxSeq = seq sportMspRemoteSeq = seq
return return
end end
@ -122,6 +125,7 @@ local function mspReceivedReply(payload)
if mspRxCRC ~= payload[idx] then if mspRxCRC ~= payload[idx] then
mspStarted = false mspStarted = false
mspCRCErrors = mspCRCErrors + 1 mspCRCErrors = mspCRCErrors + 1
return nil
end end
mspRepliesReceived = mspRepliesReceived + 1 mspRepliesReceived = mspRepliesReceived + 1
@ -157,18 +161,14 @@ local function run(event)
local now = getTime() local now = getTime()
if event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_MINUS_REPT then if event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_MINUS_REPT then
requestsSent = 0 mspResetStats()
repliesReceived = 0
mspReceivedReply_cnt = 0
mspReceivedReply_cnt1 = 0
mspReceivedReply_cnt2 = 0
mspReceivedReply_cnt3 = 0
end end
lcd.clear() lcd.clear()
lcd.drawText(41,1,"MSP/SPORT test script",INVERS)
-- do we have valid telemetry data? -- do we have valid telemetry data?
if getValue("rssi") > 0 then if getValue("RSSI") > 0 then
-- draw screen -- draw screen
lcd.drawText(1,11,"Requests:",0) lcd.drawText(1,11,"Requests:",0)
@ -178,19 +178,19 @@ local function run(event)
lcd.drawNumber(60,21,mspRepliesReceived) lcd.drawNumber(60,21,mspRepliesReceived)
lcd.drawText(1,31,"PkRxed:",0) lcd.drawText(1,31,"PkRxed:",0)
lcd.drawNumber(30,31,mspPkRxed) lcd.drawNumber(60,31,mspPkRxed)
lcd.drawText(1,41,"ErrorPk:",0) lcd.drawText(1,41,"ErrorPk:",0)
lcd.drawNumber(30,41,mspErrorPk) lcd.drawNumber(60,41,mspErrorPk)
lcd.drawText(71,31,"StartPk:",0) lcd.drawText(91,31,"StartPk:",0)
lcd.drawNumber(100,31,mspStartPk) lcd.drawNumber(160,31,mspStartPk)
lcd.drawText(71,41,"OutOfOrder:",0) lcd.drawText(91,41,"OutOfOrder:",0)
lcd.drawNumber(100,41,mspOutOfOrder) lcd.drawNumber(160,41,mspOutOfOrder)
lcd.drawText(1,51,"CRCErrors:",0) lcd.drawText(1,51,"CRCErrors:",0)
lcd.drawNumber(30,51,mspCRCErrors) lcd.drawNumber(60,51,mspCRCErrors)
-- last request is at least 2s old -- last request is at least 2s old
if lastReqTS + 200 <= now then if lastReqTS + 200 <= now then
@ -198,10 +198,10 @@ local function run(event)
lastReqTS = now lastReqTS = now
end end
else else
lcd.drawText(20,30,"No telemetry signal", XXLSIZE + BLINK) lcd.drawText(15,20,"No telemetry signal", BLINK + DBLSIZE)
end end
pollReply() mspPollReply()
end end
return {run=run} return {run=run}