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:
commit
e9a2f2b2c1
42 changed files with 640 additions and 344 deletions
4
Makefile
4
Makefile
|
@ -736,11 +736,7 @@ OPTIMIZE = -O0
|
|||
LTO_FLAGS = $(OPTIMIZE)
|
||||
else
|
||||
OPTIMIZE = -Os
|
||||
ifeq ($(TARGET),$(filter $(TARGET),$(F1_TARGETS)))
|
||||
LTO_FLAGS = -flto -fuse-linker-plugin $(OPTIMIZE)
|
||||
else
|
||||
LTO_FLAGS = -fuse-linker-plugin $(OPTIMIZE)
|
||||
endif
|
||||
endif
|
||||
|
||||
DEBUG_FLAGS = -ggdb3 -DDEBUG
|
||||
|
|
|
@ -1169,7 +1169,7 @@ static bool blackboxWriteSysinfo()
|
|||
|
||||
switch (xmitState.headerIndex) {
|
||||
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("Craft name:%s", masterConfig.name);
|
||||
BLACKBOX_PRINT_HEADER_LINE("P interval:%d/%d", masterConfig.blackbox_rate_num, masterConfig.blackbox_rate_denom);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* 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_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
|
||||
|
|
|
@ -162,11 +162,7 @@ typedef struct master_s {
|
|||
#endif
|
||||
|
||||
#ifdef LED_STRIP
|
||||
ledConfig_t ledConfigs[LED_MAX_STRIP_LENGTH];
|
||||
hsvColor_t colors[LED_CONFIGURABLE_COLOR_COUNT];
|
||||
modeColorIndexes_t modeColors[LED_MODE_COUNT];
|
||||
specialColorIndexes_t specialColors;
|
||||
uint8_t ledstrip_visual_beeper; // suppress LEDLOW mode if beeper is on
|
||||
ledStripConfig_t ledStripConfig;
|
||||
#endif
|
||||
|
||||
#ifdef TRANSPONDER
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MPU6500_WHO_AM_I_CONST (0x70)
|
||||
#define MPU9250_WHO_AM_I_CONST (0x71)
|
||||
#define ICM20608G_WHO_AM_I_CONST (0xAF)
|
||||
#define ICM20602_WHO_AM_I_CONST (0x12)
|
||||
|
||||
#define MPU6500_BIT_RESET (0x80)
|
||||
#define MPU6500_BIT_INT_ANYRD_2CLEAR (1 << 4)
|
||||
|
@ -25,8 +28,6 @@
|
|||
#define MPU6500_BIT_I2C_IF_DIS (1 << 4)
|
||||
#define MPU6500_BIT_RAW_RDY_EN (0x01)
|
||||
|
||||
#pragma once
|
||||
|
||||
bool mpu6500AccDetect(acc_t *acc);
|
||||
bool mpu6500GyroDetect(gyro_t *gyro);
|
||||
|
||||
|
|
|
@ -84,7 +84,10 @@ bool mpu6500SpiDetect(void)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
struct dmaChannelDescriptor_s;
|
||||
typedef void (*dmaCallbackHandlerFuncPtr)(struct dmaChannelDescriptor_s *channelDescriptor);
|
||||
|
|
|
@ -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
|
||||
|
||||
// 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
|
||||
#define IO_NONE ((IO_t)0)
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "common/color.h"
|
||||
#include "common/colorconversion.h"
|
||||
#include "dma.h"
|
||||
#include "io.h"
|
||||
#include "light_ws2811strip.h"
|
||||
|
||||
#if defined(STM32F4) || defined(STM32F7)
|
||||
|
@ -84,10 +85,10 @@ void setStripColors(const hsvColor_t *colors)
|
|||
}
|
||||
}
|
||||
|
||||
void ws2811LedStripInit(void)
|
||||
void ws2811LedStripInit(ioTag_t ioTag)
|
||||
{
|
||||
memset(&ledStripDMABuffer, 0, WS2811_DMA_BUFFER_SIZE);
|
||||
ws2811LedStripHardwareInit();
|
||||
ws2811LedStripHardwareInit(ioTag);
|
||||
ws2811UpdateStrip();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "io_types.h"
|
||||
|
||||
#define WS2811_LED_STRIP_LENGTH 32
|
||||
#define WS2811_BITS_PER_LED 24
|
||||
#define WS2811_DELAY_BUFFER_LENGTH 42 // for 50us delay
|
||||
|
@ -36,9 +38,9 @@
|
|||
#define BIT_COMPARE_0 9 // timer compare value for logical 0
|
||||
#endif
|
||||
|
||||
void ws2811LedStripInit(void);
|
||||
void ws2811LedStripInit(ioTag_t ioTag);
|
||||
|
||||
void ws2811LedStripHardwareInit(void);
|
||||
void ws2811LedStripHardwareInit(ioTag_t ioTag);
|
||||
void ws2811LedStripDMAEnable(void);
|
||||
|
||||
void ws2811UpdateStrip(void);
|
||||
|
|
|
@ -31,26 +31,15 @@
|
|||
#include "rcc.h"
|
||||
#include "timer.h"
|
||||
|
||||
#if !defined(WS2811_PIN)
|
||||
#define WS2811_PIN PA0
|
||||
#define WS2811_TIMER TIM5
|
||||
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_ST2_HANDLER
|
||||
#define WS2811_DMA_STREAM DMA1_Stream2
|
||||
#define WS2811_DMA_IT DMA_IT_TCIF2
|
||||
#define WS2811_DMA_CHANNEL DMA_Channel_6
|
||||
#define WS2811_TIMER_CHANNEL TIM_Channel_1
|
||||
#define WS2811_TIMER_GPIO_AF GPIO_AF2_TIM5
|
||||
#endif
|
||||
|
||||
static IO_t ws2811IO = IO_NONE;
|
||||
static uint16_t timDMASource = 0;
|
||||
bool ws2811Initialised = false;
|
||||
|
||||
static TIM_HandleTypeDef TimHandle;
|
||||
static uint16_t timerChannel = 0;
|
||||
|
||||
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
if(htim->Instance==WS2811_TIMER)
|
||||
if(htim->Instance == TimHandle.Instance)
|
||||
{
|
||||
//HAL_TIM_PWM_Stop_DMA(&TimHandle,WS2811_TIMER_CHANNEL);
|
||||
ws2811LedDataTransferInProgress = 0;
|
||||
|
@ -62,9 +51,20 @@ void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor)
|
|||
HAL_DMA_IRQHandler(TimHandle.hdma[descriptor->userParam]);
|
||||
}
|
||||
|
||||
void ws2811LedStripHardwareInit(void)
|
||||
void ws2811LedStripHardwareInit(ioTag_t ioTag)
|
||||
{
|
||||
TimHandle.Instance = WS2811_TIMER;
|
||||
if (!ioTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
|
||||
TIM_TypeDef *timer = timerHardware->tim;
|
||||
timerChannel = timerHardware->channel;
|
||||
|
||||
if (timerHardware->dmaStream == NULL) {
|
||||
return;
|
||||
}
|
||||
TimHandle.Instance = timer;
|
||||
|
||||
TimHandle.Init.Prescaler = 1;
|
||||
TimHandle.Init.Period = 135; // 800kHz
|
||||
|
@ -78,16 +78,14 @@ void ws2811LedStripHardwareInit(void)
|
|||
|
||||
static DMA_HandleTypeDef hdma_tim;
|
||||
|
||||
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
|
||||
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
|
||||
ws2811IO = IOGetByTag(ioTag);
|
||||
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
|
||||
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), WS2811_TIMER_GPIO_AF);
|
||||
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), timerHardware->alternateFunction);
|
||||
|
||||
__DMA1_CLK_ENABLE();
|
||||
|
||||
|
||||
/* Set the parameters to be configured */
|
||||
hdma_tim.Init.Channel = WS2811_DMA_CHANNEL;
|
||||
hdma_tim.Init.Channel = timerHardware->dmaChannel;
|
||||
hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
|
||||
|
@ -101,30 +99,17 @@ void ws2811LedStripHardwareInit(void)
|
|||
hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
|
||||
|
||||
/* Set hdma_tim instance */
|
||||
hdma_tim.Instance = WS2811_DMA_STREAM;
|
||||
hdma_tim.Instance = timerHardware->dmaStream;
|
||||
|
||||
switch (WS2811_TIMER_CHANNEL) {
|
||||
case TIM_CHANNEL_1:
|
||||
timDMASource = TIM_DMA_ID_CC1;
|
||||
break;
|
||||
case TIM_CHANNEL_2:
|
||||
timDMASource = TIM_DMA_ID_CC2;
|
||||
break;
|
||||
case TIM_CHANNEL_3:
|
||||
timDMASource = TIM_DMA_ID_CC3;
|
||||
break;
|
||||
case TIM_CHANNEL_4:
|
||||
timDMASource = TIM_DMA_ID_CC4;
|
||||
break;
|
||||
}
|
||||
uint16_t dmaSource = timerDmaSource(timerChannel);
|
||||
|
||||
/* Link hdma_tim to hdma[x] (channelx) */
|
||||
__HAL_LINKDMA(&TimHandle, hdma[timDMASource], hdma_tim);
|
||||
__HAL_LINKDMA(&TimHandle, hdma[dmaSource], hdma_tim);
|
||||
|
||||
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, timDMASource);
|
||||
dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, dmaSource);
|
||||
|
||||
/* Initialize TIMx DMA handle */
|
||||
if(HAL_DMA_Init(TimHandle.hdma[timDMASource]) != HAL_OK)
|
||||
if(HAL_DMA_Init(TimHandle.hdma[dmaSource]) != HAL_OK)
|
||||
{
|
||||
/* Initialization Error */
|
||||
return;
|
||||
|
@ -140,7 +125,7 @@ void ws2811LedStripHardwareInit(void)
|
|||
TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;
|
||||
TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
|
||||
if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, WS2811_TIMER_CHANNEL) != HAL_OK)
|
||||
if(HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, timerChannel) != HAL_OK)
|
||||
{
|
||||
/* Configuration Error */
|
||||
return;
|
||||
|
@ -160,7 +145,7 @@ void ws2811LedStripDMAEnable(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if( HAL_TIM_PWM_Start_DMA(&TimHandle, WS2811_TIMER_CHANNEL, ledStripDMABuffer, WS2811_DMA_BUFFER_SIZE) != HAL_OK)
|
||||
if( HAL_TIM_PWM_Start_DMA(&TimHandle, timerChannel, ledStripDMABuffer, WS2811_DMA_BUFFER_SIZE) != HAL_OK)
|
||||
{
|
||||
/* Starting PWM generation Error */
|
||||
ws2811LedDataTransferInProgress = 0;
|
||||
|
|
|
@ -30,10 +30,16 @@
|
|||
#include "rcc.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define WS2811_TIMER_HZ 24000000
|
||||
#define WS2811_TIMER_PERIOD 29
|
||||
|
||||
static IO_t ws2811IO = IO_NONE;
|
||||
bool ws2811Initialised = false;
|
||||
static DMA_Channel_TypeDef *dmaChannel = NULL;
|
||||
static TIM_TypeDef *timer = NULL;
|
||||
|
||||
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) {
|
||||
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
|
||||
{
|
||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
|
||||
ws2811LedDataTransferInProgress = 0;
|
||||
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_OCInitTypeDef TIM_OCInitStructure;
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
|
||||
uint16_t prescalerValue;
|
||||
const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
|
||||
timer = timerHardware->tim;
|
||||
|
||||
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
|
||||
if (timerHardware->dmaChannel == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
|
||||
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
|
||||
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
|
||||
IOConfigGPIO(ws2811IO, IO_CONFIG(GPIO_Speed_50MHz, GPIO_Mode_AF_PP));
|
||||
|
||||
RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE);
|
||||
|
||||
/* Compute the prescaler value */
|
||||
prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
|
||||
uint16_t prescalerValue = (uint16_t) (SystemCoreClock / WS2811_TIMER_HZ) - 1;
|
||||
/* Time base configuration */
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseStructure.TIM_Period = 29; // 800kHz
|
||||
TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
|
||||
|
||||
/* PWM1 Mode configuration: Channel1 */
|
||||
TIM_OCStructInit(&TIM_OCInitStructure);
|
||||
|
@ -74,20 +86,17 @@ void ws2811LedStripHardwareInit(void)
|
|||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OCInitStructure.TIM_Pulse = 0;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
|
||||
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
|
||||
TIM_OC1Init(timer, &TIM_OCInitStructure);
|
||||
TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable);
|
||||
|
||||
TIM_CtrlPWMOutputs(TIM3, ENABLE);
|
||||
TIM_CtrlPWMOutputs(timer, ENABLE);
|
||||
|
||||
/* configure DMA */
|
||||
/* DMA clock enable */
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
|
||||
|
||||
/* DMA1 Channel6 Config */
|
||||
DMA_DeInit(DMA1_Channel6);
|
||||
DMA_DeInit(dmaChannel);
|
||||
|
||||
DMA_StructInit(&DMA_InitStructure);
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&TIM3->CCR1;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel);
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ledStripDMABuffer;
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
||||
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE;
|
||||
|
@ -99,12 +108,13 @@ void ws2811LedStripHardwareInit(void)
|
|||
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||
|
||||
DMA_Init(DMA1_Channel6, &DMA_InitStructure);
|
||||
DMA_Init(dmaChannel, &DMA_InitStructure);
|
||||
|
||||
/* TIM3 CC1 DMA Request enable */
|
||||
TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);
|
||||
TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE);
|
||||
|
||||
DMA_ITConfig(DMA1_Channel6, DMA_IT_TC, ENABLE);
|
||||
DMA_ITConfig(dmaChannel, DMA_IT_TC, ENABLE);
|
||||
dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
|
||||
|
||||
const hsvColor_t hsv_white = { 0, 255, 255};
|
||||
ws2811Initialised = true;
|
||||
|
@ -117,10 +127,10 @@ void ws2811LedStripDMAEnable(void)
|
|||
if (!ws2811Initialised)
|
||||
return;
|
||||
|
||||
DMA_SetCurrDataCounter(DMA1_Channel6, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
|
||||
TIM_SetCounter(TIM3, 0);
|
||||
TIM_Cmd(TIM3, ENABLE);
|
||||
DMA_Cmd(DMA1_Channel6, ENABLE);
|
||||
DMA_SetCurrDataCounter(dmaChannel, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
|
||||
TIM_SetCounter(timer, 0);
|
||||
TIM_Cmd(timer, ENABLE);
|
||||
DMA_Cmd(dmaChannel, ENABLE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,18 +31,16 @@
|
|||
#include "rcc.h"
|
||||
#include "timer.h"
|
||||
|
||||
#ifndef WS2811_PIN
|
||||
#define WS2811_PIN PB8 // TIM16_CH1
|
||||
#define WS2811_TIMER TIM16
|
||||
#define WS2811_DMA_CHANNEL DMA1_Channel3
|
||||
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_CH3_HANDLER
|
||||
#define WS2811_TIMER_GPIO_AF GPIO_AF_1
|
||||
#endif
|
||||
#define WS2811_TIMER_HZ 24000000
|
||||
#define WS2811_TIMER_PERIOD 29
|
||||
|
||||
static IO_t ws2811IO = IO_NONE;
|
||||
bool ws2811Initialised = false;
|
||||
static DMA_Channel_TypeDef *dmaChannel = NULL;
|
||||
static TIM_TypeDef *timer = NULL;
|
||||
|
||||
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor) {
|
||||
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
|
||||
{
|
||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
|
||||
ws2811LedDataTransferInProgress = 0;
|
||||
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_OCInitTypeDef TIM_OCInitStructure;
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
|
||||
uint16_t prescalerValue;
|
||||
const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
|
||||
timer = timerHardware->tim;
|
||||
|
||||
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
|
||||
if (timerHardware->dmaChannel == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
|
||||
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
|
||||
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
|
||||
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), WS2811_TIMER_GPIO_AF);
|
||||
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction);
|
||||
|
||||
RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE);
|
||||
RCC_ClockCmd(timerRCC(timer), ENABLE);
|
||||
|
||||
/* Compute the prescaler value */
|
||||
prescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
|
||||
uint16_t prescalerValue = (uint16_t) (SystemCoreClock / WS2811_TIMER_HZ) - 1;
|
||||
|
||||
/* Time base configuration */
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseStructure.TIM_Period = 29; // 800kHz
|
||||
TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
|
||||
|
||||
/* PWM1 Mode configuration */
|
||||
TIM_OCStructInit(&TIM_OCInitStructure);
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
|
||||
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
|
||||
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
|
||||
TIM_OCInitStructure.TIM_OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPolarity_High : TIM_OCNPolarity_Low;
|
||||
} else {
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High;
|
||||
}
|
||||
TIM_OCInitStructure.TIM_Pulse = 0;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
|
||||
TIM_OC1Init(WS2811_TIMER, &TIM_OCInitStructure);
|
||||
TIM_OC1PreloadConfig(WS2811_TIMER, TIM_OCPreload_Enable);
|
||||
TIM_OC1Init(timer, &TIM_OCInitStructure);
|
||||
TIM_OC1PreloadConfig(timer, TIM_OCPreload_Enable);
|
||||
|
||||
TIM_CtrlPWMOutputs(timer, ENABLE);
|
||||
|
||||
TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE);
|
||||
dmaChannel = timerHardware->dmaChannel;
|
||||
|
||||
/* configure DMA */
|
||||
/* DMA1 Channel Config */
|
||||
DMA_DeInit(WS2811_DMA_CHANNEL);
|
||||
DMA_DeInit(dmaChannel);
|
||||
|
||||
DMA_StructInit(&DMA_InitStructure);
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&WS2811_TIMER->CCR1;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel);
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ledStripDMABuffer;
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
||||
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE;
|
||||
|
@ -106,11 +119,12 @@ void ws2811LedStripHardwareInit(void)
|
|||
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
|
||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||
|
||||
DMA_Init(WS2811_DMA_CHANNEL, &DMA_InitStructure);
|
||||
DMA_Init(dmaChannel, &DMA_InitStructure);
|
||||
|
||||
TIM_DMACmd(WS2811_TIMER, TIM_DMA_CC1, ENABLE);
|
||||
TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE);
|
||||
|
||||
DMA_ITConfig(WS2811_DMA_CHANNEL, DMA_IT_TC, ENABLE);
|
||||
DMA_ITConfig(dmaChannel, DMA_IT_TC, ENABLE);
|
||||
dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
|
||||
|
||||
const hsvColor_t hsv_white = { 0, 255, 255};
|
||||
ws2811Initialised = true;
|
||||
|
@ -123,10 +137,10 @@ void ws2811LedStripDMAEnable(void)
|
|||
if (!ws2811Initialised)
|
||||
return;
|
||||
|
||||
DMA_SetCurrDataCounter(WS2811_DMA_CHANNEL, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
|
||||
TIM_SetCounter(WS2811_TIMER, 0);
|
||||
TIM_Cmd(WS2811_TIMER, ENABLE);
|
||||
DMA_Cmd(WS2811_DMA_CHANNEL, ENABLE);
|
||||
DMA_SetCurrDataCounter(dmaChannel, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
|
||||
TIM_SetCounter(timer, 0);
|
||||
TIM_Cmd(timer, ENABLE);
|
||||
DMA_Cmd(dmaChannel, ENABLE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,85 +31,93 @@
|
|||
#include "rcc.h"
|
||||
#include "timer.h"
|
||||
#include "timer_stm32f4xx.h"
|
||||
#include "io.h"
|
||||
|
||||
#if !defined(WS2811_PIN)
|
||||
#define WS2811_PIN PA0
|
||||
#define WS2811_TIMER TIM5
|
||||
#define WS2811_DMA_HANDLER_IDENTIFER DMA1_ST2_HANDLER
|
||||
#define WS2811_DMA_STREAM DMA1_Stream2
|
||||
#define WS2811_DMA_CHANNEL DMA_Channel_6
|
||||
#define WS2811_TIMER_CHANNEL TIM_Channel_1
|
||||
#define WS2811_TIMER_GPIO_AF GPIO_AF_TIM5
|
||||
#endif
|
||||
#define WS2811_TIMER_HZ 84000000
|
||||
#define WS2811_TIMER_PERIOD 104
|
||||
|
||||
static IO_t ws2811IO = IO_NONE;
|
||||
static uint16_t timDMASource = 0;
|
||||
bool ws2811Initialised = false;
|
||||
static DMA_Stream_TypeDef *stream = NULL;
|
||||
static TIM_TypeDef *timer = NULL;
|
||||
|
||||
static void WS2811_DMA_IRQHandler(dmaChannelDescriptor_t *descriptor)
|
||||
{
|
||||
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
|
||||
ws2811LedDataTransferInProgress = 0;
|
||||
DMA_Cmd(descriptor->stream, DISABLE);
|
||||
TIM_DMACmd(WS2811_TIMER, timDMASource, DISABLE);
|
||||
DMA_CLEAR_FLAG(descriptor, DMA_IT_TCIF);
|
||||
}
|
||||
}
|
||||
|
||||
void ws2811LedStripHardwareInit(void)
|
||||
void ws2811LedStripHardwareInit(ioTag_t ioTag)
|
||||
{
|
||||
if (!ioTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
TIM_OCInitTypeDef TIM_OCInitStructure;
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
|
||||
uint16_t prescalerValue;
|
||||
const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
|
||||
timer = timerHardware->tim;
|
||||
|
||||
RCC_ClockCmd(timerRCC(WS2811_TIMER), ENABLE);
|
||||
if (timerHardware->dmaStream == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN));
|
||||
RCC_ClockCmd(timerRCC(timer), ENABLE);
|
||||
|
||||
ws2811IO = IOGetByTag(ioTag);
|
||||
/* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */
|
||||
IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0);
|
||||
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), WS2811_TIMER_GPIO_AF);
|
||||
IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_PP, GPIO_PuPd_UP), timerHardware->alternateFunction);
|
||||
|
||||
// Stop timer
|
||||
TIM_Cmd(WS2811_TIMER, DISABLE);
|
||||
TIM_Cmd(timer, DISABLE);
|
||||
|
||||
/* Compute the prescaler value */
|
||||
prescalerValue = (uint16_t)(SystemCoreClock / 2 / 84000000) - 1;
|
||||
uint16_t prescalerValue = (uint16_t)(SystemCoreClock / timerClockDivisor(timer) / WS2811_TIMER_HZ) - 1;
|
||||
|
||||
/* Time base configuration */
|
||||
TIM_TimeBaseStructure.TIM_Period = 104; // 800kHz
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseStructure.TIM_Period = WS2811_TIMER_PERIOD; // 800kHz
|
||||
TIM_TimeBaseStructure.TIM_Prescaler = prescalerValue;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(WS2811_TIMER, &TIM_TimeBaseStructure);
|
||||
TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
|
||||
|
||||
/* PWM1 Mode configuration: Channel1 */
|
||||
TIM_OCStructInit(&TIM_OCInitStructure);
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
|
||||
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCNPolarity_High;
|
||||
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
|
||||
if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
|
||||
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
|
||||
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
|
||||
TIM_OCInitStructure.TIM_OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPolarity_High : TIM_OCNPolarity_Low;
|
||||
} else {
|
||||
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
|
||||
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
|
||||
TIM_OCInitStructure.TIM_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High;
|
||||
}
|
||||
TIM_OCInitStructure.TIM_Pulse = 0;
|
||||
|
||||
timerOCInit(WS2811_TIMER, WS2811_TIMER_CHANNEL, &TIM_OCInitStructure);
|
||||
timerOCPreloadConfig(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_OCPreload_Enable);
|
||||
timDMASource = timerDmaSource(WS2811_TIMER_CHANNEL);
|
||||
timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);
|
||||
timerOCPreloadConfig(timer, timerHardware->channel, TIM_OCPreload_Enable);
|
||||
|
||||
TIM_CtrlPWMOutputs(WS2811_TIMER, ENABLE);
|
||||
TIM_ARRPreloadConfig(WS2811_TIMER, ENABLE);
|
||||
TIM_CtrlPWMOutputs(timer, ENABLE);
|
||||
TIM_ARRPreloadConfig(timer, ENABLE);
|
||||
|
||||
TIM_CCxCmd(WS2811_TIMER, WS2811_TIMER_CHANNEL, TIM_CCx_Enable);
|
||||
TIM_Cmd(WS2811_TIMER, ENABLE);
|
||||
TIM_CCxCmd(timer, timerHardware->channel, TIM_CCx_Enable);
|
||||
TIM_Cmd(timer, ENABLE);
|
||||
|
||||
stream = timerHardware->dmaStream;
|
||||
/* configure DMA */
|
||||
DMA_Cmd(WS2811_DMA_STREAM, DISABLE);
|
||||
DMA_DeInit(WS2811_DMA_STREAM);
|
||||
DMA_Cmd(stream, DISABLE);
|
||||
DMA_DeInit(stream);
|
||||
DMA_StructInit(&DMA_InitStructure);
|
||||
DMA_InitStructure.DMA_Channel = WS2811_DMA_CHANNEL;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(WS2811_TIMER, WS2811_TIMER_CHANNEL);
|
||||
DMA_InitStructure.DMA_Channel = timerHardware->dmaChannel;
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)timerCCR(timer, timerHardware->channel);
|
||||
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ledStripDMABuffer;
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
|
||||
DMA_InitStructure.DMA_BufferSize = WS2811_DMA_BUFFER_SIZE;
|
||||
|
@ -124,14 +132,15 @@ void ws2811LedStripHardwareInit(void)
|
|||
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
|
||||
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
|
||||
|
||||
DMA_Init(WS2811_DMA_STREAM, &DMA_InitStructure);
|
||||
DMA_Init(stream, &DMA_InitStructure);
|
||||
TIM_DMACmd(timer, timerDmaSource(timerHardware->channel), ENABLE);
|
||||
|
||||
DMA_ITConfig(WS2811_DMA_STREAM, DMA_IT_TC, ENABLE);
|
||||
DMA_ClearITPendingBit(WS2811_DMA_STREAM, dmaFlag_IT_TCIF(WS2811_DMA_STREAM));
|
||||
DMA_ITConfig(stream, DMA_IT_TC, ENABLE);
|
||||
DMA_ClearITPendingBit(stream, dmaFlag_IT_TCIF(stream));
|
||||
|
||||
dmaSetHandler(WS2811_DMA_HANDLER_IDENTIFER, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
|
||||
dmaSetHandler(timerHardware->dmaIrqHandler, WS2811_DMA_IRQHandler, NVIC_PRIO_WS2811_DMA, 0);
|
||||
|
||||
const hsvColor_t hsv_white = { 0, 255, 255};
|
||||
const hsvColor_t hsv_white = { 0, 255, 255 };
|
||||
ws2811Initialised = true;
|
||||
setStripColor(&hsv_white);
|
||||
ws2811UpdateStrip();
|
||||
|
@ -142,10 +151,10 @@ void ws2811LedStripDMAEnable(void)
|
|||
if (!ws2811Initialised)
|
||||
return;
|
||||
|
||||
DMA_SetCurrDataCounter(WS2811_DMA_STREAM, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
|
||||
TIM_SetCounter(WS2811_TIMER, 0);
|
||||
DMA_Cmd(WS2811_DMA_STREAM, ENABLE);
|
||||
TIM_DMACmd(WS2811_TIMER, timDMASource, ENABLE);
|
||||
DMA_SetCurrDataCounter(stream, WS2811_DMA_BUFFER_SIZE); // load number of bytes to be transferred
|
||||
TIM_SetCounter(timer, 0);
|
||||
TIM_Cmd(timer, ENABLE);
|
||||
DMA_Cmd(stream, ENABLE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -208,7 +208,7 @@ void motorInit(const motorConfig_t *motorConfig, uint16_t idlePulse, uint8_t mot
|
|||
break;
|
||||
}
|
||||
|
||||
const timerHardware_t *timerHardware = timerGetByTag(tag, TIM_USE_MOTOR);
|
||||
const timerHardware_t *timerHardware = timerGetByTag(tag, TIM_USE_ANY);
|
||||
|
||||
if (timerHardware == NULL) {
|
||||
/* 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));
|
||||
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) {
|
||||
/* flag failure and disable ability to arm */
|
||||
|
|
|
@ -119,7 +119,8 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
|
|||
|
||||
if (configureTimer) {
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
|
||||
RCC_ClockCmd(timerRCC(timer), ENABLE);
|
||||
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_Period = MOTOR_BITLENGTH;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
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_OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPolarity_Low : TIM_OCPolarity_High;
|
||||
}
|
||||
|
||||
TIM_OCInitStructure.TIM_Pulse = 0;
|
||||
|
||||
timerOCInit(timer, timerHardware->channel, &TIM_OCInitStructure);
|
||||
|
|
|
@ -120,7 +120,8 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
|
|||
|
||||
if (configureTimer) {
|
||||
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
|
||||
|
||||
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
|
||||
|
||||
RCC_ClockCmd(timerRCC(timer), ENABLE);
|
||||
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_Period = MOTOR_BITLENGTH;
|
||||
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
|
||||
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
|
||||
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
|
||||
TIM_TimeBaseInit(timer, &TIM_TimeBaseStructure);
|
||||
}
|
||||
|
||||
TIM_OCStructInit(&TIM_OCInitStructure);
|
||||
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
|
||||
if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
|
||||
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
|
||||
|
|
|
@ -145,6 +145,7 @@ void pwmDigitalMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t
|
|||
motor->TimHandle.Instance = timerHardware->tim;
|
||||
motor->TimHandle.Init.Prescaler = (SystemCoreClock / timerClockDivisor(timer) / hz) - 1;;
|
||||
motor->TimHandle.Init.Period = MOTOR_BITLENGTH;
|
||||
motor->TimHandle.Init.RepetitionCounter = 0;
|
||||
motor->TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
motor->TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
if(HAL_TIM_PWM_Init(&motor->TimHandle) != HAL_OK)
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
@ -25,6 +26,13 @@ typedef enum {
|
|||
BAUDRATE_KISS = 38400
|
||||
} escBaudRate_e;
|
||||
|
||||
typedef enum {
|
||||
PROTOCOL_SIMONK = 0,
|
||||
PROTOCOL_BLHELI = 1,
|
||||
PROTOCOL_KISS = 2,
|
||||
PROTOCOL_KISSALL = 3
|
||||
} escProtocol_e;
|
||||
|
||||
#if defined(USE_ESCSERIAL)
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
@ -80,11 +88,19 @@ typedef struct escSerial_s {
|
|||
|
||||
uint8_t escSerialPortIndex;
|
||||
uint8_t mode;
|
||||
uint8_t outputCount;
|
||||
|
||||
timerCCHandlerRec_t timerCb;
|
||||
timerCCHandlerRec_t edgeCb;
|
||||
} escSerial_t;
|
||||
|
||||
typedef struct {
|
||||
IO_t io;
|
||||
uint8_t inverted;
|
||||
} escOutputs_t;
|
||||
|
||||
escOutputs_t escOutputs[MAX_SUPPORTED_MOTORS];
|
||||
|
||||
extern timerHardware_t* serialTimerHardware;
|
||||
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 onSerialTimerBL(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)
|
||||
{
|
||||
if (state) {
|
||||
IOHi(escSerial->txIO);
|
||||
} else {
|
||||
IOLo(escSerial->txIO);
|
||||
if((escSerial->mode = PROTOCOL_KISSALL))
|
||||
{
|
||||
for (volatile uint8_t i = 0; i < escSerial->outputCount; i++) {
|
||||
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);
|
||||
}
|
||||
|
||||
void serialInputPortConfigEsc(const timerHardware_t *timerHardwarePtr)
|
||||
void escSerialInputPortConfig(const timerHardware_t *timerHardwarePtr)
|
||||
{
|
||||
#ifdef STM32F10X
|
||||
escSerialGPIOConfig(timerHardwarePtr->tag, IOCFG_IPU);
|
||||
|
@ -164,12 +202,12 @@ static void serialTimerRxConfigBL(const timerHardware_t *timerHardwarePtr, uint8
|
|||
uint8_t mhz = SystemCoreClock / 2000000;
|
||||
TIM_DeInit(timerHardwarePtr->tim);
|
||||
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);
|
||||
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;
|
||||
TIM_DeInit(timerHardwarePtr->tim);
|
||||
|
@ -178,7 +216,7 @@ static void serialTimerTxConfig(const timerHardware_t *timerHardwarePtr, uint8_t
|
|||
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;
|
||||
|
||||
|
@ -192,17 +230,17 @@ static void serialICConfig(TIM_TypeDef *tim, uint8_t channel, uint16_t polarity)
|
|||
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
|
||||
TIM_DeInit(timerHardwarePtr->tim);
|
||||
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);
|
||||
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);
|
||||
timerChITConfig(timerHardwarePtr,DISABLE);
|
||||
|
@ -225,7 +263,11 @@ serialPort_t *openEscSerial(escSerialPortIndex_e portIndex, serialReceiveCallbac
|
|||
{
|
||||
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->port.vTable = escSerialVTable;
|
||||
|
@ -247,30 +289,56 @@ serialPort_t *openEscSerial(escSerialPortIndex_e portIndex, serialReceiveCallbac
|
|||
|
||||
escSerial->escSerialPortIndex = portIndex;
|
||||
|
||||
escSerial->txIO = IOGetByTag(escSerial->rxTimerHardware->tag);
|
||||
serialInputPortConfigEsc(escSerial->rxTimerHardware);
|
||||
|
||||
setTxSignalEsc(escSerial, ENABLE);
|
||||
if(mode != PROTOCOL_KISSALL)
|
||||
{
|
||||
escSerial->txIO = IOGetByTag(escSerial->rxTimerHardware->tag);
|
||||
escSerialInputPortConfig(escSerial->rxTimerHardware);
|
||||
setTxSignalEsc(escSerial, ENABLE);
|
||||
}
|
||||
delay(50);
|
||||
|
||||
if(mode==0){
|
||||
serialTimerTxConfig(escSerial->txTimerHardware, portIndex);
|
||||
serialTimerRxConfig(escSerial->rxTimerHardware, portIndex);
|
||||
if(mode==PROTOCOL_SIMONK){
|
||||
escSerialTimerTxConfig(escSerial->txTimerHardware, portIndex);
|
||||
escSerialTimerRxConfig(escSerial->rxTimerHardware, portIndex);
|
||||
}
|
||||
else if(mode==1){
|
||||
else if(mode==PROTOCOL_BLHELI){
|
||||
serialTimerTxConfigBL(escSerial->txTimerHardware, portIndex, baud);
|
||||
serialTimerRxConfigBL(escSerial->rxTimerHardware, portIndex, options);
|
||||
}
|
||||
else if(mode==2) {
|
||||
serialOutputPortConfig(escSerial->rxTimerHardware); // rx is the pin used
|
||||
else if(mode==PROTOCOL_KISS) {
|
||||
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);
|
||||
}
|
||||
escSerial->mode = mode;
|
||||
return &escSerial->port;
|
||||
}
|
||||
|
||||
|
||||
void serialInputPortDeConfig(const timerHardware_t *timerHardwarePtr)
|
||||
void escSerialInputPortDeConfig(const timerHardware_t *timerHardwarePtr)
|
||||
{
|
||||
timerChClearCCFlag(timerHardwarePtr);
|
||||
timerChITConfig(timerHardwarePtr,DISABLE);
|
||||
|
@ -284,7 +352,7 @@ void closeEscSerial(escSerialPortIndex_e portIndex, uint16_t output)
|
|||
|
||||
escSerial->rxTimerHardware = &(timerHardware[output]);
|
||||
escSerial->txTimerHardware = &(timerHardware[ESCSERIAL_TIMER_TX_HARDWARE]);
|
||||
serialInputPortDeConfig(escSerial->rxTimerHardware);
|
||||
escSerialInputPortDeConfig(escSerial->rxTimerHardware);
|
||||
timerChConfigCallbacks(escSerial->txTimerHardware,NULL,NULL);
|
||||
timerChConfigCallbacks(escSerial->rxTimerHardware,NULL,NULL);
|
||||
TIM_DeInit(escSerial->txTimerHardware->tim);
|
||||
|
@ -339,7 +407,7 @@ reload:
|
|||
escSerial->isTransmittingData = true;
|
||||
|
||||
//set output
|
||||
serialOutputPortConfig(escSerial->rxTimerHardware);
|
||||
escSerialOutputPortConfig(escSerial->rxTimerHardware);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -383,7 +451,7 @@ reload:
|
|||
|
||||
if (isEscSerialTransmitBufferEmpty((serialPort_t *)escSerial)) {
|
||||
escSerial->isTransmittingData = false;
|
||||
serialInputPortConfigEsc(escSerial->rxTimerHardware);
|
||||
escSerialInputPortConfig(escSerial->rxTimerHardware);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -417,7 +485,9 @@ void processTxStateBL(escSerial_t *escSerial)
|
|||
|
||||
|
||||
//set output
|
||||
serialOutputPortConfig(escSerial->rxTimerHardware);
|
||||
if(escSerial->mode==PROTOCOL_BLHELI) {
|
||||
escSerialOutputPortConfig(escSerial->rxTimerHardware);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -432,9 +502,9 @@ void processTxStateBL(escSerial_t *escSerial)
|
|||
|
||||
escSerial->isTransmittingData = false;
|
||||
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;
|
||||
if (escSerial->rxEdge == LEADING) {
|
||||
escSerial->rxEdge = TRAILING;
|
||||
serialICConfig(
|
||||
escSerialICConfig(
|
||||
escSerial->rxTimerHardware->tim,
|
||||
escSerial->rxTimerHardware->channel,
|
||||
(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++;
|
||||
}
|
||||
|
||||
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->rxBitIndex = 0;
|
||||
|
@ -569,10 +639,10 @@ void onSerialRxPinChangeBL(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
|
|||
|
||||
if (escSerial->rxEdge == TRAILING) {
|
||||
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 {
|
||||
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*/
|
||||
|
@ -605,7 +675,7 @@ void onSerialTimerEsc(timerCCHandlerRec_t *cbRec, captureCompare_t capture)
|
|||
{
|
||||
escSerial->isReceivingData=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;
|
||||
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;
|
||||
|
@ -763,7 +833,7 @@ void escSerialInitialize()
|
|||
|
||||
for (volatile uint8_t i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) {
|
||||
// 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
|
||||
}
|
||||
|
@ -844,27 +914,34 @@ static bool ProcessExitCommand(uint8_t c)
|
|||
void escEnablePassthrough(serialPort_t *escPassthroughPort, uint16_t output, uint8_t mode)
|
||||
{
|
||||
bool exitEsc = false;
|
||||
uint8_t motor_output = 0;
|
||||
LED0_OFF;
|
||||
LED1_OFF;
|
||||
//StopPwmAllMotors();
|
||||
pwmDisableMotors();
|
||||
passPort = escPassthroughPort;
|
||||
|
||||
uint8_t first_output = 0;
|
||||
for (volatile uint8_t i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) {
|
||||
if(timerHardware[i].output==1)
|
||||
{
|
||||
first_output=i;
|
||||
break;
|
||||
}
|
||||
uint32_t escBaudrate = (mode == PROTOCOL_KISS) ? BAUDRATE_KISS : BAUDRATE_NORMAL;
|
||||
|
||||
if((mode == PROTOCOL_KISS) && (output == 255)){
|
||||
motor_output = 255;
|
||||
mode = PROTOCOL_KISSALL;
|
||||
}
|
||||
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
|
||||
uint8_t motor_output=first_output+output-1;
|
||||
if(motor_output >=USABLE_TIMER_CHANNEL_COUNT)
|
||||
return;
|
||||
|
||||
uint32_t escBaudrate = (mode == 2) ? BAUDRATE_KISS : BAUDRATE_NORMAL;
|
||||
//doesn't work with messy timertable
|
||||
motor_output=first_output+output-1;
|
||||
if(motor_output >=USABLE_TIMER_CHANNEL_COUNT)
|
||||
return;
|
||||
}
|
||||
|
||||
escPort = openEscSerial(ESCSERIAL1, NULL, motor_output, escBaudrate, 0, mode);
|
||||
uint8_t ch;
|
||||
|
@ -898,7 +975,7 @@ void escEnablePassthrough(serialPort_t *escPassthroughPort, uint16_t output, uin
|
|||
closeEscSerial(ESCSERIAL1, output);
|
||||
return;
|
||||
}
|
||||
if(mode==1){
|
||||
if(mode==PROTOCOL_BLHELI){
|
||||
serialWrite(escPassthroughPort, ch); // blheli loopback
|
||||
}
|
||||
serialWrite(escPort, ch);
|
||||
|
|
|
@ -759,7 +759,7 @@ const timerHardware_t *timerGetByTag(ioTag_t tag, timerUsageFlag_e flag)
|
|||
{
|
||||
for (int i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) {
|
||||
if (timerHardware[i].tag == tag) {
|
||||
if (timerHardware[i].usageFlags & flag) {
|
||||
if (timerHardware[i].usageFlags & flag || flag == 0) {
|
||||
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);
|
||||
}
|
||||
|
||||
#ifndef USE_HAL_DRIVER
|
||||
uint16_t timerDmaSource(uint8_t channel)
|
||||
{
|
||||
switch (channel) {
|
||||
|
@ -823,4 +824,5 @@ uint16_t timerDmaSource(uint8_t channel)
|
|||
return TIM_DMA_CC4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -55,6 +55,7 @@ typedef uint32_t timCNT_t;
|
|||
#endif
|
||||
|
||||
typedef enum {
|
||||
TIM_USE_ANY = 0x0,
|
||||
TIM_USE_PPM = 0x1,
|
||||
TIM_USE_PWM = 0x2,
|
||||
TIM_USE_MOTOR = 0x4,
|
||||
|
@ -92,11 +93,11 @@ typedef struct timerHardware_s {
|
|||
#if defined(STM32F3) || defined(STM32F4) || defined(STM32F7)
|
||||
uint8_t alternateFunction;
|
||||
#endif
|
||||
#if defined(USE_DSHOT)
|
||||
#if defined(USE_DSHOT) || defined(LED_STRIP)
|
||||
#if defined(STM32F4) || defined(STM32F7)
|
||||
DMA_Stream_TypeDef *dmaStream;
|
||||
uint32_t dmaChannel;
|
||||
#elif defined(STM32F3)
|
||||
#elif defined(STM32F3) || defined(STM32F1)
|
||||
DMA_Channel_TypeDef *dmaChannel;
|
||||
#endif
|
||||
uint8_t dmaIrqHandler;
|
||||
|
|
|
@ -867,3 +867,18 @@ const timerHardware_t *timerGetByTag(ioTag_t tag, timerUsageFlag_e flag)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t timerDmaSource(uint8_t channel)
|
||||
{
|
||||
switch (channel) {
|
||||
case TIM_CHANNEL_1:
|
||||
return TIM_DMA_ID_CC1;
|
||||
case TIM_CHANNEL_2:
|
||||
return TIM_DMA_ID_CC2;
|
||||
case TIM_CHANNEL_3:
|
||||
return TIM_DMA_ID_CC3;
|
||||
case TIM_CHANNEL_4:
|
||||
return TIM_DMA_ID_CC4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "drivers/pwm_output.h"
|
||||
#include "drivers/max7456.h"
|
||||
#include "drivers/sound_beeper.h"
|
||||
#include "drivers/light_ws2811strip.h"
|
||||
|
||||
#include "fc/config.h"
|
||||
#include "fc/rc_controls.h"
|
||||
|
@ -239,6 +240,26 @@ void resetSensorAlignment(sensorAlignmentConfig_t *sensorAlignmentConfig)
|
|||
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
|
||||
void resetServoConfig(servoConfig_t *servoConfig)
|
||||
{
|
||||
|
@ -598,6 +619,10 @@ void createDefaultConfig(master_t *config)
|
|||
#endif
|
||||
resetFlight3DConfig(&config->flight3DConfig);
|
||||
|
||||
#ifdef LED_STRIP
|
||||
resetLedStripConfig(&config->ledStripConfig);
|
||||
#endif
|
||||
|
||||
#ifdef GPS
|
||||
// gps/nav stuff
|
||||
config->gpsConfig.provider = GPS_NMEA;
|
||||
|
@ -667,14 +692,6 @@ void createDefaultConfig(master_t *config)
|
|||
config->customMotorMixer[i].throttle = 0.0f;
|
||||
}
|
||||
|
||||
#ifdef LED_STRIP
|
||||
applyDefaultColors(config->colors);
|
||||
applyDefaultLedStripConfig(config->ledConfigs);
|
||||
applyDefaultModeColors(config->modeColors);
|
||||
applyDefaultSpecialColors(&(config->specialColors));
|
||||
config->ledstrip_visual_beeper = 0;
|
||||
#endif
|
||||
|
||||
#ifdef VTX
|
||||
config->vtx_band = 4; //Fatshark/Airwaves
|
||||
config->vtx_channel = 1; //CH1
|
||||
|
|
|
@ -930,7 +930,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
|
|||
#ifdef LED_STRIP
|
||||
case MSP_LED_COLORS:
|
||||
for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
|
||||
hsvColor_t *color = &masterConfig.colors[i];
|
||||
hsvColor_t *color = &masterConfig.ledStripConfig.colors[i];
|
||||
sbufWriteU16(dst, color->h);
|
||||
sbufWriteU8(dst, color->s);
|
||||
sbufWriteU8(dst, color->v);
|
||||
|
@ -939,7 +939,7 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
|
|||
|
||||
case MSP_LED_STRIP_CONFIG:
|
||||
for (i = 0; i < LED_MAX_STRIP_LENGTH; i++) {
|
||||
ledConfig_t *ledConfig = &masterConfig.ledConfigs[i];
|
||||
ledConfig_t *ledConfig = &masterConfig.ledStripConfig.ledConfigs[i];
|
||||
sbufWriteU32(dst, *ledConfig);
|
||||
}
|
||||
break;
|
||||
|
@ -949,15 +949,20 @@ static bool mspFcProcessOutCommand(uint8_t cmdMSP, sbuf_t *dst, mspPostProcessFn
|
|||
for (int j = 0; j < LED_DIRECTION_COUNT; j++) {
|
||||
sbufWriteU8(dst, i);
|
||||
sbufWriteU8(dst, j);
|
||||
sbufWriteU8(dst, masterConfig.modeColors[i].color[j]);
|
||||
sbufWriteU8(dst, masterConfig.ledStripConfig.modeColors[i].color[j]);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) {
|
||||
sbufWriteU8(dst, LED_MODE_COUNT);
|
||||
sbufWriteU8(dst, j);
|
||||
sbufWriteU8(dst, masterConfig.specialColors.color[j]);
|
||||
sbufWriteU8(dst, masterConfig.ledStripConfig.specialColors.color[j]);
|
||||
}
|
||||
|
||||
sbufWriteU8(dst, LED_AUX_CHANNEL);
|
||||
sbufWriteU8(dst, 0);
|
||||
sbufWriteU8(dst, masterConfig.ledStripConfig.ledstrip_aux_channel);
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -1649,7 +1654,7 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
|
|||
#ifdef LED_STRIP
|
||||
case MSP_SET_LED_COLORS:
|
||||
for (i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
|
||||
hsvColor_t *color = &masterConfig.colors[i];
|
||||
hsvColor_t *color = &masterConfig.ledStripConfig.colors[i];
|
||||
color->h = sbufReadU16(src);
|
||||
color->s = sbufReadU8(src);
|
||||
color->v = sbufReadU8(src);
|
||||
|
@ -1663,7 +1668,7 @@ static mspResult_e mspFcProcessInCommand(uint8_t cmdMSP, sbuf_t *src)
|
|||
return MSP_RESULT_ERROR;
|
||||
break;
|
||||
}
|
||||
ledConfig_t *ledConfig = &masterConfig.ledConfigs[i];
|
||||
ledConfig_t *ledConfig = &masterConfig.ledStripConfig.ledConfigs[i];
|
||||
*ledConfig = sbufReadU32(src);
|
||||
reevaluateLedConfig();
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ PG_REGISTER_WITH_RESET_FN(specialColorIndexes_t, specialColors, PG_SPECIAL_COLOR
|
|||
|
||||
static bool ledStripInitialised = false;
|
||||
static bool ledStripEnabled = true;
|
||||
static ledStripConfig_t * currentLedStripConfig;
|
||||
|
||||
static void ledStripDisable(void);
|
||||
|
||||
|
@ -168,6 +169,7 @@ static const specialColorIndexes_t defaultSpecialColors[] = {
|
|||
};
|
||||
|
||||
static int scaledThrottle;
|
||||
static int scaledAux;
|
||||
|
||||
static void updateLedRingCounts(void);
|
||||
|
||||
|
@ -177,7 +179,7 @@ STATIC_UNIT_TESTED void determineLedStripDimensions(void)
|
|||
int maxY = 0;
|
||||
|
||||
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
|
||||
maxX = MAX(ledGetX(ledConfig), maxX);
|
||||
maxY = MAX(ledGetY(ledConfig), maxY);
|
||||
|
@ -199,7 +201,7 @@ STATIC_UNIT_TESTED void updateLedCount(void)
|
|||
int count = 0, countRing = 0, countScanner= 0;
|
||||
|
||||
for (int ledIndex = 0; ledIndex < LED_MAX_STRIP_LENGTH; ledIndex++) {
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
|
||||
if (!(*ledConfig))
|
||||
break;
|
||||
|
@ -229,7 +231,7 @@ void reevaluateLedConfig(void)
|
|||
// get specialColor by index
|
||||
static hsvColor_t* getSC(ledSpecialColorIds_e index)
|
||||
{
|
||||
return &masterConfig.colors[masterConfig.specialColors.color[index]];
|
||||
return ¤tLedStripConfig->colors[currentLedStripConfig->specialColors.color[index]];
|
||||
}
|
||||
|
||||
static const char directionCodes[LED_DIRECTION_COUNT] = { 'N', 'E', 'S', 'W', 'U', 'D' };
|
||||
|
@ -251,9 +253,9 @@ bool parseLedStripConfig(int ledIndex, const char *config)
|
|||
RING_COLORS,
|
||||
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 = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
memset(ledConfig, 0, sizeof(ledConfig_t));
|
||||
|
||||
int x = 0, y = 0, color = 0; // initialize to prevent warnings
|
||||
|
@ -372,7 +374,7 @@ typedef enum {
|
|||
|
||||
static quadrant_e getLedQuadrant(const int ledIndex)
|
||||
{
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
|
||||
int x = ledGetX(ledConfig);
|
||||
int y = ledGetY(ledConfig);
|
||||
|
@ -414,7 +416,7 @@ static const struct {
|
|||
|
||||
static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIndexes_t *modeColors)
|
||||
{
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
|
||||
quadrant_e quad = getLedQuadrant(ledIndex);
|
||||
for (unsigned i = 0; i < ARRAYLEN(directionQuadrantMap); i++) {
|
||||
|
@ -422,7 +424,7 @@ static hsvColor_t* getDirectionalModeColor(const int ledIndex, const modeColorIn
|
|||
quadrant_e quadMask = directionQuadrantMap[i].quadrantMask;
|
||||
|
||||
if (ledGetDirectionBit(ledConfig, dir) && (quad & quadMask))
|
||||
return &masterConfig.colors[modeColors->color[dir]];
|
||||
return ¤tLedStripConfig->colors[modeColors->color[dir]];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -448,7 +450,7 @@ static const struct {
|
|||
static void applyLedFixedLayers()
|
||||
{
|
||||
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
hsvColor_t color = *getSC(LED_SCOLOR_BACKGROUND);
|
||||
|
||||
int fn = ledGetFunction(ledConfig);
|
||||
|
@ -456,13 +458,13 @@ static void applyLedFixedLayers()
|
|||
|
||||
switch (fn) {
|
||||
case LED_FUNCTION_COLOR:
|
||||
color = masterConfig.colors[ledGetColor(ledConfig)];
|
||||
color = currentLedStripConfig->colors[ledGetColor(ledConfig)];
|
||||
break;
|
||||
|
||||
case LED_FUNCTION_FLIGHT_MODE:
|
||||
for (unsigned i = 0; i < ARRAYLEN(flightModeToLed); i++)
|
||||
if (!flightModeToLed[i].flightMode || FLIGHT_MODE(flightModeToLed[i].flightMode)) {
|
||||
hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, &masterConfig.modeColors[flightModeToLed[i].ledMode]);
|
||||
hsvColor_t *directionalColor = getDirectionalModeColor(ledIndex, ¤tLedStripConfig->modeColors[flightModeToLed[i].ledMode]);
|
||||
if (directionalColor) {
|
||||
color = *directionalColor;
|
||||
}
|
||||
|
@ -490,7 +492,7 @@ static void applyLedFixedLayers()
|
|||
}
|
||||
|
||||
if (ledGetOverlayBit(ledConfig, LED_OVERLAY_THROTTLE)) {
|
||||
hOffset += ((scaledThrottle - 10) * 4) / 3;
|
||||
hOffset += scaledAux;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
if ((*ledConfig & mask) == mask)
|
||||
setLedHsv(ledIndex, color);
|
||||
}
|
||||
|
@ -699,7 +701,7 @@ static void applyLedIndicatorLayer(bool updateNow, uint32_t *timer)
|
|||
}
|
||||
|
||||
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
if (ledGetOverlayBit(ledConfig, LED_OVERLAY_INDICATOR)) {
|
||||
if (getLedQuadrant(ledIndex) & quadrants)
|
||||
setLedHsv(ledIndex, flashColor);
|
||||
|
@ -740,7 +742,7 @@ static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer)
|
|||
}
|
||||
|
||||
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
if (ledGetFunction(ledConfig) == LED_FUNCTION_THRUST_RING) {
|
||||
|
||||
bool applyColor;
|
||||
|
@ -751,7 +753,7 @@ static void applyLedThrustRingLayer(bool updateNow, uint32_t *timer)
|
|||
}
|
||||
|
||||
if (applyColor) {
|
||||
const hsvColor_t *ringColor = &masterConfig.colors[ledGetColor(ledConfig)];
|
||||
const hsvColor_t *ringColor = ¤tLedStripConfig->colors[ledGetColor(ledConfig)];
|
||||
setLedHsv(ledIndex, ringColor);
|
||||
}
|
||||
|
||||
|
@ -867,7 +869,7 @@ static void applyLedAnimationLayer(bool updateNow, uint32_t *timer)
|
|||
int nextRow = (frameCounter + 1 < animationFrames) ? frameCounter + 1 : 0;
|
||||
|
||||
for (int ledIndex = 0; ledIndex < ledCounts.count; ledIndex++) {
|
||||
const ledConfig_t *ledConfig = &masterConfig.ledConfigs[ledIndex];
|
||||
const ledConfig_t *ledConfig = ¤tLedStripConfig->ledConfigs[ledIndex];
|
||||
|
||||
if (ledGetY(ledConfig) == previousRow) {
|
||||
setLedHsv(ledIndex, getSC(LED_SCOLOR_ANIMATION));
|
||||
|
@ -929,7 +931,7 @@ void ledStripUpdate(uint32_t currentTime)
|
|||
return;
|
||||
}
|
||||
|
||||
if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(masterConfig.ledstrip_visual_beeper && isBeeperOn())) {
|
||||
if (IS_RC_MODE_ACTIVE(BOXLEDLOW) && !(currentLedStripConfig->ledstrip_visual_beeper && isBeeperOn())) {
|
||||
if (ledStripEnabled) {
|
||||
ledStripDisable();
|
||||
ledStripEnabled = false;
|
||||
|
@ -960,6 +962,7 @@ void ledStripUpdate(uint32_t currentTime)
|
|||
// apply all layers; triggered timed functions has to update timers
|
||||
|
||||
scaledThrottle = ARMING_FLAG(ARMED) ? scaleRange(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX, 10, 100) : 10;
|
||||
scaledAux = scaleRange(rcData[currentLedStripConfig->ledstrip_aux_channel], PWM_RANGE_MIN, PWM_RANGE_MAX, 0, HSV_HUE_MAX + 1);
|
||||
|
||||
applyLedFixedLayers();
|
||||
|
||||
|
@ -975,7 +978,7 @@ bool parseColor(int index, const char *colorConfig)
|
|||
{
|
||||
const char *remainingCharacters = colorConfig;
|
||||
|
||||
hsvColor_t *color = &masterConfig.colors[index];
|
||||
hsvColor_t *color = ¤tLedStripConfig->colors[index];
|
||||
|
||||
bool result = true;
|
||||
static const uint16_t hsv_limit[HSV_COLOR_COMPONENT_COUNT] = {
|
||||
|
@ -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(modeColorIndex < 0 || modeColorIndex >= LED_DIRECTION_COUNT)
|
||||
return false;
|
||||
masterConfig.modeColors[modeIndex].color[modeColorIndex] = colorIndex;
|
||||
currentLedStripConfig->modeColors[modeIndex].color[modeColorIndex] = colorIndex;
|
||||
} else if (modeIndex == LED_SPECIAL) {
|
||||
if (modeColorIndex < 0 || modeColorIndex >= LED_SPECIAL_COLOR_COUNT)
|
||||
return false;
|
||||
masterConfig.specialColors.color[modeColorIndex] = colorIndex;
|
||||
currentLedStripConfig->specialColors.color[modeColorIndex] = colorIndex;
|
||||
} else if (modeIndex == LED_AUX_CHANNEL) {
|
||||
if (modeColorIndex < 0 || modeColorIndex >= 1)
|
||||
return false;
|
||||
currentLedStripConfig->ledstrip_aux_channel = colorIndex;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -1090,21 +1097,26 @@ void applyDefaultSpecialColors(specialColorIndexes_t *specialColors)
|
|||
memcpy_fn(specialColors, &defaultSpecialColors, sizeof(defaultSpecialColors));
|
||||
}
|
||||
|
||||
void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, modeColorIndexes_t *modeColorsToUse, specialColorIndexes_t *specialColorsToUse)
|
||||
void ledStripInit(ledStripConfig_t *ledStripConfig)
|
||||
{
|
||||
ledConfigs = ledConfigsToUse;
|
||||
colors = colorsToUse;
|
||||
modeColors = modeColorsToUse;
|
||||
specialColors = *specialColorsToUse;
|
||||
currentLedStripConfig = ledStripConfig;
|
||||
|
||||
ledConfigs = currentLedStripConfig->ledConfigs;
|
||||
colors = currentLedStripConfig->colors;
|
||||
modeColors = currentLedStripConfig->modeColors;
|
||||
specialColors = currentLedStripConfig->specialColors;
|
||||
ledStripInitialised = false;
|
||||
}
|
||||
|
||||
void ledStripEnable(void)
|
||||
{
|
||||
if (currentLedStripConfig == NULL) {
|
||||
return;
|
||||
}
|
||||
reevaluateLedConfig();
|
||||
ledStripInitialised = true;
|
||||
|
||||
ws2811LedStripInit();
|
||||
ws2811LedStripInit(currentLedStripConfig->ioTag);
|
||||
}
|
||||
|
||||
static void ledStripDisable(void)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "common/color.h"
|
||||
#include "drivers/io_types.h"
|
||||
|
||||
#define LED_MAX_STRIP_LENGTH 32
|
||||
#define LED_CONFIGURABLE_COLOR_COUNT 16
|
||||
|
@ -75,7 +76,8 @@ typedef enum {
|
|||
LED_MODE_ANGLE,
|
||||
LED_MODE_MAG,
|
||||
LED_MODE_BARO,
|
||||
LED_SPECIAL
|
||||
LED_SPECIAL,
|
||||
LED_AUX_CHANNEL
|
||||
} ledModeIndex_e;
|
||||
|
||||
typedef enum {
|
||||
|
@ -134,6 +136,15 @@ typedef struct ledCounts_s {
|
|||
uint8_t ringSeqLen;
|
||||
} ledCounts_t;
|
||||
|
||||
typedef struct ledStripConfig_s {
|
||||
ledConfig_t ledConfigs[LED_MAX_STRIP_LENGTH];
|
||||
hsvColor_t colors[LED_CONFIGURABLE_COLOR_COUNT];
|
||||
modeColorIndexes_t modeColors[LED_MODE_COUNT];
|
||||
specialColorIndexes_t specialColors;
|
||||
uint8_t ledstrip_visual_beeper; // suppress LEDLOW mode if beeper is on
|
||||
rc_alias_e ledstrip_aux_channel;
|
||||
ioTag_t ioTag;
|
||||
} ledStripConfig_t;
|
||||
|
||||
ledConfig_t *ledConfigs;
|
||||
hsvColor_t *colors;
|
||||
|
@ -165,7 +176,7 @@ bool parseLedStripConfig(int ledIndex, const char *config);
|
|||
void generateLedConfig(ledConfig_t *ledConfig, char *ledConfigBuffer, size_t bufferSize);
|
||||
void reevaluateLedConfig(void);
|
||||
|
||||
void ledStripInit(ledConfig_t *ledConfigsToUse, hsvColor_t *colorsToUse, modeColorIndexes_t *modeColorsToUse, specialColorIndexes_t *specialColorsToUse);
|
||||
void ledStripInit(ledStripConfig_t *ledStripConfig);
|
||||
void ledStripEnable(void);
|
||||
void ledStripUpdate(uint32_t currentTime);
|
||||
|
||||
|
|
|
@ -936,7 +936,7 @@ const clivalue_t valueTable[] = {
|
|||
{ "magzero_z", VAR_INT16 | MASTER_VALUE, &masterConfig.magZero.raw[Z], .config.minmax = { -32768, 32767 } },
|
||||
#endif
|
||||
#ifdef LED_STRIP
|
||||
{ "ledstrip_visual_beeper", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.ledstrip_visual_beeper, .config.lookup = { TABLE_OFF_ON } },
|
||||
{ "ledstrip_visual_beeper", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, &masterConfig.ledStripConfig.ledstrip_visual_beeper, .config.lookup = { TABLE_OFF_ON } },
|
||||
#endif
|
||||
#ifdef USE_RTC6705
|
||||
{ "vtx_channel", VAR_UINT8 | MASTER_VALUE, &masterConfig.vtx_channel, .config.minmax = { 0, 39 } },
|
||||
|
@ -1707,8 +1707,8 @@ static void printLed(uint8_t dumpMask, master_t *defaultConfig)
|
|||
char ledConfigBuffer[20];
|
||||
char ledConfigDefaultBuffer[20];
|
||||
for (uint32_t i = 0; i < LED_MAX_STRIP_LENGTH; i++) {
|
||||
ledConfig = masterConfig.ledConfigs[i];
|
||||
ledConfigDefault = defaultConfig->ledConfigs[i];
|
||||
ledConfig = masterConfig.ledStripConfig.ledConfigs[i];
|
||||
ledConfigDefault = defaultConfig->ledStripConfig.ledConfigs[i];
|
||||
equalsDefault = ledConfig == ledConfigDefault;
|
||||
generateLedConfig(&ledConfig, ledConfigBuffer, sizeof(ledConfigBuffer));
|
||||
generateLedConfig(&ledConfigDefault, ledConfigDefaultBuffer, sizeof(ledConfigDefaultBuffer));
|
||||
|
@ -1745,8 +1745,8 @@ static void printColor(uint8_t dumpMask, master_t *defaultConfig)
|
|||
hsvColor_t *colorDefault;
|
||||
bool equalsDefault;
|
||||
for (uint32_t i = 0; i < LED_CONFIGURABLE_COLOR_COUNT; i++) {
|
||||
color = &masterConfig.colors[i];
|
||||
colorDefault = &defaultConfig->colors[i];
|
||||
color = &masterConfig.ledStripConfig.colors[i];
|
||||
colorDefault = &defaultConfig->ledStripConfig.colors[i];
|
||||
equalsDefault = color->h == colorDefault->h
|
||||
&& color->s == colorDefault->s
|
||||
&& color->v == colorDefault->v;
|
||||
|
@ -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 j = 0; j < LED_DIRECTION_COUNT; j++) {
|
||||
int colorIndex = masterConfig.modeColors[i].color[j];
|
||||
int colorIndexDefault = defaultConfig->modeColors[i].color[j];
|
||||
int colorIndex = masterConfig.ledStripConfig.modeColors[i].color[j];
|
||||
int colorIndexDefault = defaultConfig->ledStripConfig.modeColors[i].color[j];
|
||||
const char *format = "mode_color %u %u %u\r\n";
|
||||
cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndexDefault);
|
||||
cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, i, j, colorIndex);
|
||||
}
|
||||
}
|
||||
|
||||
const char *format = "mode_color %u %u %u\r\n";
|
||||
for (uint32_t j = 0; j < LED_SPECIAL_COLOR_COUNT; j++) {
|
||||
int colorIndex = masterConfig.specialColors.color[j];
|
||||
int colorIndexDefault = defaultConfig->specialColors.color[j];
|
||||
const char *format = "mode_color %u %u %u\r\n";
|
||||
int colorIndex = masterConfig.ledStripConfig.specialColors.color[j];
|
||||
int colorIndexDefault = defaultConfig->ledStripConfig.specialColors.color[j];
|
||||
cliDefaultPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndexDefault);
|
||||
cliDumpPrintf(dumpMask, colorIndex == colorIndexDefault, format, LED_SPECIAL, j, colorIndex);
|
||||
}
|
||||
|
||||
int ledStripAuxChannel = masterConfig.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)
|
||||
|
@ -2997,12 +3002,18 @@ static void cliEscPassthrough(char *cmdline)
|
|||
break;
|
||||
case 1:
|
||||
index = atoi(pch);
|
||||
if ((index >= 0) && (index < USABLE_TIMER_CHANNEL_COUNT)) {
|
||||
printf("passthru at pwm output %d enabled\r\n", index);
|
||||
if(mode == 2 && index == 255)
|
||||
{
|
||||
printf("passthru on all pwm outputs enabled\r\n");
|
||||
}
|
||||
else {
|
||||
printf("invalid pwm output, valid range: 1 to %d\r\n", USABLE_TIMER_CHANNEL_COUNT);
|
||||
return;
|
||||
else{
|
||||
if ((index >= 0) && (index < USABLE_TIMER_CHANNEL_COUNT)) {
|
||||
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;
|
||||
}
|
||||
|
@ -3610,7 +3621,8 @@ static void cliVersion(char *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,
|
||||
FC_VERSION_STRING,
|
||||
buildDate,
|
||||
|
@ -3739,19 +3751,22 @@ typedef struct {
|
|||
|
||||
const cliResourceValue_t resourceTable[] = {
|
||||
#ifdef BEEPER
|
||||
{ OWNER_BEEPER, &masterConfig.beeperConfig.ioTag, 0 },
|
||||
{ OWNER_BEEPER, &masterConfig.beeperConfig.ioTag, 0 },
|
||||
#endif
|
||||
{ OWNER_MOTOR, &masterConfig.motorConfig.ioTags[0], MAX_SUPPORTED_MOTORS },
|
||||
{ OWNER_MOTOR, &masterConfig.motorConfig.ioTags[0], MAX_SUPPORTED_MOTORS },
|
||||
#ifdef USE_SERVOS
|
||||
{ OWNER_SERVO, &masterConfig.servoConfig.ioTags[0], MAX_SUPPORTED_SERVOS },
|
||||
{ OWNER_SERVO, &masterConfig.servoConfig.ioTags[0], MAX_SUPPORTED_SERVOS },
|
||||
#endif
|
||||
#ifndef SKIP_RX_PWM_PPM
|
||||
{ OWNER_PPMINPUT, &masterConfig.ppmConfig.ioTag, 0 },
|
||||
{ OWNER_PWMINPUT, &masterConfig.pwmConfig.ioTags[0], PWM_INPUT_PORT_COUNT },
|
||||
{ OWNER_PPMINPUT, &masterConfig.ppmConfig.ioTag, 0 },
|
||||
{ OWNER_PWMINPUT, &masterConfig.pwmConfig.ioTags[0], PWM_INPUT_PORT_COUNT },
|
||||
#endif
|
||||
#ifdef SONAR
|
||||
{ OWNER_SONAR_TRIGGER, &masterConfig.sonarConfig.triggerTag, 0 },
|
||||
{ OWNER_SONAR_ECHO, &masterConfig.sonarConfig.echoTag, 0 },
|
||||
{ OWNER_SONAR_ECHO, &masterConfig.sonarConfig.echoTag, 0 },
|
||||
#endif
|
||||
#ifdef LED_STRIP
|
||||
{ OWNER_LED_STRIP, &masterConfig.ledStripConfig.ioTag, 0 },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -495,7 +495,7 @@ void init(void)
|
|||
#endif
|
||||
|
||||
#ifdef LED_STRIP
|
||||
ledStripInit(masterConfig.ledConfigs, masterConfig.colors, masterConfig.modeColors, &masterConfig.specialColors);
|
||||
ledStripInit(&masterConfig.ledStripConfig);
|
||||
|
||||
if (feature(FEATURE_LED_STRIP)) {
|
||||
ledStripEnable();
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
#define MSP_PROTOCOL_VERSION 0
|
||||
|
||||
#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
|
||||
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
#include "drivers/timer.h"
|
||||
|
||||
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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
|
||||
|
|
1
src/main/target/LUX_RACE/LUXV2_RACE.mk
Executable file
1
src/main/target/LUX_RACE/LUXV2_RACE.mk
Executable file
|
@ -0,0 +1 @@
|
|||
# LUXR_RACE is new version
|
|
@ -21,18 +21,21 @@
|
|||
#include "drivers/io.h"
|
||||
|
||||
#include "drivers/timer.h"
|
||||
#include "drivers/dma.h"
|
||||
|
||||
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
|
||||
{ TIM3, IO_TAG(PC6), TIM_Channel_1, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2 }, // PWM2 - PC6
|
||||
{ TIM3, IO_TAG(PC7), TIM_Channel_2, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2 }, // PWM3 - PC7
|
||||
{ TIM3, IO_TAG(PC8), TIM_Channel_3, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2 }, // PMW4 - PC8
|
||||
{ TIM3, IO_TAG(PC9), TIM_Channel_4, TIM3_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_2 }, // PWM5 - PC9
|
||||
{ TIM2, IO_TAG(PA0), TIM_Channel_1, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM6 - PA0
|
||||
{ TIM2, IO_TAG(PA1), TIM_Channel_2, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM7 - PA1
|
||||
{ TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM8 - PA2
|
||||
{ TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM9 - PA3
|
||||
{ TIM15, IO_TAG(PB14), TIM_Channel_1, TIM1_BRK_TIM15_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM10 - PB14
|
||||
{ TIM15, IO_TAG(PB15), TIM_Channel_2, TIM1_BRK_TIM15_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1 }, // PWM11 - PB15
|
||||
{ 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, DMA1_Channel6, DMA1_CH6_HANDLER }, // PWM2 - PC6
|
||||
{ TIM8, IO_TAG(PC7), TIM_Channel_2, TIM8_CC_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_4, DMA2_Channel5, DMA2_CH5_HANDLER }, // PWM3 - PC7
|
||||
{ TIM8, IO_TAG(PC8), TIM_Channel_3, TIM8_CC_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_4, DMA2_Channel1, DMA2_CH1_HANDLER }, // PMW4 - PC8
|
||||
{ TIM8, IO_TAG(PC9), TIM_Channel_4, TIM8_CC_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_4, DMA2_Channel2, DMA2_CH2_HANDLER }, // PWM5 - PC9
|
||||
#ifndef LUXV2_RACE
|
||||
{ TIM2, IO_TAG(PA0), TIM_Channel_1, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM6 - PA0
|
||||
{ TIM2, IO_TAG(PA1), TIM_Channel_2, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM7 - PA1
|
||||
{ TIM2, IO_TAG(PA2), TIM_Channel_3, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM8 - PA2
|
||||
{ TIM2, IO_TAG(PA3), TIM_Channel_4, TIM2_IRQn, TIM_USE_MOTOR, 1, GPIO_AF_1, NULL, 0 }, // PWM9 - PA3
|
||||
{ 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
|
||||
};
|
||||
|
||||
|
|
|
@ -17,16 +17,26 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#ifdef LUXV2_RACE
|
||||
#define TARGET_BOARD_IDENTIFIER "LUXR"
|
||||
#else
|
||||
#define TARGET_BOARD_IDENTIFIER "LUX"
|
||||
#endif
|
||||
#define BOARD_HAS_VOLTAGE_DIVIDER
|
||||
|
||||
#define CONFIG_FASTLOOP_PREFERRED_ACC ACC_DEFAULT
|
||||
|
||||
#define LED0 PC15
|
||||
#define LED1 PC14
|
||||
#ifndef LUXV2_RACE
|
||||
#define LED2 PC13
|
||||
#endif
|
||||
|
||||
#ifdef LUXV2_RACE
|
||||
#define BEEPER PB9
|
||||
#else
|
||||
#define BEEPER PB13
|
||||
#endif
|
||||
#define BEEPER_INVERTED
|
||||
|
||||
// MPU6500 interrupt
|
||||
|
@ -36,26 +46,72 @@
|
|||
#define USE_MPU_DATA_READY_SIGNAL
|
||||
#define ENSURE_MPU_DATA_READY_IS_LOW
|
||||
|
||||
#define USE_DSHOT
|
||||
|
||||
#define USE_SPI
|
||||
#define USE_SPI_DEVICE_1
|
||||
#ifdef LUXV2_RACE
|
||||
#define USE_SPI_DEVICE_2
|
||||
#endif
|
||||
|
||||
#define SPI1_SCK_PIN PB3
|
||||
#define SPI1_MISO_PIN PB4
|
||||
#define SPI1_MOSI_PIN PB5
|
||||
//#ifndef LUXV2_RACE
|
||||
#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_SPI_INSTANCE SPI1
|
||||
|
||||
#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_SPI_MPU6500
|
||||
#define GYRO_MPU6500_ALIGN CW270_DEG
|
||||
#define GYRO_MPU6500_ALIGN CW270_DEG
|
||||
#endif
|
||||
|
||||
#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_SPI_MPU6500
|
||||
#define ACC_MPU6500_ALIGN CW270_DEG
|
||||
#define ACC_MPU6500_ALIGN CW270_DEG
|
||||
#endif
|
||||
|
||||
#define USB_IO
|
||||
|
||||
|
@ -63,7 +119,13 @@
|
|||
#define USE_UART1
|
||||
#define USE_UART2
|
||||
#define USE_UART3
|
||||
#ifdef LUXV2_RACE
|
||||
#define USE_UART4
|
||||
#define USE_UART5
|
||||
#define SERIAL_PORT_COUNT 6
|
||||
#else
|
||||
#define SERIAL_PORT_COUNT 4
|
||||
#endif
|
||||
|
||||
#define UART1_TX_PIN PC4
|
||||
#define UART1_RX_PIN PC5
|
||||
|
@ -74,8 +136,7 @@
|
|||
#define UART3_TX_PIN PB10
|
||||
#define UART3_RX_PIN PB11
|
||||
|
||||
#define USE_I2C
|
||||
#define I2C_DEVICE (I2CDEV_2)
|
||||
#undef USE_I2C
|
||||
|
||||
#define USE_ADC
|
||||
#define ADC_INSTANCE ADC1
|
||||
|
@ -95,6 +156,11 @@
|
|||
|
||||
#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
|
||||
// USART1, PC5
|
||||
#define BIND_PIN PC5
|
||||
|
@ -108,6 +174,10 @@
|
|||
#define TARGET_IO_PORTD (BIT(2))
|
||||
#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 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))
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
F3_TARGETS += $(TARGET)
|
||||
FEATURES = VCP
|
||||
FEATURES = VCP SDCARD
|
||||
|
||||
TARGET_SRC = \
|
||||
drivers/accgyro_mpu.c \
|
||||
drivers/accgyro_mpu6500.c \
|
||||
drivers/accgyro_spi_mpu6500.c \
|
||||
drivers/accgyro_mpu6500.c
|
||||
|
||||
drivers/accgyro_mpu6500.c \
|
||||
drivers/accgyro_spi_mpu6000.c
|
0
src/main/target/REVO/AIRBOTF4.mk
Normal file
0
src/main/target/REVO/AIRBOTF4.mk
Normal file
0
src/main/target/REVO/REVOLT.mk
Normal file
0
src/main/target/REVO/REVOLT.mk
Normal 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(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
|
||||
{ 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
|
||||
{ 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
|
||||
{ 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
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -17,43 +17,71 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#define TARGET_BOARD_IDENTIFIER "REVO"
|
||||
|
||||
#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"
|
||||
|
||||
#ifdef OPBL
|
||||
#define USBD_SERIALNUMBER_STRING "0x8020000"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define USE_DSHOT
|
||||
|
||||
#define LED0 PB5
|
||||
// Disable LED1, conflicts with AirbotF4/Flip32F4 beeper
|
||||
//#define LED1 PB4
|
||||
|
||||
// Disable LED1, conflicts with AirbotF4/Flip32F4/Revolt beeper
|
||||
#if defined(AIRBOTF4) || defined(REVOLT)
|
||||
#define BEEPER PB4
|
||||
#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 MPU6000_CS_PIN PA4
|
||||
#define MPU6000_SPI_INSTANCE SPI1
|
||||
|
||||
#define MPU6500_CS_PIN PA4
|
||||
#define MPU6500_SPI_INSTANCE SPI1
|
||||
|
||||
#define ACC
|
||||
#define USE_ACC_SPI_MPU6000
|
||||
#define GYRO_MPU6000_ALIGN CW270_DEG
|
||||
|
||||
#define USE_ACC_MPU6500
|
||||
#define USE_ACC_SPI_MPU6500
|
||||
#define ACC_MPU6500_ALIGN CW270_DEG
|
||||
|
||||
#define GYRO
|
||||
#define USE_GYRO_SPI_MPU6000
|
||||
#define ACC_MPU6000_ALIGN CW270_DEG
|
||||
|
||||
#define USE_GYRO_MPU6500
|
||||
#define USE_GYRO_SPI_MPU6500
|
||||
#define GYRO_MPU9250_ALIGN CW270_DEG
|
||||
|
||||
// MPU6000 interrupts
|
||||
#define USE_EXTI
|
||||
#define MPU_INT_EXTI PC4
|
||||
#define USE_MPU_DATA_READY_SIGNAL
|
||||
|
||||
#if !defined(AIRBOTF4) && !defined(REVOLT)
|
||||
#define MAG
|
||||
#define USE_MAG_HMC5883
|
||||
#define MAG_HMC5883_ALIGN CW90_DEG
|
||||
|
@ -67,6 +95,7 @@
|
|||
//#define PITOT
|
||||
//#define USE_PITOT_MS4525
|
||||
//#define MS4525_BUS I2C_DEVICE_EXT
|
||||
#endif
|
||||
|
||||
#define M25P16_CS_PIN PB3
|
||||
#define M25P16_SPI_INSTANCE SPI3
|
||||
|
@ -78,8 +107,8 @@
|
|||
#define VBUS_SENSING_PIN PC5
|
||||
|
||||
#define USE_UART1
|
||||
#define UART1_RX_PIN PA10
|
||||
#define UART1_TX_PIN PA9
|
||||
#define UART1_RX_PIN PA10
|
||||
#define UART1_TX_PIN PA9
|
||||
#define UART1_AHB1_PERIPHERALS RCC_AHB1Periph_DMA2
|
||||
|
||||
#define USE_UART3
|
||||
|
@ -106,7 +135,7 @@
|
|||
#define SPI3_MOSI_PIN PC12
|
||||
|
||||
#define USE_I2C
|
||||
#define I2C_DEVICE (I2CDEV_1)
|
||||
#define I2C_DEVICE (I2CDEV_1)
|
||||
|
||||
#define USE_ADC
|
||||
#define CURRENT_METER_ADC_PIN PC1
|
||||
|
@ -126,7 +155,7 @@
|
|||
#define WS2811_DMA_FLAG DMA_FLAG_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_FEATURES (FEATURE_BLACKBOX)
|
||||
|
@ -140,7 +169,12 @@
|
|||
#define TARGET_IO_PORTA 0xffff
|
||||
#define TARGET_IO_PORTB 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
|
||||
#endif
|
||||
|
||||
#define USED_TIMERS ( TIM_N(2) | TIM_N(3) | TIM_N(5) | TIM_N(12) | TIM_N(8) | TIM_N(9) )
|
||||
|
|
|
@ -3,6 +3,8 @@ FEATURES += VCP ONBOARDFLASH
|
|||
|
||||
TARGET_SRC = \
|
||||
drivers/accgyro_spi_mpu6000.c \
|
||||
drivers/accgyro_mpu6500.c \
|
||||
drivers/accgyro_spi_mpu6500.c \
|
||||
drivers/barometer_ms5611.c \
|
||||
drivers/compass_hmc5883l.c \
|
||||
io/cms.c \
|
||||
|
|
|
@ -625,8 +625,10 @@ void handleSmartPortTelemetry(void)
|
|||
#ifdef GPS
|
||||
case FSSP_DATAID_SPEED :
|
||||
if (sensors(SENSOR_GPS) && STATE(GPS_FIX)) {
|
||||
uint32_t tmpui = (GPS_speed * 36 + 36 / 2) / 100;
|
||||
smartPortSendPackage(id, tmpui); // given in 0.1 m/s, provide in KM/H
|
||||
//convert to knots: 1cm/s = 0.0194384449 knots
|
||||
//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;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "usbd_conf.h"
|
||||
#include "usb_regs.h"
|
||||
#include "platform.h"
|
||||
#include "build/version.h"
|
||||
|
||||
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
|
||||
* @{
|
||||
|
@ -57,7 +58,7 @@
|
|||
* @{
|
||||
*/
|
||||
#define USBD_LANGID_STRING 0x409
|
||||
#define USBD_MANUFACTURER_STRING "BetaFlight"
|
||||
#define USBD_MANUFACTURER_STRING FC_FIRMWARE_NAME
|
||||
|
||||
#ifdef USBD_PRODUCT_STRING
|
||||
#define USBD_PRODUCT_HS_STRING USBD_PRODUCT_STRING
|
||||
|
|
|
@ -16,11 +16,13 @@ REPLY_FRAME_ID = 0x32
|
|||
|
||||
-- Sequence number for next MSP/SPORT packet
|
||||
local sportMspSeq = 0
|
||||
local sportMspRemoteSeq = 0
|
||||
|
||||
local mspRxBuf = {}
|
||||
local mspRxIdx = 1
|
||||
local mspRxCRC = 0
|
||||
local mspStarted = false
|
||||
local mspLastReq = 0
|
||||
|
||||
-- Stats
|
||||
mspRequestsSent = 0
|
||||
|
@ -55,7 +57,8 @@ local function mspSendRequest(cmd)
|
|||
value = bit32.band(cmd,0xFF) -- MSP command
|
||||
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)
|
||||
end
|
||||
|
||||
|
@ -90,7 +93,7 @@ local function mspReceivedReply(payload)
|
|||
mspRxBuf = {}
|
||||
|
||||
mspRxSize = payload[idx]
|
||||
mspRxCRC = mspRxSize
|
||||
mspRxCRC = bit32.bxor(mspRxSize,mspLastReq)
|
||||
idx = idx + 1
|
||||
mspStarted = true
|
||||
|
||||
|
@ -100,7 +103,7 @@ local function mspReceivedReply(payload)
|
|||
mspOutOfOrder = mspOutOfOrder + 1
|
||||
return nil
|
||||
|
||||
elseif bit32.band(lastSeq+1,0x0F) ~= seq then
|
||||
elseif bit32.band(sportMspRemoteSeq + 1, 0x0F) ~= seq then
|
||||
mspOutOfOrder = mspOutOfOrder + 1
|
||||
mspStarted = false
|
||||
return nil
|
||||
|
@ -114,7 +117,7 @@ local function mspReceivedReply(payload)
|
|||
end
|
||||
|
||||
if idx > 6 then
|
||||
lastRxSeq = seq
|
||||
sportMspRemoteSeq = seq
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -122,6 +125,7 @@ local function mspReceivedReply(payload)
|
|||
if mspRxCRC ~= payload[idx] then
|
||||
mspStarted = false
|
||||
mspCRCErrors = mspCRCErrors + 1
|
||||
return nil
|
||||
end
|
||||
|
||||
mspRepliesReceived = mspRepliesReceived + 1
|
||||
|
@ -157,18 +161,14 @@ local function run(event)
|
|||
local now = getTime()
|
||||
|
||||
if event == EVT_MINUS_FIRST or event == EVT_ROT_LEFT or event == EVT_MINUS_REPT then
|
||||
requestsSent = 0
|
||||
repliesReceived = 0
|
||||
mspReceivedReply_cnt = 0
|
||||
mspReceivedReply_cnt1 = 0
|
||||
mspReceivedReply_cnt2 = 0
|
||||
mspReceivedReply_cnt3 = 0
|
||||
mspResetStats()
|
||||
end
|
||||
|
||||
lcd.clear()
|
||||
|
||||
lcd.drawText(41,1,"MSP/SPORT test script",INVERS)
|
||||
|
||||
-- do we have valid telemetry data?
|
||||
if getValue("rssi") > 0 then
|
||||
if getValue("RSSI") > 0 then
|
||||
|
||||
-- draw screen
|
||||
lcd.drawText(1,11,"Requests:",0)
|
||||
|
@ -178,19 +178,19 @@ local function run(event)
|
|||
lcd.drawNumber(60,21,mspRepliesReceived)
|
||||
|
||||
lcd.drawText(1,31,"PkRxed:",0)
|
||||
lcd.drawNumber(30,31,mspPkRxed)
|
||||
lcd.drawNumber(60,31,mspPkRxed)
|
||||
|
||||
lcd.drawText(1,41,"ErrorPk:",0)
|
||||
lcd.drawNumber(30,41,mspErrorPk)
|
||||
lcd.drawNumber(60,41,mspErrorPk)
|
||||
|
||||
lcd.drawText(71,31,"StartPk:",0)
|
||||
lcd.drawNumber(100,31,mspStartPk)
|
||||
lcd.drawText(91,31,"StartPk:",0)
|
||||
lcd.drawNumber(160,31,mspStartPk)
|
||||
|
||||
lcd.drawText(71,41,"OutOfOrder:",0)
|
||||
lcd.drawNumber(100,41,mspOutOfOrder)
|
||||
lcd.drawText(91,41,"OutOfOrder:",0)
|
||||
lcd.drawNumber(160,41,mspOutOfOrder)
|
||||
|
||||
lcd.drawText(1,51,"CRCErrors:",0)
|
||||
lcd.drawNumber(30,51,mspCRCErrors)
|
||||
lcd.drawNumber(60,51,mspCRCErrors)
|
||||
|
||||
-- last request is at least 2s old
|
||||
if lastReqTS + 200 <= now then
|
||||
|
@ -198,10 +198,10 @@ local function run(event)
|
|||
lastReqTS = now
|
||||
end
|
||||
else
|
||||
lcd.drawText(20,30,"No telemetry signal", XXLSIZE + BLINK)
|
||||
lcd.drawText(15,20,"No telemetry signal", BLINK + DBLSIZE)
|
||||
end
|
||||
|
||||
pollReply()
|
||||
mspPollReply()
|
||||
end
|
||||
|
||||
return {run=run}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue