Cosmetics
[opentx.git] / radio / src / targets / taranis / intmodule_pulses_driver.cpp
blobe71768eacb1fab33f66c2d16c4c6e963922966a2
1 /*
2 * Copyright (C) OpenTX
4 * Based on code named
5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
21 #include "opentx.h"
22 #include "pulses/pulses.h"
24 void intmoduleStop()
26 INTERNAL_MODULE_OFF();
28 NVIC_DisableIRQ(INTMODULE_DMA_STREAM_IRQn);
29 NVIC_DisableIRQ(INTMODULE_TIMER_CC_IRQn);
31 INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
32 INTMODULE_TIMER->DIER &= ~(TIM_DIER_CC2IE | TIM_DIER_UDE);
33 INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
36 // #define HEARBEAT_OFFSET unsigned(6000 + g_model.flightModeData[0].gvars[0] * 100)
37 constexpr unsigned HEARBEAT_OFFSET = 6000;
39 void intmoduleSendNextFrame()
41 switch (moduleState[INTERNAL_MODULE].protocol) {
42 #if defined(PXX1)
43 case PROTOCOL_CHANNELS_PXX1_PULSES:
45 uint32_t last = intmodulePulsesData.pxx.getLast();
46 if (heartbeatCapture.valid) {
47 if (getTmr2MHz() - heartbeatCapture.timestamp > HEARBEAT_OFFSET)
48 last -= 21;
49 else
50 last += 19;
51 intmodulePulsesData.pxx.setLast(last);
53 INTMODULE_TIMER->CCR2 = last - 4000; // 2mS in advance
54 INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
55 INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
56 INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR);
57 INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(intmodulePulsesData.pxx.getData());
58 INTMODULE_DMA_STREAM->NDTR = intmodulePulsesData.pxx.getSize();
59 INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
60 break;
62 #endif
64 #if defined(INTERNAL_MODULE_PPM)
65 case PROTOCOL_CHANNELS_PPM:
66 INTMODULE_TIMER->CCR3 = GET_MODULE_PPM_DELAY(INTERNAL_MODULE) * 2;
67 INTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_MODULE_PPM_POLARITY(INTERNAL_MODULE) ? 0 : TIM_CCER_CC3P);
68 INTMODULE_TIMER->CCR2 = *(intmodulePulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
69 INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
70 INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
71 INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR);
72 INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(intmodulePulsesData.ppm.pulses);
73 INTMODULE_DMA_STREAM->NDTR = intmodulePulsesData.ppm.ptr - intmodulePulsesData.ppm.pulses;
74 INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
75 break;
76 #endif
78 default:
79 INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
80 break;
84 void intmodulePxx1PulsesStart()
86 INTERNAL_MODULE_ON();
88 GPIO_PinAFConfig(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PinSource, INTMODULE_TX_GPIO_AF);
90 GPIO_InitTypeDef GPIO_InitStructure;
91 GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
92 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
93 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
94 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
95 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
96 GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
98 INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
99 INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
100 INTMODULE_TIMER->ARR = 18000;
101 INTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE;
102 INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
103 INTMODULE_TIMER->CCR3 = 16;
104 INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high
105 INTMODULE_TIMER->EGR = 1; // Restart
106 INTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
107 INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;
108 INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
109 INTMODULE_TIMER->CCR2 = 16000; // The first frame will be sent in 20ms
110 INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
111 INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
113 NVIC_EnableIRQ(INTMODULE_DMA_STREAM_IRQn);
114 NVIC_SetPriority(INTMODULE_DMA_STREAM_IRQn, 7);
115 NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn);
116 NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7);
119 #if defined(INTERNAL_MODULE_PPM)
120 void intmodulePpmStart()
122 INTERNAL_MODULE_ON();
124 GPIO_PinAFConfig(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PinSource, INTMODULE_TX_GPIO_AF);
126 GPIO_InitTypeDef GPIO_InitStructure;
127 GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
128 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
129 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
130 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
131 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
132 GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
134 INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
135 INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz
136 INTMODULE_TIMER->ARR = 45000;
137 INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1
138 INTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
139 INTMODULE_TIMER->EGR = 1;
140 INTMODULE_TIMER->DIER = TIM_DIER_UDE;
141 INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
142 INTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms
143 INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
144 INTMODULE_TIMER->CR1 = TIM_CR1_CEN;
146 NVIC_EnableIRQ(INTMODULE_DMA_STREAM_IRQn);
147 NVIC_SetPriority(INTMODULE_DMA_STREAM_IRQn, 7);
148 NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn);
149 NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7);
151 #endif // defined(INTERNAL_MODULE_PPM)
153 extern "C" void INTMODULE_DMA_STREAM_IRQHandler()
155 if (!DMA_GetITStatus(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC))
156 return;
158 DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC);
160 INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
161 INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
164 extern "C" void INTMODULE_TIMER_CC_IRQHandler()
166 INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt
167 INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
168 if (setupPulsesInternalModule()) {
169 intmoduleSendNextFrame();