mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-17 13:25:30 +03:00
CF/BF - Add support for IR Transponder on STM32F7 boards.
This commit is contained in:
parent
337fbb2392
commit
75bafb7b71
13 changed files with 275 additions and 14 deletions
|
@ -74,6 +74,7 @@ MCU_COMMON_SRC = \
|
|||
drivers/bus_spi_stdperiph.c \
|
||||
drivers/dma.c \
|
||||
drivers/light_ws2811strip_stdperiph.c \
|
||||
drivers/transponder_ir_io_stdperiph.c \
|
||||
drivers/pwm_output_dshot.c \
|
||||
drivers/serial_uart_init.c \
|
||||
drivers/serial_uart_stm32f30x.c \
|
||||
|
|
|
@ -172,6 +172,7 @@ MCU_COMMON_SRC = \
|
|||
drivers/dma_stm32f4xx.c \
|
||||
drivers/inverter.c \
|
||||
drivers/light_ws2811strip_stdperiph.c \
|
||||
drivers/transponder_ir_io_stdperiph.c \
|
||||
drivers/pwm_output_dshot.c \
|
||||
drivers/serial_uart_init.c \
|
||||
drivers/serial_uart_stm32f4xx.c \
|
||||
|
|
|
@ -166,6 +166,7 @@ MCU_COMMON_SRC = \
|
|||
drivers/bus_i2c_hal.c \
|
||||
drivers/dma_stm32f7xx.c \
|
||||
drivers/light_ws2811strip_hal.c \
|
||||
drivers/transponder_ir_io_hal.c \
|
||||
drivers/bus_spi_ll.c \
|
||||
drivers/pwm_output_dshot_hal.c \
|
||||
drivers/timer_hal.c \
|
||||
|
|
|
@ -47,7 +47,6 @@ COMMON_SRC = \
|
|||
drivers/stack_check.c \
|
||||
drivers/system.c \
|
||||
drivers/timer.c \
|
||||
drivers/transponder_ir.c \
|
||||
drivers/transponder_ir_arcitimer.c \
|
||||
drivers/transponder_ir_ilap.c \
|
||||
drivers/transponder_ir_erlt.c \
|
||||
|
@ -294,13 +293,15 @@ SIZE_OPTIMISED_SRC := $(SIZE_OPTIMISED_SRC) \
|
|||
drivers/inverter.c \
|
||||
drivers/light_ws2811strip.c \
|
||||
drivers/light_ws2811strip_hal.c \
|
||||
drivers/light_ws2811strip_stdperiph.c \
|
||||
drivers/serial_escserial.c \
|
||||
drivers/serial_pinconfig.c \
|
||||
drivers/serial_tcp.c \
|
||||
drivers/serial_uart_init.c \
|
||||
drivers/serial_uart_pinconfig.c \
|
||||
drivers/serial_usb_vcp.c \
|
||||
drivers/transponder_ir.c \
|
||||
drivers/transponder_ir_io_hal.c \
|
||||
drivers/transponder_ir_io_stdperiph.c \
|
||||
drivers/vtx_rtc6705_soft_spi.c \
|
||||
drivers/vtx_rtc6705.c \
|
||||
drivers/vtx_common.c \
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
uint8_t erlt[TRANSPONDER_DMA_BUFFER_SIZE_ERLT]; // 91-200
|
||||
} transponderIrDMABuffer_t;
|
||||
|
||||
#elif defined(STM32F4)
|
||||
#elif defined(STM32F4) || defined(STM32F7)
|
||||
|
||||
typedef union transponderIrDMABuffer_s {
|
||||
uint32_t arcitimer[TRANSPONDER_DMA_BUFFER_SIZE_ARCITIMER]; // 620
|
||||
|
@ -93,7 +93,7 @@ typedef struct transponder_s {
|
|||
uint16_t bitToggleOne;
|
||||
uint32_t dma_buffer_size;
|
||||
|
||||
#if defined(STM32F3) || defined(STM32F4)|| defined(UNIT_TEST)
|
||||
#if defined(STM32F3) || defined(STM32F4)|| defined(STM32F7) || defined(UNIT_TEST)
|
||||
transponderIrDMABuffer_t transponderIrDMABuffer;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "drivers/transponder_ir.h"
|
||||
#include "drivers/transponder_ir_arcitimer.h"
|
||||
|
||||
#if defined(STM32F3) || defined(STM32F4) || defined(UNIT_TEST)
|
||||
#if defined(STM32F3) || defined(STM32F4) || defined(STM32F7) || defined(UNIT_TEST)
|
||||
|
||||
extern const struct transponderVTable arcitimerTansponderVTable;
|
||||
static uint16_t dmaBufferOffset;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "drivers/transponder_ir.h"
|
||||
#include "drivers/transponder_ir_erlt.h"
|
||||
|
||||
#if defined(STM32F3) || defined(STM32F4) || defined(UNIT_TEST)
|
||||
#if defined(STM32F3) || defined(STM32F4) || defined(STM32F7) || defined(UNIT_TEST)
|
||||
|
||||
static uint16_t dmaBufferOffset;
|
||||
extern const struct transponderVTable erltTansponderVTable;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "drivers/transponder_ir.h"
|
||||
#include "drivers/transponder_ir_ilap.h"
|
||||
|
||||
#if defined(STM32F3) || defined(STM32F4) || defined(UNIT_TEST)
|
||||
#if defined(STM32F3) || defined(STM32F4) || defined(STM32F7) || defined(UNIT_TEST)
|
||||
|
||||
static uint16_t dmaBufferOffset;
|
||||
extern const struct transponderVTable ilapTansponderVTable;
|
||||
|
|
262
src/main/drivers/transponder_ir_io_hal.c
Normal file
262
src/main/drivers/transponder_ir_io_hal.c
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* This file is part of Cleanflight.
|
||||
*
|
||||
* Cleanflight is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Cleanflight is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#ifdef USE_TRANSPONDER
|
||||
|
||||
#include "dma.h"
|
||||
#include "drivers/nvic.h"
|
||||
#include "drivers/io.h"
|
||||
#include "rcc.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "transponder_ir.h"
|
||||
#include "drivers/transponder_ir_arcitimer.h"
|
||||
#include "drivers/transponder_ir_ilap.h"
|
||||
#include "drivers/transponder_ir_erlt.h"
|
||||
|
||||
volatile uint8_t transponderIrDataTransferInProgress = 0;
|
||||
|
||||
|
||||
static IO_t transponderIO = IO_NONE;
|
||||
static TIM_HandleTypeDef TimHandle;
|
||||
static uint16_t timerChannel = 0;
|
||||
|
||||
#if !defined(STM32F7)
|
||||
#error "Transponder (via HAL) not supported on this MCU."
|
||||
#endif
|
||||
|
||||
transponder_t transponder;
|
||||
bool transponderInitialised = false;
|
||||
|
||||
static void TRANSPONDER_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor)
|
||||
{
|
||||
HAL_DMA_IRQHandler(TimHandle.hdma[descriptor->userParam]);
|
||||
TIM_DMACmd(&TimHandle, timerChannel, DISABLE);
|
||||
transponderIrDataTransferInProgress = 0;
|
||||
}
|
||||
|
||||
void transponderIrHardwareInit(ioTag_t ioTag, transponder_t *transponder)
|
||||
{
|
||||
if (!ioTag) {
|
||||
return;
|
||||
}
|
||||
|
||||
const timerHardware_t *timerHardware = timerGetByTag(ioTag, TIM_USE_ANY);
|
||||
TIM_TypeDef *timer = timerHardware->tim;
|
||||
timerChannel = timerHardware->channel;
|
||||
|
||||
if (timerHardware->dmaRef == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Time base configuration */
|
||||
|
||||
TimHandle.Instance = timer;
|
||||
|
||||
uint16_t prescaler = timerGetPrescalerByDesiredMhz(timer, transponder->timer_hz);
|
||||
uint16_t period = timerGetPeriodByPrescaler(timer, prescaler, transponder->timer_carrier_hz);
|
||||
|
||||
transponder->bitToggleOne = period / 2;
|
||||
|
||||
TimHandle.Init.Prescaler = prescaler;
|
||||
TimHandle.Init.Period = period; // 800kHz
|
||||
TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
|
||||
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
|
||||
/* Initialization Error */
|
||||
return;
|
||||
}
|
||||
|
||||
/* IO configuration */
|
||||
|
||||
static DMA_HandleTypeDef hdma_tim;
|
||||
|
||||
transponderIO = IOGetByTag(ioTag);
|
||||
IOInit(transponderIO, OWNER_TRANSPONDER, 0);
|
||||
IOConfigGPIOAF(transponderIO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLDOWN), timerHardware->alternateFunction);
|
||||
|
||||
__DMA1_CLK_ENABLE();
|
||||
|
||||
/* Set the parameters to be configured */
|
||||
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;
|
||||
hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
|
||||
hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
|
||||
hdma_tim.Init.Mode = DMA_NORMAL;
|
||||
hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
|
||||
hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
|
||||
hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
|
||||
hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
|
||||
hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
|
||||
|
||||
/* Set hdma_tim instance */
|
||||
hdma_tim.Instance = timerHardware->dmaRef;
|
||||
|
||||
uint16_t dmaIndex = timerDmaIndex(timerChannel);
|
||||
|
||||
/* Link hdma_tim to hdma[x] (channelx) */
|
||||
__HAL_LINKDMA(&TimHandle, hdma[dmaIndex], hdma_tim);
|
||||
|
||||
dmaInit(timerHardware->dmaIrqHandler, OWNER_TRANSPONDER, 0);
|
||||
dmaSetHandler(timerHardware->dmaIrqHandler, TRANSPONDER_DMA_IRQHandler, NVIC_PRIO_TRANSPONDER_DMA, dmaIndex);
|
||||
|
||||
/* Initialize TIMx DMA handle */
|
||||
if (HAL_DMA_Init(TimHandle.hdma[dmaIndex]) != HAL_OK) {
|
||||
/* Initialization Error */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
RCC_ClockCmd(timerRCC(timer), ENABLE);
|
||||
|
||||
/* PWM1 Mode configuration: Channel1 */
|
||||
TIM_OC_InitTypeDef TIM_OCInitStructure;
|
||||
|
||||
TIM_OCInitStructure.OCMode = TIM_OCMODE_PWM1;
|
||||
TIM_OCInitStructure.OCIdleState = TIM_OCIDLESTATE_RESET;
|
||||
TIM_OCInitStructure.OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPOLARITY_LOW : TIM_OCPOLARITY_HIGH;
|
||||
TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;
|
||||
TIM_OCInitStructure.OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPOLARITY_LOW : TIM_OCNPOLARITY_HIGH;
|
||||
TIM_OCInitStructure.Pulse = 0;
|
||||
TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, timerChannel) != HAL_OK) {
|
||||
/* Configuration Error */
|
||||
return;
|
||||
}
|
||||
if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
|
||||
if (HAL_TIMEx_PWMN_Start(&TimHandle, timerChannel) != HAL_OK) {
|
||||
/* Starting PWM generation Error */
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (HAL_TIM_PWM_Start(&TimHandle, timerChannel) != HAL_OK) {
|
||||
/* Starting PWM generation Error */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
transponderInitialised = true;
|
||||
}
|
||||
|
||||
bool transponderIrInit(const ioTag_t ioTag, const transponderProvider_e provider)
|
||||
{
|
||||
if (!ioTag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (provider) {
|
||||
case TRANSPONDER_ARCITIMER:
|
||||
transponderIrInitArcitimer(&transponder);
|
||||
break;
|
||||
case TRANSPONDER_ILAP:
|
||||
transponderIrInitIlap(&transponder);
|
||||
break;
|
||||
case TRANSPONDER_ERLT:
|
||||
transponderIrInitERLT(&transponder);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
transponderIrHardwareInit(ioTag, &transponder);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isTransponderIrReady(void)
|
||||
{
|
||||
return !transponderIrDataTransferInProgress;
|
||||
}
|
||||
|
||||
static uint16_t dmaBufferOffset;
|
||||
|
||||
void transponderIrWaitForTransmitComplete(void)
|
||||
{
|
||||
static uint32_t waitCounter = 0;
|
||||
|
||||
while (transponderIrDataTransferInProgress) {
|
||||
waitCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
void transponderIrUpdateData(const uint8_t* transponderData)
|
||||
{
|
||||
transponderIrWaitForTransmitComplete();
|
||||
transponder.vTable->updateTransponderDMABuffer(&transponder, transponderData);
|
||||
}
|
||||
|
||||
void transponderIrDMAEnable(transponder_t *transponder)
|
||||
{
|
||||
if (!transponderInitialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DMA_SetCurrDataCounter(&TimHandle, timerChannel, transponder->transponderIrDMABuffer.ilap, transponder->dma_buffer_size) != HAL_OK) {
|
||||
/* DMA set error */
|
||||
transponderIrDataTransferInProgress = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reset timer counter */
|
||||
__HAL_TIM_SET_COUNTER(&TimHandle, 0);
|
||||
/* Enable channel DMA requests */
|
||||
TIM_DMACmd(&TimHandle, timerChannel, ENABLE);
|
||||
}
|
||||
|
||||
void transponderIrDisable(void)
|
||||
{
|
||||
if (!transponderInitialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
TIM_DMACmd(&TimHandle, timerChannel, DISABLE);
|
||||
if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
|
||||
HAL_TIMEx_PWMN_Stop(&TimHandle, timerChannel);
|
||||
} else {
|
||||
HAL_TIM_PWM_Stop(&TimHandle, timerChannel);
|
||||
}
|
||||
|
||||
|
||||
IOInit(transponderIO, OWNER_TRANSPONDER, 0);
|
||||
|
||||
#ifdef TRANSPONDER_INVERTED
|
||||
IOHi(transponderIO);
|
||||
#else
|
||||
IOLo(transponderIO);
|
||||
#endif
|
||||
|
||||
IOConfigGPIOAF(transponderIO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLDOWN), timerHardware->alternateFunction);
|
||||
}
|
||||
|
||||
void transponderIrTransmit(void)
|
||||
{
|
||||
transponderIrWaitForTransmitComplete();
|
||||
|
||||
dmaBufferOffset = 0;
|
||||
|
||||
transponderIrDataTransferInProgress = 1;
|
||||
transponderIrDMAEnable(&transponder);
|
||||
}
|
||||
#endif
|
|
@ -5,6 +5,4 @@ TARGET_SRC = \
|
|||
drivers/accgyro/accgyro_spi_icm20689.c \
|
||||
drivers/barometer/barometer_bmp280.c \
|
||||
drivers/barometer/barometer_ms5611.c \
|
||||
drivers/max7456.c \
|
||||
drivers/transponder_ir.c \
|
||||
io/transponder_ir.c
|
||||
drivers/max7456.c
|
|
@ -10,7 +10,5 @@ TARGET_SRC = \
|
|||
drivers/compass/compass_hmc5883l.c \
|
||||
drivers/compass/compass_qmc5883l.c \
|
||||
drivers/max7456.c \
|
||||
drivers/transponder_ir.c \
|
||||
drivers/vtx_rtc6705.c \
|
||||
io/osd.c \
|
||||
io/transponder_ir.c \
|
||||
|
|
|
@ -199,8 +199,7 @@
|
|||
|
||||
#define USE_LED_STRIP
|
||||
|
||||
//TODO Implement transponder on F7
|
||||
//#define USE_TRANSPONDER
|
||||
#define USE_TRANSPONDER
|
||||
|
||||
#define ENABLE_BLACKBOX_LOGGING_ON_SDCARD_BY_DEFAULT
|
||||
//#define RX_CHANNELS_TAER
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue