1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-17 21:35:44 +03:00

Merge pull request #3039 from cleanflight/f7-transponder-ir (#5618)

CF/BF - Add support for IR Transponder on STM32F7 boards.
This commit is contained in:
Michael Keller 2018-04-06 03:44:18 +12:00 committed by GitHub
parent 337fbb2392
commit 75bafb7b71
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 275 additions and 14 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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

View file

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

View file

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

View file

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