Paparazzi UAS  v4.2.2_stable-4-gcc32f65
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ppm_arch.c
Go to the documentation of this file.
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2010 The Paparazzi Team
5  *
6  * This file is part of paparazzi.
7  *
8  * paparazzi is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2, or (at your option)
11  * any later version.
12  *
13  * paparazzi is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with paparazzi; see the file COPYING. If not, write to
20  * the Free Software Foundation, 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 
26 
27 #include <stm32/rcc.h>
28 #include <stm32/gpio.h>
29 #include <stm32/tim.h>
30 #include <stm32/misc.h>
31 
32 #include "mcu_periph/sys_time.h"
33 
34 /*
35 *
36 * This a radio control ppm driver for stm32
37 * Either on:
38 * signal on PA1 TIM2/CH2 (uart1 trig on lisa/L) (Servo 6 on Lisa/M2)
39 * or signal on PA10 TIM1/CH3 (uart1 trig on lisa/L) (uart1 rx on Lisa/M2)
40 *
41 */
46 
47 #ifdef USE_TIM1_IRQ
48 #pragma message "UART1 RX pin is used for PPM input"
49 void tim1_up_irq_handler(void);
50 void tim1_cc_irq_handler(void);
51 #endif
52 
53 #ifdef USE_TIM2_IRQ
54 #pragma message "Servo pin 6 is used for PPM input"
55 void tim2_irq_handler(void);
56 #endif
57 
58 
59 void ppm_arch_init ( void ) {
60  GPIO_InitTypeDef GPIO_InitStructure;
61 #ifdef USE_TIM1_IRQ
62  /* TIM1 channel 3 pin (PA.10) configuration */
63  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
64 #elif defined USE_TIM2_IRQ
65  /* TIM2 channel 2 pin (PA.01) configuration */
66  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
67 #endif
68  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
69  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
70  GPIO_Init(GPIOA, &GPIO_InitStructure);
71 
72 #ifdef USE_TIM1_IRQ
73  /* TIM1 clock enable */
74  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
75 #elif defined USE_TIM2_IRQ
76  /* TIM2 clock enable */
77  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
78 #endif
79 
80  /* GPIOA clock enable */
81  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
82 
83  /* Time Base configuration */
84  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
85  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
86  TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
87  TIM_TimeBaseStructure.TIM_Prescaler = 0x8;
88  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
89  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
90 #ifdef USE_TIM1_IRQ
91  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
92 #elif defined USE_TIM2_IRQ
93  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
94 #endif
95 
96 /* TIM2 configuration: Input Capture mode ---------------------
97 The external signal is connected to TIM2 CH2 pin (PA.01)
98 TIM1 configuration: Input Capture mode ---------------------
99 The external signal is connected to TIM1 CH3 pin (PA.10)
100 The Rising edge is used as active edge,
101 ------------------------------------------------------------ */
102  TIM_ICInitTypeDef TIM_ICInitStructure;
103 #ifdef USE_TIM1_IRQ
104  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;
105 #elif defined USE_TIM2_IRQ
106  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
107 #endif
108  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
109  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
110  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
111  TIM_ICInitStructure.TIM_ICFilter = 0x00;
112 #ifdef USE_TIM1_IRQ
113  TIM_ICInit(TIM1, &TIM_ICInitStructure);
114 #elif defined USE_TIM2_IRQ
115  TIM_ICInit(TIM2, &TIM_ICInitStructure);
116 #endif
117  /* Enable the TIM1 global Interrupt */
118  /* Enable the TIM2 global Interrupt */
119  NVIC_InitTypeDef NVIC_InitStructure;
120 #ifdef USE_TIM1_IRQ
121  NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
122 #elif defined USE_TIM2_IRQ
123  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
124 #endif
125  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
126  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
127  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
128  NVIC_Init(&NVIC_InitStructure);
129 #ifdef USE_TIM1_IRQ
130  NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
131  NVIC_Init(&NVIC_InitStructure);
132 #endif
133 
134 #ifdef USE_TIM1_IRQ
135  /* TIM1 enable counter */
136  TIM_Cmd(TIM1, ENABLE);
137 #elif defined USE_TIM2_IRQ
138  /* TIM2 enable counter */
139  TIM_Cmd(TIM2, ENABLE);
140 #endif
141 
142 #ifdef USE_TIM1_IRQ
143  /* Enable the CC3 Interrupt Request */
144  TIM_ITConfig(TIM1, TIM_IT_CC3|TIM_IT_Update, ENABLE);
145 #elif defined USE_TIM2_IRQ
146  /* Enable the CC2 Interrupt Request */
147  TIM_ITConfig(TIM2, TIM_IT_CC2|TIM_IT_Update, ENABLE);
148 #endif
149 
152  timer_rollover_cnt = 0;
153 
154 }
155 
156 #ifdef USE_TIM1_IRQ
157 void tim1_up_irq_handler(void) {
158  if(TIM_GetITStatus(TIM1, TIM_IT_Update) == SET) {
159  timer_rollover_cnt+=(1<<16);
160  TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
161  }
162 }
163 
164 void tim1_cc_irq_handler(void) {
165  if(TIM_GetITStatus(TIM1, TIM_IT_CC3) == SET) {
166  TIM_ClearITPendingBit(TIM1, TIM_IT_CC3);
167 
168  uint32_t now = TIM_GetCapture3(TIM1) + timer_rollover_cnt;
169  DecodePpmFrame(now);
170  }
171 }
172 #elif defined USE_TIM2_IRQ
173 void tim2_irq_handler(void) {
174  if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET) {
175  TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
176  uint32_t now = TIM_GetCapture2(TIM2) + timer_rollover_cnt;
177  DecodePpmFrame(now);
178  }
179  else if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) {
180  timer_rollover_cnt+=(1<<16);
181  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
182  }
183 }
184 #endif
uint32_t ppm_last_pulse_time
Definition: ppm_arch.c:28
bool_t ppm_data_valid
Definition: ppm_arch.c:29
void ppm_arch_init(void)
Architecture dependant code.
Definition: ppm_arch.c:31
uint8_t ppm_cur_pulse
State machine for decoding ppm frames.
Definition: ppm_arch.c:27
Architecture independent timing functions.
unsigned long uint32_t
Definition: types.h:18
#define DecodePpmFrame(_ppm_time)
A valid ppm frame:
Definition: ppm.h:89
#define RADIO_CONTROL_NB_CHANNEL
Definition: spektrum_arch.h:36
unsigned char uint8_t
Definition: types.h:14
static uint32_t timer_rollover_cnt
Definition: ppm_arch.c:45