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.
25 EXTERNAL_MODULE_OFF();
27 NVIC_DisableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn
);
28 NVIC_DisableIRQ(EXTMODULE_TIMER_CC_IRQn
);
30 EXTMODULE_TIMER_DMA_STREAM
->CR
&= ~DMA_SxCR_EN
; // Disable DMA
31 EXTMODULE_TIMER
->DIER
&= ~(TIM_DIER_CC2IE
| TIM_DIER_UDE
);
32 EXTMODULE_TIMER
->CR1
&= ~TIM_CR1_CEN
;
34 GPIO_InitTypeDef GPIO_InitStructure
;
35 GPIO_InitStructure
.GPIO_Pin
= EXTMODULE_TX_GPIO_PIN
;
36 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_OUT
;
37 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_2MHz
;
38 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
39 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_NOPULL
;
40 GPIO_Init(EXTMODULE_TX_GPIO
, &GPIO_InitStructure
);
43 void extmodulePpmStart()
47 GPIO_PinAFConfig(EXTMODULE_TX_GPIO
, EXTMODULE_TX_GPIO_PinSource
, EXTMODULE_TIMER_TX_GPIO_AF
);
49 GPIO_InitTypeDef GPIO_InitStructure
;
50 GPIO_InitStructure
.GPIO_Pin
= EXTMODULE_TX_GPIO_PIN
;
51 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_AF
;
52 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_2MHz
;
53 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
54 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_NOPULL
;
55 GPIO_Init(EXTMODULE_TX_GPIO
, &GPIO_InitStructure
);
57 // PPM generation principle:
59 // Hardware timer in PWM mode is used for PPM generation
60 // Output is OFF if CNT<CCR1(delay) and ON if bigger
61 // CCR1 register defines duration of pulse length and is constant
62 // AAR register defines duration of each pulse, it is
63 // updated after every pulse in Update interrupt handler.
64 // CCR2 register defines duration of no pulses (time between two pulse trains)
65 // it is calculated every round to have PPM period constant.
66 // CC2 interrupt is then used to setup new PPM values for the
67 // next PPM pulses train.
69 EXTMODULE_TIMER
->CR1
&= ~TIM_CR1_CEN
; // Stop timer
70 EXTMODULE_TIMER
->PSC
= EXTMODULE_TIMER_FREQ
/ 2000000 - 1; // 0.5uS (2Mhz)
72 #if defined(PCBX10) || PCBREV >= 13
73 EXTMODULE_TIMER
->CCR3
= GET_MODULE_PPM_DELAY(EXTERNAL_MODULE
)*2;
74 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC3E
| (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE
) ? TIM_CCER_CC3P
: 0);
75 EXTMODULE_TIMER
->CCMR2
= TIM_CCMR2_OC3M_1
| TIM_CCMR2_OC3M_0
; // Force O/P high
76 EXTMODULE_TIMER
->BDTR
= TIM_BDTR_MOE
;
77 EXTMODULE_TIMER
->EGR
= 1; // Reloads register values now
78 EXTMODULE_TIMER
->CCMR2
= TIM_CCMR2_OC3M_1
| TIM_CCMR2_OC3M_2
; // PWM mode 1
80 EXTMODULE_TIMER
->CCR1
= GET_MODULE_PPM_DELAY(EXTERNAL_MODULE
)*2;
81 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC1E
| (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE
) ? TIM_CCER_CC1P
: 0);
82 EXTMODULE_TIMER
->CCMR1
= TIM_CCMR1_OC1M_2
| TIM_CCMR1_OC1M_0
; // Force O/P high
83 EXTMODULE_TIMER
->EGR
= 1; // Reloads register values now
84 EXTMODULE_TIMER
->CCMR1
= TIM_CCMR1_OC1M_1
| TIM_CCMR1_OC1M_2
| TIM_CCMR1_OC2PE
; // PWM mode 1
87 EXTMODULE_TIMER
->ARR
= 45000;
88 EXTMODULE_TIMER
->CCR2
= 40000; // The first frame will be sent in 20ms
89 EXTMODULE_TIMER
->SR
&= ~TIM_SR_CC2IF
; // Clear flag
90 EXTMODULE_TIMER
->DIER
|= TIM_DIER_UDE
| TIM_DIER_CC2IE
; // Enable this interrupt
91 EXTMODULE_TIMER
->CR1
= TIM_CR1_CEN
; // Start timer
93 NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn
);
94 NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn
, 7);
95 NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn
);
96 NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn
, 7);
100 void extmodulePxx1PulsesStart()
102 EXTERNAL_MODULE_ON();
104 GPIO_PinAFConfig(EXTMODULE_TX_GPIO
, EXTMODULE_TX_GPIO_PinSource
, EXTMODULE_TIMER_TX_GPIO_AF
);
106 GPIO_InitTypeDef GPIO_InitStructure
;
107 GPIO_InitStructure
.GPIO_Pin
= EXTMODULE_TX_GPIO_PIN
;
108 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_AF
;
109 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_2MHz
;
110 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
111 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_NOPULL
;
112 GPIO_Init(EXTMODULE_TX_GPIO
, &GPIO_InitStructure
);
114 EXTMODULE_TIMER
->CR1
&= ~TIM_CR1_CEN
;
115 EXTMODULE_TIMER
->PSC
= EXTMODULE_TIMER_FREQ
/ 2000000 - 1; // 0.5uS (2Mhz)
117 #if defined(PCBX10) || PCBREV >= 13
118 EXTMODULE_TIMER
->CCR3
= 18;
119 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC3E
| TIM_CCER_CC3NE
| TIM_CCER_CC3P
| TIM_CCER_CC3NP
;
120 EXTMODULE_TIMER
->CCMR2
= TIM_CCMR2_OC3M_2
| TIM_CCMR2_OC3M_0
; // Force O/P high
121 EXTMODULE_TIMER
->BDTR
= TIM_BDTR_MOE
; // Enable outputs
122 EXTMODULE_TIMER
->EGR
= 1; // Restart
123 EXTMODULE_TIMER
->CCMR2
= TIM_CCMR2_OC3M_1
| TIM_CCMR2_OC3M_2
;
125 EXTMODULE_TIMER
->CCR1
= 18;
126 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC1E
| TIM_CCER_CC1P
| TIM_CCER_CC1NE
| TIM_CCER_CC1NP
; // TIM_CCER_CC1E | TIM_CCER_CC1P;
127 EXTMODULE_TIMER
->CCMR1
= TIM_CCMR1_OC1M_2
| TIM_CCMR1_OC1M_0
; // Force O/P high
128 EXTMODULE_TIMER
->BDTR
= TIM_BDTR_MOE
; // Enable outputs
129 EXTMODULE_TIMER
->EGR
= 1; // Restart
130 EXTMODULE_TIMER
->CCMR1
= TIM_CCMR1_OC1M_1
| TIM_CCMR1_OC1M_2
;
133 EXTMODULE_TIMER
->ARR
= 45000;
134 EXTMODULE_TIMER
->CCR2
= 40000; // The first frame will be sent in 20ms
135 EXTMODULE_TIMER
->SR
&= ~TIM_SR_CC2IF
; // Clear flag
136 EXTMODULE_TIMER
->DIER
|= TIM_DIER_UDE
| TIM_DIER_CC2IE
; // Enable DMA on update
137 EXTMODULE_TIMER
->CR1
|= TIM_CR1_CEN
;
139 NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn
);
140 NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn
, 7);
141 NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn
);
142 NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn
, 7);
146 void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us
, bool inverted
)
148 EXTERNAL_MODULE_ON();
150 GPIO_PinAFConfig(EXTMODULE_TX_GPIO
, EXTMODULE_TX_GPIO_PinSource
, EXTMODULE_TIMER_TX_GPIO_AF
);
152 GPIO_InitTypeDef GPIO_InitStructure
;
153 GPIO_InitStructure
.GPIO_Pin
= EXTMODULE_TX_GPIO_PIN
;
154 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_AF
;
155 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_2MHz
;
156 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
157 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_NOPULL
;
158 GPIO_Init(EXTMODULE_TX_GPIO
, &GPIO_InitStructure
);
160 EXTMODULE_TIMER
->CR1
&= ~TIM_CR1_CEN
;
161 EXTMODULE_TIMER
->PSC
= EXTMODULE_TIMER_FREQ
/ 2000000 - 1; // 0.5uS (2Mhz)
163 #if defined(PCBX10) || PCBREV >= 13
164 EXTMODULE_TIMER
->CCR3
= 0;
165 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC3E
| TIM_CCER_CC3P
;
166 EXTMODULE_TIMER
->CCMR2
= TIM_CCMR2_OC3M_2
| TIM_CCMR2_OC3M_0
; // Force O/P high
167 EXTMODULE_TIMER
->BDTR
= TIM_BDTR_MOE
; // Enable outputs
168 EXTMODULE_TIMER
->EGR
= 1; // Restart
169 EXTMODULE_TIMER
->CCMR2
= TIM_CCMR2_OC3M_1
| TIM_CCMR2_OC3M_0
;
171 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC1E
| (inverted
? 0 : TIM_CCER_CC1P
);
172 EXTMODULE_TIMER
->BDTR
= TIM_BDTR_MOE
; // Enable outputs
173 EXTMODULE_TIMER
->CCR1
= 0;
174 EXTMODULE_TIMER
->CCMR1
= TIM_CCMR1_OC1M_2
| TIM_CCMR1_OC1M_0
; // Force O/P high
175 EXTMODULE_TIMER
->EGR
= 1; // Restart
176 EXTMODULE_TIMER
->CCMR1
= TIM_CCMR1_OC1M_1
| TIM_CCMR1_OC1M_0
;
179 EXTMODULE_TIMER
->ARR
= period_half_us
;
180 EXTMODULE_TIMER
->CCR2
= period_half_us
- 4000;
181 EXTMODULE_TIMER
->SR
&= ~TIM_SR_CC2IF
; // Clear flag
182 EXTMODULE_TIMER
->DIER
|= TIM_DIER_UDE
| TIM_DIER_CC2IE
;
183 EXTMODULE_TIMER
->CR1
|= TIM_CR1_CEN
;
185 NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn
);
186 NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn
, 7);
187 NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn
);
188 NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn
, 7);
191 #if defined(EXTMODULE_USART)
192 ModuleFifo extmoduleFifo
;
194 void extmoduleInvertedSerialStart(uint32_t baudrate
)
196 EXTERNAL_MODULE_ON();
199 GPIO_PinAFConfig(EXTMODULE_USART_GPIO
, EXTMODULE_TX_GPIO_PinSource
, EXTMODULE_USART_GPIO_AF
);
200 GPIO_PinAFConfig(EXTMODULE_USART_GPIO
, EXTMODULE_RX_GPIO_PinSource
, EXTMODULE_USART_GPIO_AF
);
202 GPIO_InitTypeDef GPIO_InitStructure
;
203 GPIO_InitStructure
.GPIO_Pin
= EXTMODULE_TX_GPIO_PIN
| EXTMODULE_RX_GPIO_PIN
;
204 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_AF
;
205 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
206 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_2MHz
;
207 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_UP
;
208 GPIO_Init(EXTMODULE_USART_GPIO
, &GPIO_InitStructure
);
211 USART_DeInit(EXTMODULE_USART
);
212 USART_InitTypeDef USART_InitStructure
;
213 USART_InitStructure
.USART_BaudRate
= baudrate
;
214 USART_InitStructure
.USART_Parity
= USART_Parity_No
;
215 USART_InitStructure
.USART_StopBits
= USART_StopBits_1
;
216 USART_InitStructure
.USART_WordLength
= USART_WordLength_8b
;
217 USART_InitStructure
.USART_HardwareFlowControl
= USART_HardwareFlowControl_None
;
218 USART_InitStructure
.USART_Mode
= USART_Mode_Tx
| USART_Mode_Rx
;
219 USART_Init(EXTMODULE_USART
, &USART_InitStructure
);
220 USART_Cmd(EXTMODULE_USART
, ENABLE
);
222 extmoduleFifo
.clear();
224 USART_ITConfig(EXTMODULE_USART
, USART_IT_RXNE
, ENABLE
);
225 NVIC_SetPriority(EXTMODULE_USART_IRQn
, 6);
226 NVIC_EnableIRQ(EXTMODULE_USART_IRQn
);
229 void extmoduleSendBuffer(const uint8_t * data
, uint8_t size
)
231 DMA_InitTypeDef DMA_InitStructure
;
232 DMA_DeInit(EXTMODULE_USART_TX_DMA_STREAM
);
233 DMA_InitStructure
.DMA_Channel
= EXTMODULE_USART_TX_DMA_CHANNEL
;
234 DMA_InitStructure
.DMA_PeripheralBaseAddr
= CONVERT_PTR_UINT(&EXTMODULE_USART
->DR
);
235 DMA_InitStructure
.DMA_DIR
= DMA_DIR_MemoryToPeripheral
;
236 DMA_InitStructure
.DMA_Memory0BaseAddr
= CONVERT_PTR_UINT(data
);
237 DMA_InitStructure
.DMA_BufferSize
= size
;
238 DMA_InitStructure
.DMA_PeripheralInc
= DMA_PeripheralInc_Disable
;
239 DMA_InitStructure
.DMA_MemoryInc
= DMA_MemoryInc_Enable
;
240 DMA_InitStructure
.DMA_PeripheralDataSize
= DMA_PeripheralDataSize_Byte
;
241 DMA_InitStructure
.DMA_MemoryDataSize
= DMA_MemoryDataSize_Byte
;
242 DMA_InitStructure
.DMA_Mode
= DMA_Mode_Normal
;
243 DMA_InitStructure
.DMA_Priority
= DMA_Priority_VeryHigh
;
244 DMA_InitStructure
.DMA_FIFOMode
= DMA_FIFOMode_Disable
;
245 DMA_InitStructure
.DMA_FIFOThreshold
= DMA_FIFOThreshold_Full
;
246 DMA_InitStructure
.DMA_MemoryBurst
= DMA_MemoryBurst_Single
;
247 DMA_InitStructure
.DMA_PeripheralBurst
= DMA_PeripheralBurst_Single
;
248 DMA_Init(EXTMODULE_USART_TX_DMA_STREAM
, &DMA_InitStructure
);
249 DMA_Cmd(EXTMODULE_USART_TX_DMA_STREAM
, ENABLE
);
250 USART_DMACmd(EXTMODULE_USART
, USART_DMAReq_Tx
, ENABLE
);
253 #define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
254 extern "C" void EXTMODULE_USART_IRQHandler(void)
256 uint32_t status
= EXTMODULE_USART
->SR
;
258 while (status
& (USART_FLAG_RXNE
| USART_FLAG_ERRORS
)) {
259 uint8_t data
= EXTMODULE_USART
->DR
;
260 if (status
& USART_FLAG_ERRORS
) {
261 extmoduleFifo
.errors
++;
264 extmoduleFifo
.push(data
);
266 status
= EXTMODULE_USART
->SR
;
271 void extmoduleSendNextFrame()
273 switch (moduleState
[EXTERNAL_MODULE
].protocol
) {
274 case PROTOCOL_CHANNELS_PPM
:
275 #if defined(PCBX10) || PCBREV >= 13
276 EXTMODULE_TIMER
->CCR3
= GET_MODULE_PPM_DELAY(EXTERNAL_MODULE
)*2;
277 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC3E
| (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE
) ? TIM_CCER_CC3P
: 0);
278 EXTMODULE_TIMER
->CCR2
= *(extmodulePulsesData
.ppm
.ptr
- 1) - 4000; // 2mS in advance
279 EXTMODULE_TIMER_DMA_STREAM
->CR
&= ~DMA_SxCR_EN
; // Disable DMA
280 EXTMODULE_TIMER_DMA_STREAM
->CR
|= EXTMODULE_TIMER_DMA_CHANNEL
| DMA_SxCR_DIR_0
| DMA_SxCR_MINC
| EXTMODULE_TIMER_DMA_SIZE
| DMA_SxCR_PL_0
| DMA_SxCR_PL_1
;
282 EXTMODULE_TIMER
->CCR1
= GET_MODULE_PPM_DELAY(EXTERNAL_MODULE
)*2;
283 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC1E
| (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE
) ? TIM_CCER_CC1P
: 0);
284 EXTMODULE_TIMER
->CCR2
= *(extmodulePulsesData
.ppm
.ptr
- 1) - 4000; // 2mS in advance
285 EXTMODULE_TIMER_DMA_STREAM
->CR
&= ~DMA_SxCR_EN
; // Disable DMA
286 EXTMODULE_TIMER_DMA_STREAM
->CR
|= EXTMODULE_TIMER_DMA_CHANNEL
| DMA_SxCR_DIR_0
| DMA_SxCR_MINC
| EXTMODULE_TIMER_DMA_SIZE
| DMA_SxCR_PL_0
| DMA_SxCR_PL_1
;
288 EXTMODULE_TIMER_DMA_STREAM
->PAR
= CONVERT_PTR_UINT(&EXTMODULE_TIMER
->ARR
);
289 EXTMODULE_TIMER_DMA_STREAM
->M0AR
= CONVERT_PTR_UINT(extmodulePulsesData
.ppm
.pulses
);
290 EXTMODULE_TIMER_DMA_STREAM
->NDTR
= extmodulePulsesData
.ppm
.ptr
- extmodulePulsesData
.ppm
.pulses
;
291 EXTMODULE_TIMER_DMA_STREAM
->CR
|= DMA_SxCR_EN
| DMA_SxCR_TCIE
; // Enable DMA
295 case PROTOCOL_CHANNELS_PXX1_PULSES
:
296 EXTMODULE_TIMER
->CCR2
= extmodulePulsesData
.pxx
.getLast() - 4000; // 2mS in advance
297 EXTMODULE_TIMER_DMA_STREAM
->CR
&= ~DMA_SxCR_EN
; // Disable DMA
298 EXTMODULE_TIMER_DMA_STREAM
->CR
|= EXTMODULE_TIMER_DMA_CHANNEL
| DMA_SxCR_DIR_0
| DMA_SxCR_MINC
| EXTMODULE_TIMER_DMA_SIZE
| DMA_SxCR_PL_0
| DMA_SxCR_PL_1
;
299 EXTMODULE_TIMER_DMA_STREAM
->PAR
= CONVERT_PTR_UINT(&EXTMODULE_TIMER
->ARR
);
300 EXTMODULE_TIMER_DMA_STREAM
->M0AR
= CONVERT_PTR_UINT(extmodulePulsesData
.pxx
.getData());
301 EXTMODULE_TIMER_DMA_STREAM
->NDTR
= extmodulePulsesData
.pxx
.getSize();
302 EXTMODULE_TIMER_DMA_STREAM
->CR
|= DMA_SxCR_EN
| DMA_SxCR_TCIE
; // Enable DMA
306 #if defined(PXX1) && defined(HARDWARE_EXTERNAL_MODULE_SIZE_SML)
307 case PROTOCOL_CHANNELS_PXX1_SERIAL
:
308 extmoduleSendBuffer(extmodulePulsesData
.pxx_uart
.getData(), extmodulePulsesData
.pxx_uart
.getSize());
312 #if defined(PXX2) && defined(EXTMODULE_USART)
313 case PROTOCOL_CHANNELS_PXX2_HIGHSPEED
:
314 case PROTOCOL_CHANNELS_PXX2_LOWSPEED
:
315 extmoduleSendBuffer(extmodulePulsesData
.pxx2
.getData(), extmodulePulsesData
.pxx2
.getSize());
320 case PROTOCOL_CHANNELS_SBUS
:
321 #if defined(PCBX10) || PCBREV >= 13
322 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC3E
| (GET_SBUS_POLARITY(EXTERNAL_MODULE
) ? TIM_CCER_CC3P
: 0); // reverse polarity for Sbus if needed
324 EXTMODULE_TIMER
->CCER
= TIM_CCER_CC1E
| (GET_SBUS_POLARITY(EXTERNAL_MODULE
) ? TIM_CCER_CC1P
: 0); // reverse polarity for Sbus if needed
327 case PROTOCOL_CHANNELS_DSM2_LP45
:
328 case PROTOCOL_CHANNELS_DSM2_DSM2
:
329 case PROTOCOL_CHANNELS_DSM2_DSMX
:
330 case PROTOCOL_CHANNELS_MULTIMODULE
:
331 EXTMODULE_TIMER
->CCR2
= *(extmodulePulsesData
.dsm2
.ptr
- 1) - 4000; // 2mS in advance
332 EXTMODULE_TIMER_DMA_STREAM
->CR
&= ~DMA_SxCR_EN
; // Disable DMA
333 EXTMODULE_TIMER_DMA_STREAM
->CR
|= EXTMODULE_TIMER_DMA_CHANNEL
| DMA_SxCR_DIR_0
| DMA_SxCR_MINC
| EXTMODULE_TIMER_DMA_SIZE
| DMA_SxCR_PL_0
| DMA_SxCR_PL_1
;
334 EXTMODULE_TIMER_DMA_STREAM
->PAR
= CONVERT_PTR_UINT(&EXTMODULE_TIMER
->ARR
);
335 EXTMODULE_TIMER_DMA_STREAM
->M0AR
= CONVERT_PTR_UINT(extmodulePulsesData
.dsm2
.pulses
);
336 EXTMODULE_TIMER_DMA_STREAM
->NDTR
= extmodulePulsesData
.dsm2
.ptr
- extmodulePulsesData
.dsm2
.pulses
;
337 EXTMODULE_TIMER_DMA_STREAM
->CR
|= DMA_SxCR_EN
| DMA_SxCR_TCIE
; // Enable DMA
341 #if defined(CROSSFIRE)
342 case PROTOCOL_CHANNELS_CROSSFIRE
:
343 sportSendBuffer(extmodulePulsesData
.crossfire
.pulses
, extmodulePulsesData
.crossfire
.length
);
348 EXTMODULE_TIMER
->DIER
|= TIM_DIER_CC2IE
;
353 void extmoduleSendInvertedByte(uint8_t byte
)
360 GPIO_SetBits(EXTMODULE_TX_GPIO
, EXTMODULE_TX_GPIO_PIN
);
361 while ((uint16_t) (getTmr2MHz() - time
) < 34) {
365 for (i
= 0 ; i
< 8 ; i
+= 1) {
367 GPIO_ResetBits(EXTMODULE_TX_GPIO
, EXTMODULE_TX_GPIO_PIN
);
370 GPIO_SetBits(EXTMODULE_TX_GPIO
, EXTMODULE_TX_GPIO_PIN
);
373 while ((uint16_t) (getTmr2MHz() - time
) < 35) {
378 GPIO_ResetBits(EXTMODULE_TX_GPIO
, EXTMODULE_TX_GPIO_PIN
);
379 __enable_irq() ; // No need to wait for the stop bit to complete
380 while ((uint16_t) (getTmr2MHz() - time
) < 34) {
385 extern "C" void EXTMODULE_TIMER_DMA_IRQHandler()
387 if (!DMA_GetITStatus(EXTMODULE_TIMER_DMA_STREAM
, EXTMODULE_TIMER_DMA_FLAG_TC
))
390 DMA_ClearITPendingBit(EXTMODULE_TIMER_DMA_STREAM
, EXTMODULE_TIMER_DMA_FLAG_TC
);
392 EXTMODULE_TIMER
->SR
&= ~TIM_SR_CC2IF
; // Clear flag
393 EXTMODULE_TIMER
->DIER
|= TIM_DIER_CC2IE
; // Enable this interrupt
396 extern "C" void EXTMODULE_TIMER_IRQHandler()
398 EXTMODULE_TIMER
->DIER
&= ~TIM_DIER_CC2IE
; // Stop this interrupt
399 EXTMODULE_TIMER
->SR
&= ~TIM_SR_CC2IF
;
400 if (setupPulsesExternalModule())
401 extmoduleSendNextFrame();