Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
ppm_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2014 The Paparazzi Team
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
35 
36 #include BOARD_CONFIG
37 
38 #include <libopencm3/stm32/rcc.h>
39 #include <libopencm3/stm32/gpio.h>
40 #include <libopencm3/stm32/timer.h>
41 #include <libopencm3/cm3/nvic.h>
42 
43 #include "mcu_periph/gpio.h"
44 
45 // for timer_get_frequency
46 #include "mcu_arch.h"
47 
48 #define ONE_MHZ_CLK 1000000
49 #ifdef NVIC_TIM_IRQ_PRIO
50 #define PPM_IRQ_PRIO NVIC_TIM_IRQ_PRIO
51 #else
52 #define PPM_IRQ_PRIO 2
53 #endif
54 
55 
57 
58 
59 #if USE_PPM_TIM1
60 
61 PRINT_CONFIG_MSG("Using TIM1 for PPM input.")
62 #define PPM_TIMER TIM1
63 #define RCC_TIM_PPM RCC_TIM1
64 #define RST_TIM_PPM RST_TIM1
65 
66 #elif USE_PPM_TIM2
67 
68 PRINT_CONFIG_MSG("Using TIM2 for PPM input.")
69 #define PPM_TIMER TIM2
70 #define RCC_TIM_PPM RCC_TIM2
71 #define RST_TIM_PPM RST_TIM2
72 
73 #elif USE_PPM_TIM3
74 
75 PRINT_CONFIG_MSG("Using TIM3 for PPM input.")
76 #define PPM_TIMER TIM3
77 #define RCC_TIM_PPM RCC_TIM3
78 #define RST_TIM_PPM RST_TIM3
79 
80 #elif USE_PPM_TIM4
81 
82 PRINT_CONFIG_MSG("Using TIM4 for PPM input.")
83 #define PPM_TIMER TIM4
84 #define RCC_TIM_PPM RCC_TIM4
85 #define RST_TIM_PPM RST_TIM4
86 
87 #elif USE_PPM_TIM5
88 
89 PRINT_CONFIG_MSG("Using TIM5 for PPM input.")
90 #define PPM_TIMER TIM5
91 #define RCC_TIM_PPM RCC_TIM5
92 #define RST_TIM_PPM RST_TIM5
93 
94 #elif USE_PPM_TIM8
95 
96 PRINT_CONFIG_MSG("Using TIM8 for PPM input.")
97 #define PPM_TIMER TIM8
98 #define RCC_TIM_PPM RCC_TIM8
99 #define RST_TIM_PPM RST_TIM8
100 
101 #elif USE_PPM_TIM9
102 
103 PRINT_CONFIG_MSG("Using TIM9 for PPM input.")
104 #define PPM_TIMER TIM9
105 #define RCC_TIM_PPM RCC_TIM9
106 #define RST_TIM_PPM RST_TIM9
107 
108 #elif USE_PPM_TIM12
109 
110 PRINT_CONFIG_MSG("Using TIM12 for PPM input.")
111 #define PPM_TIMER TIM12
112 #define RCC_TIM_PPM RCC_TIM12
113 #define RST_TIM_PPM RST_TIM12
114 
115 #else
116 #error Unknown PPM input timer configuration.
117 #endif
118 
119 void ppm_arch_init(void)
120 {
121  /* timer clock enable */
122  rcc_periph_clock_enable(RCC_TIM_PPM);
123 
124  /* GPIO configuration as input capture for timer */
126 
127  /* Time Base configuration */
128  rcc_periph_reset_pulse(RST_TIM_PPM);
129  timer_set_mode(PPM_TIMER, TIM_CR1_CKD_CK_INT,
130  TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
131  timer_set_period(PPM_TIMER, 0xFFFF);
133  timer_set_prescaler(PPM_TIMER, (timer_clk / (RC_PPM_TICKS_PER_USEC * ONE_MHZ_CLK)) - 1);
134 
135  /* TIM configuration: Input Capture mode ---------------------
136  The Rising edge is used as active edge
137  ------------------------------------------------------------ */
138 #if defined PPM_PULSE_TYPE && PPM_PULSE_TYPE == PPM_PULSE_TYPE_POSITIVE
139  timer_ic_set_polarity(PPM_TIMER, PPM_CHANNEL, TIM_IC_RISING);
140 #elif defined PPM_PULSE_TYPE && PPM_PULSE_TYPE == PPM_PULSE_TYPE_NEGATIVE
141  timer_ic_set_polarity(PPM_TIMER, PPM_CHANNEL, TIM_IC_FALLING);
142 #else
143 #error "Unknown PPM_PULSE_TYPE"
144 #endif
145  timer_ic_set_input(PPM_TIMER, PPM_CHANNEL, PPM_TIMER_INPUT);
146  timer_ic_set_prescaler(PPM_TIMER, PPM_CHANNEL, TIM_IC_PSC_OFF);
147  timer_ic_set_filter(PPM_TIMER, PPM_CHANNEL, TIM_IC_OFF);
148 
149  /* Enable timer Interrupt(s). */
150  nvic_set_priority(PPM_IRQ, PPM_IRQ_PRIO);
151  nvic_enable_irq(PPM_IRQ);
152 
153 #ifdef PPM_IRQ2
154  nvic_set_priority(PPM_IRQ2, PPM_IRQ_PRIO);
155  nvic_enable_irq(PPM_IRQ2);
156 #endif
157 
158  /* Enable the Capture/Compare and Update interrupt requests. */
159  timer_enable_irq(PPM_TIMER, (PPM_CC_IE | TIM_DIER_UIE));
160 
161  /* Enable capture channel. */
162  timer_ic_enable(PPM_TIMER, PPM_CHANNEL);
163 
164  /* TIM enable counter */
165  timer_enable_counter(PPM_TIMER);
166 
167  timer_rollover_cnt = 0;
168 }
169 
170 #if USE_PPM_TIM2
171 
172 void tim2_isr(void)
173 {
174  if ((TIM2_SR & PPM_CC_IF) != 0) {
175  timer_clear_flag(TIM2, PPM_CC_IF);
176 
177  uint32_t now = timer_get_counter(TIM2) + timer_rollover_cnt;
178  ppm_decode_frame(now);
179  } else if ((TIM2_SR & TIM_SR_UIF) != 0) {
180  timer_rollover_cnt += (1 << 16);
181  timer_clear_flag(TIM2, TIM_SR_UIF);
182  }
183 }
184 
185 
186 #elif USE_PPM_TIM3
187 
188 void tim3_isr(void)
189 {
190  if ((TIM3_SR & PPM_CC_IF) != 0) {
191  timer_clear_flag(TIM3, PPM_CC_IF);
192 
193  uint32_t now = timer_get_counter(TIM3) + timer_rollover_cnt;
194  ppm_decode_frame(now);
195  } else if ((TIM3_SR & TIM_SR_UIF) != 0) {
196  timer_rollover_cnt += (1 << 16);
197  timer_clear_flag(TIM3, TIM_SR_UIF);
198  }
199 }
200 
201 #elif USE_PPM_TIM4
202 
203 void tim4_isr(void)
204 {
205  if ((TIM4_SR & PPM_CC_IF) != 0) {
206  timer_clear_flag(TIM4, PPM_CC_IF);
207 
208  uint32_t now = timer_get_counter(TIM4) + timer_rollover_cnt;
209  ppm_decode_frame(now);
210  } else if ((TIM4_SR & TIM_SR_UIF) != 0) {
211  timer_rollover_cnt += (1 << 16);
212  timer_clear_flag(TIM4, TIM_SR_UIF);
213  }
214 }
215 
216 #elif USE_PPM_TIM5
217 
218 void tim5_isr(void)
219 {
220  if ((TIM5_SR & PPM_CC_IF) != 0) {
221  timer_clear_flag(TIM5, PPM_CC_IF);
222 
223  uint32_t now = timer_get_counter(TIM5) + timer_rollover_cnt;
224  ppm_decode_frame(now);
225  } else if ((TIM5_SR & TIM_SR_UIF) != 0) {
226  timer_rollover_cnt += (1 << 16);
227  timer_clear_flag(TIM5, TIM_SR_UIF);
228  }
229 }
230 
231 
232 #elif USE_PPM_TIM1
233 
234 #if defined(STM32F1)
235 void tim1_up_isr(void)
236 {
237 #elif defined(STM32F4)
238 void tim1_up_tim10_isr(void) {
239 #endif
240  if ((TIM1_SR & TIM_SR_UIF) != 0) {
241  timer_rollover_cnt += (1 << 16);
242  timer_clear_flag(TIM1, TIM_SR_UIF);
243  }
244 }
245 
246 void tim1_cc_isr(void) {
247  if ((TIM1_SR & PPM_CC_IF) != 0) {
248  timer_clear_flag(TIM1, PPM_CC_IF);
249 
250  uint32_t now = timer_get_counter(TIM1) + timer_rollover_cnt;
251  ppm_decode_frame(now);
252  }
253 }
254 
255 #elif USE_PPM_TIM8
256 
257 #if defined(STM32F1)
258 void tim8_up_isr(void) {
259 #elif defined(STM32F4)
260 void tim8_up_tim13_isr(void) {
261 #endif
262  if ((TIM8_SR & TIM_SR_UIF) != 0) {
263  timer_rollover_cnt += (1 << 16);
264  timer_clear_flag(TIM8, TIM_SR_UIF);
265  }
266 }
267 
268 void tim8_cc_isr(void) {
269  if ((TIM8_SR & PPM_CC_IF) != 0) {
270  timer_clear_flag(TIM8, PPM_CC_IF);
271 
272  uint32_t now = timer_get_counter(TIM8) + timer_rollover_cnt;
273  ppm_decode_frame(now);
274  }
275 }
276 
277 #elif USE_PPM_TIM9 && defined(STM32F4)
278 
279 void tim1_brk_tim9_isr(void)
280 {
281  if ((TIM9_SR & PPM_CC_IF) != 0) {
282  timer_clear_flag(TIM9, PPM_CC_IF);
283 
284  uint32_t now = timer_get_counter(TIM9) + timer_rollover_cnt;
285  ppm_decode_frame(now);
286 
287  } else if ((TIM9_SR & TIM_SR_UIF) != 0) {
288  timer_rollover_cnt += (1 << 16);
289  timer_clear_flag(TIM9, TIM_SR_UIF);
290  }
291 }
292 
293 #elif USE_PPM_TIM12 && defined(STM32F4)
294 
295 void tim8_brk_tim12_isr(void)
296 {
297  if ((TIM12_SR & PPM_CC_IF) != 0) {
298  timer_clear_flag(TIM12, PPM_CC_IF);
299 
300  uint32_t now = timer_get_counter(TIM12) + timer_rollover_cnt;
301  ppm_decode_frame(now);
302 
303  } else if ((TIM12_SR & TIM_SR_UIF) != 0) {
304  timer_rollover_cnt += (1 << 16);
305  timer_clear_flag(TIM12, TIM_SR_UIF);
306  }
307 }
308 
309 
310 
311 #endif /* USE_PPM_TIM1 */
312 
#define PPM_CHANNEL
Definition: board.h:388
#define PPM_TIMER
Definition: board.h:389
#define PPM_CC_IF
Definition: apogee_1.0.h:350
#define PPM_IRQ
Definition: apogee_1.0.h:346
#define PPM_CC_IE
Definition: apogee_1.0.h:349
#define PPM_TIMER_INPUT
Definition: apogee_1.0.h:345
#define PPM_GPIO_AF
Definition: apogee_1.0.h:353
#define PPM_GPIO_PORT
Definition: apogee_1.0.h:351
#define PPM_IRQ2
Definition: apogee_1.0.h:347
#define PPM_GPIO_PIN
Definition: apogee_1.0.h:352
void gpio_setup_pin_af(ioportid_t port, uint16_t pin, uint8_t af, bool is_output)
Setup a gpio for input or output with alternate function.
Definition: gpio_arch.c:65
void ppm_arch_init(void)
Architecture dependant code.
Definition: ppm_arch.c:90
Some architecture independent helper functions for GPIOs.
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
void ppm_decode_frame(uint32_t ppm_time)
Decode a PPM frame from global timer value.
Definition: ppm.c:105
Generic interface for radio control modules.
#define FALSE
Definition: std.h:5
uint32_t timer_get_frequency(uint32_t timer_peripheral)
Get Timer clock frequency (before prescaling) Only valid if using the internal clock for the timer.
Definition: mcu_arch.c:311
#define ONE_MHZ_CLK
Definition: ppm_arch.c:48
static uint32_t timer_rollover_cnt
Definition: ppm_arch.c:56
#define PPM_IRQ_PRIO
Definition: ppm_arch.c:52
#define RC_PPM_TICKS_PER_USEC
The ppm counter is set-up to have 1/6 us resolution.
Definition: ppm_arch.h:43
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78