diff --git a/make/mcu/STM32F3.mk b/make/mcu/STM32F3.mk index 50d9a2cbfb..c0d96caace 100644 --- a/make/mcu/STM32F3.mk +++ b/make/mcu/STM32F3.mk @@ -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 \ diff --git a/make/mcu/STM32F4.mk b/make/mcu/STM32F4.mk index cb09f1a6be..1bdd207046 100644 --- a/make/mcu/STM32F4.mk +++ b/make/mcu/STM32F4.mk @@ -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 \ diff --git a/make/mcu/STM32F7.mk b/make/mcu/STM32F7.mk index 3967906fd2..acdd7a6860 100644 --- a/make/mcu/STM32F7.mk +++ b/make/mcu/STM32F7.mk @@ -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 \ diff --git a/make/source.mk b/make/source.mk index 1922bb43ac..17ca7a4d99 100644 --- a/make/source.mk +++ b/make/source.mk @@ -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 \ diff --git a/src/main/drivers/transponder_ir.h b/src/main/drivers/transponder_ir.h index 49d75d6785..9ecd36af29 100644 --- a/src/main/drivers/transponder_ir.h +++ b/src/main/drivers/transponder_ir.h @@ -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 diff --git a/src/main/drivers/transponder_ir_arcitimer.c b/src/main/drivers/transponder_ir_arcitimer.c index e5b75eda98..df973d3750 100644 --- a/src/main/drivers/transponder_ir_arcitimer.c +++ b/src/main/drivers/transponder_ir_arcitimer.c @@ -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; diff --git a/src/main/drivers/transponder_ir_erlt.c b/src/main/drivers/transponder_ir_erlt.c index 5cb238b63a..330a61d2b3 100644 --- a/src/main/drivers/transponder_ir_erlt.c +++ b/src/main/drivers/transponder_ir_erlt.c @@ -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; diff --git a/src/main/drivers/transponder_ir_ilap.c b/src/main/drivers/transponder_ir_ilap.c index 4d110898ed..0ad2e71e37 100644 --- a/src/main/drivers/transponder_ir_ilap.c +++ b/src/main/drivers/transponder_ir_ilap.c @@ -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; diff --git a/src/main/drivers/transponder_ir_io_hal.c b/src/main/drivers/transponder_ir_io_hal.c new file mode 100644 index 0000000000..626b2bb8e2 --- /dev/null +++ b/src/main/drivers/transponder_ir_io_hal.c @@ -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 . + */ + +#include +#include +#include + +#include + +#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 diff --git a/src/main/drivers/transponder_ir.c b/src/main/drivers/transponder_ir_io_stdperiph.c similarity index 100% rename from src/main/drivers/transponder_ir.c rename to src/main/drivers/transponder_ir_io_stdperiph.c diff --git a/src/main/target/BEEROTORF4/target.mk b/src/main/target/BEEROTORF4/target.mk index a2f3a2352b..a54056c083 100644 --- a/src/main/target/BEEROTORF4/target.mk +++ b/src/main/target/BEEROTORF4/target.mk @@ -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 \ No newline at end of file diff --git a/src/main/target/SPRACINGF4NEO/target.mk b/src/main/target/SPRACINGF4NEO/target.mk index 94fafc7479..6568f56a5b 100644 --- a/src/main/target/SPRACINGF4NEO/target.mk +++ b/src/main/target/SPRACINGF4NEO/target.mk @@ -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 \ diff --git a/src/main/target/SPRACINGF7DUAL/target.h b/src/main/target/SPRACINGF7DUAL/target.h index e532c6bb7c..4fcfc80614 100644 --- a/src/main/target/SPRACINGF7DUAL/target.h +++ b/src/main/target/SPRACINGF7DUAL/target.h @@ -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