Remove unused typedefs for DMA stream/channel
[betaflight.git] / src / main / drivers / transponder_ir_io_hal.c
blob3b6e8b98232c03037be292c72a6a038e16517847
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <string.h>
25 #include "platform.h"
27 #ifdef USE_TRANSPONDER
29 #include "drivers/dma.h"
30 #include "drivers/dma_reqmap.h"
31 #include "drivers/io.h"
32 #include "drivers/nvic.h"
33 #include "drivers/rcc.h"
34 #include "drivers/timer.h"
35 #include "drivers/transponder_ir_arcitimer.h"
36 #include "drivers/transponder_ir_erlt.h"
37 #include "drivers/transponder_ir_ilap.h"
39 #include "transponder_ir.h"
41 volatile uint8_t transponderIrDataTransferInProgress = 0;
43 static IO_t transponderIO = IO_NONE;
44 static TIM_HandleTypeDef TimHandle;
45 static uint16_t timerChannel = 0;
46 static uint8_t output;
47 static uint8_t alternateFunction;
49 #if !(defined(STM32F7) || defined(STM32H7))
50 #error "Transponder (via HAL) not supported on this MCU."
51 #endif
53 #ifdef STM32H7
54 DMA_RAM transponder_t transponder;
55 #else
56 transponder_t transponder;
57 #endif
58 bool transponderInitialised = false;
60 static void TRANSPONDER_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor)
62 HAL_DMA_IRQHandler(TimHandle.hdma[descriptor->userParam]);
63 TIM_DMACmd(&TimHandle, timerChannel, DISABLE);
64 transponderIrDataTransferInProgress = 0;
67 void transponderIrHardwareInit(ioTag_t ioTag, transponder_t *transponder)
69 if (!ioTag) {
70 return;
73 const timerHardware_t *timerHardware = timerAllocate(ioTag, OWNER_TRANSPONDER, 0);
74 TIM_TypeDef *timer = timerHardware->tim;
75 timerChannel = timerHardware->channel;
76 output = timerHardware->output;
77 alternateFunction = timerHardware->alternateFunction;
79 #if defined(USE_DMA_SPEC)
80 const dmaChannelSpec_t *dmaSpec = dmaGetChannelSpecByTimer(timerHardware);
82 if (dmaSpec == NULL) {
83 return;
86 dmaResource_t *dmaRef = dmaSpec->ref;
87 uint32_t dmaChannel = dmaSpec->channel;
88 #else
89 dmaResource_t *dmaRef = timerHardware->dmaRef;
90 uint32_t dmaChannel = timerHardware->dmaChannel;
91 #endif
93 if (dmaRef == NULL) {
94 return;
97 /* Time base configuration */
99 TimHandle.Instance = timer;
101 uint16_t prescaler = timerGetPrescalerByDesiredMhz(timer, transponder->timer_hz);
102 uint16_t period = timerGetPeriodByPrescaler(timer, prescaler, transponder->timer_carrier_hz);
104 transponder->bitToggleOne = period / 2;
106 TimHandle.Init.Prescaler = prescaler;
107 TimHandle.Init.Period = period; // 800kHz
108 TimHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
109 TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
110 if (HAL_TIM_PWM_Init(&TimHandle) != HAL_OK) {
111 /* Initialization Error */
112 return;
115 /* IO configuration */
117 static DMA_HandleTypeDef hdma_tim;
119 transponderIO = IOGetByTag(ioTag);
120 IOInit(transponderIO, OWNER_TRANSPONDER, 0);
121 IOConfigGPIOAF(transponderIO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLDOWN), timerHardware->alternateFunction);
123 __DMA1_CLK_ENABLE();
124 __DMA2_CLK_ENABLE();
126 /* Set the parameters to be configured */
127 #ifdef STM32H7
128 hdma_tim.Init.Request = dmaChannel;
129 #else
130 hdma_tim.Init.Channel = dmaChannel;
131 #endif
132 hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH;
133 hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
134 hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
135 hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
136 hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
137 hdma_tim.Init.Mode = DMA_NORMAL;
138 hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
139 hdma_tim.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
140 hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
141 hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
142 hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
144 /* Set hdma_tim instance */
145 hdma_tim.Instance = (DMA_ARCH_TYPE *)dmaRef;
147 uint16_t dmaIndex = timerDmaIndex(timerChannel);
149 /* Link hdma_tim to hdma[x] (channelx) */
150 __HAL_LINKDMA(&TimHandle, hdma[dmaIndex], hdma_tim);
152 dmaInit(dmaGetIdentifier(dmaRef), OWNER_TRANSPONDER, 0);
153 dmaSetHandler(dmaGetIdentifier(dmaRef), TRANSPONDER_DMA_IRQHandler, NVIC_PRIO_TRANSPONDER_DMA, dmaIndex);
155 /* Initialize TIMx DMA handle */
156 if (HAL_DMA_Init(TimHandle.hdma[dmaIndex]) != HAL_OK) {
157 /* Initialization Error */
158 return;
162 RCC_ClockCmd(timerRCC(timer), ENABLE);
164 /* PWM1 Mode configuration: Channel1 */
165 TIM_OC_InitTypeDef TIM_OCInitStructure;
167 TIM_OCInitStructure.OCMode = TIM_OCMODE_PWM1;
168 TIM_OCInitStructure.OCIdleState = TIM_OCIDLESTATE_RESET;
169 TIM_OCInitStructure.OCPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCPOLARITY_LOW : TIM_OCPOLARITY_HIGH;
170 TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET;
171 TIM_OCInitStructure.OCNPolarity = (timerHardware->output & TIMER_OUTPUT_INVERTED) ? TIM_OCNPOLARITY_LOW : TIM_OCNPOLARITY_HIGH;
172 TIM_OCInitStructure.Pulse = 0;
173 TIM_OCInitStructure.OCFastMode = TIM_OCFAST_DISABLE;
174 if (HAL_TIM_PWM_ConfigChannel(&TimHandle, &TIM_OCInitStructure, timerChannel) != HAL_OK) {
175 /* Configuration Error */
176 return;
178 if (timerHardware->output & TIMER_OUTPUT_N_CHANNEL) {
179 if (HAL_TIMEx_PWMN_Start(&TimHandle, timerChannel) != HAL_OK) {
180 /* Starting PWM generation Error */
181 return;
183 } else {
184 if (HAL_TIM_PWM_Start(&TimHandle, timerChannel) != HAL_OK) {
185 /* Starting PWM generation Error */
186 return;
190 transponderInitialised = true;
193 bool transponderIrInit(const ioTag_t ioTag, const transponderProvider_e provider)
195 if (!ioTag) {
196 return false;
199 switch (provider) {
200 case TRANSPONDER_ARCITIMER:
201 transponderIrInitArcitimer(&transponder);
202 break;
203 case TRANSPONDER_ILAP:
204 transponderIrInitIlap(&transponder);
205 break;
206 case TRANSPONDER_ERLT:
207 transponderIrInitERLT(&transponder);
208 break;
209 default:
210 return false;
213 transponderIrHardwareInit(ioTag, &transponder);
215 return true;
218 bool isTransponderIrReady(void)
220 return !transponderIrDataTransferInProgress;
223 void transponderIrWaitForTransmitComplete(void)
225 #ifdef DEBUG
226 static uint32_t waitCounter = 0;
227 #endif
229 while (transponderIrDataTransferInProgress) {
230 #ifdef DEBUG
231 waitCounter++;
232 #endif
236 void transponderIrUpdateData(const uint8_t* transponderData)
238 transponderIrWaitForTransmitComplete();
239 transponder.vTable->updateTransponderDMABuffer(&transponder, transponderData);
242 void transponderIrDMAEnable(transponder_t *transponder)
244 if (!transponderInitialised) {
245 return;
248 if (DMA_SetCurrDataCounter(&TimHandle, timerChannel, transponder->transponderIrDMABuffer.ilap, transponder->dma_buffer_size) != HAL_OK) {
249 /* DMA set error */
250 transponderIrDataTransferInProgress = 0;
251 return;
254 /* Reset timer counter */
255 __HAL_TIM_SET_COUNTER(&TimHandle, 0);
256 /* Enable channel DMA requests */
257 TIM_DMACmd(&TimHandle, timerChannel, ENABLE);
260 void transponderIrDisable(void)
262 if (!transponderInitialised) {
263 return;
266 TIM_DMACmd(&TimHandle, timerChannel, DISABLE);
267 if (output & TIMER_OUTPUT_N_CHANNEL) {
268 HAL_TIMEx_PWMN_Stop(&TimHandle, timerChannel);
269 } else {
270 HAL_TIM_PWM_Stop(&TimHandle, timerChannel);
274 IOInit(transponderIO, OWNER_TRANSPONDER, 0);
276 #ifdef TRANSPONDER_INVERTED
277 IOHi(transponderIO);
278 #else
279 IOLo(transponderIO);
280 #endif
282 IOConfigGPIOAF(transponderIO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLDOWN), alternateFunction);
285 void transponderIrTransmit(void)
287 transponderIrWaitForTransmitComplete();
289 transponderIrDataTransferInProgress = 1;
290 transponderIrDMAEnable(&transponder);
292 #endif