diff --git a/conf/modules/AOA_pwm.xml b/conf/modules/AOA_pwm.xml
index 4c548f28ed..63797e9011 100644
--- a/conf/modules/AOA_pwm.xml
+++ b/conf/modules/AOA_pwm.xml
@@ -33,7 +33,7 @@
-
+
diff --git a/conf/modules/meteo_stick.xml b/conf/modules/meteo_stick.xml
index 3ef28a1a9d..ac1893158b 100644
--- a/conf/modules/meteo_stick.xml
+++ b/conf/modules/meteo_stick.xml
@@ -71,8 +71,8 @@ MS_SPI_DEV_LOWER=$(shell echo $(MS_SPI_DEV) | tr A-Z a-z)
-
-
+
+
diff --git a/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.c b/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.c
index c13320892f..0da7150250 100644
--- a/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.c
+++ b/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.c
@@ -25,7 +25,7 @@
*
* handling of smt32 PWM input using a timer with capture.
*/
-#include "mcu_periph/pwm_input_arch.h"
+#include "mcu_periph/pwm_input.h"
#include BOARD_CONFIG
#include "generated/airframe.h"
@@ -48,13 +48,18 @@
#define PWM_INPUT_IRQ_PRIO 2
#endif
-static inline void pwm_input_set_timer(uint32_t tim)
+static const uint32_t pwm_input_ticks_per_usec[] = {
+ PWM_INPUT1_TICKS_PER_USEC,
+ PWM_INPUT2_TICKS_PER_USEC
+};
+
+static inline void pwm_input_set_timer(uint32_t tim, uint32_t ticks_per_usec)
{
timer_reset(tim);
timer_set_mode(tim, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
timer_set_period(tim, 0xFFFF);
uint32_t timer_clk = timer_get_frequency(tim);
- timer_set_prescaler(tim, (timer_clk / (PWM_INPUT_TICKS_PER_USEC * ONE_MHZ_CLK)) - 1);
+ timer_set_prescaler(tim, (timer_clk / (ticks_per_usec * ONE_MHZ_CLK)) - 1);
timer_enable_counter(tim);
}
@@ -76,15 +81,27 @@ void pwm_input_init(void)
*/
#if USE_PWM_INPUT_TIM1
rcc_periph_clock_enable(RCC_TIM1);
- pwm_input_set_timer(TIM1);
+ pwm_input_set_timer(TIM1, PWM_INPUT_TIM1_TICKS_PER_USEC);
#endif
#if USE_PWM_INPUT_TIM2
rcc_periph_clock_enable(RCC_TIM2);
- pwm_input_set_timer(TIM2);
+ pwm_input_set_timer(TIM2, PWM_INPUT_TIM2_TICKS_PER_USEC);
#endif
#if USE_PWM_INPUT_TIM3
rcc_periph_clock_enable(RCC_TIM3);
- pwm_input_set_timer(TIM3);
+ pwm_input_set_timer(TIM3, PWM_INPUT_TIM3_TICKS_PER_USEC);
+#endif
+#if USE_PWM_INPUT_TIM5
+ rcc_periph_clock_enable(RCC_TIM5);
+ pwm_input_set_timer(TIM5, PWM_INPUT_TIM5_TICKS_PER_USEC);
+#endif
+#if USE_PWM_INPUT_TIM8
+ rcc_periph_clock_enable(RCC_TIM8);
+ pwm_input_set_timer(TIM8, PWM_INPUT_TIM8_TICKS_PER_USEC);
+#endif
+#if USE_PWM_INPUT_TIM9
+ rcc_periph_clock_enable(RCC_TIM9);
+ pwm_input_set_timer(TIM9, PWM_INPUT_TIM9_TICKS_PER_USEC);
#endif
#ifdef USE_PWM_INPUT1
@@ -165,6 +182,14 @@ void pwm_input_init(void)
}
+uint32_t get_pwm_input_duty_in_usec(uint32_t channel) {
+ return pwm_input_duty_tics[channel] / pwm_input_ticks_per_usec[channel];
+}
+
+uint32_t get_pwm_input_period_in_usec(uint32_t channel) {
+ return pwm_input_period_tics[channel] / pwm_input_ticks_per_usec[channel];
+}
+
#if USE_PWM_INPUT_TIM1
#if defined(STM32F1)
@@ -235,3 +260,76 @@ void tim3_isr(void) {
}
#endif
+
+#if USE_PWM_INPUT_TIM5
+
+void tim5_isr(void) {
+ if ((TIM5_SR & TIM5_CC_IF_PERIOD) != 0) {
+ timer_clear_flag(TIM5, TIM5_CC_IF_PERIOD);
+ pwm_input_period_tics[TIM5_PWM_INPUT_IDX] = TIM5_CCR_PERIOD;
+ pwm_input_period_valid[TIM5_PWM_INPUT_IDX] = TRUE;
+ }
+ if ((TIM5_SR & TIM5_CC_IF_DUTY) != 0) {
+ timer_clear_flag(TIM5, TIM5_CC_IF_DUTY);
+ pwm_input_duty_tics[TIM5_PWM_INPUT_IDX] = TIM5_CCR_DUTY;
+ pwm_input_duty_valid[TIM5_PWM_INPUT_IDX] = TRUE;
+ }
+ if ((TIM5_SR & TIM_SR_UIF) != 0) {
+ timer_clear_flag(TIM5, TIM_SR_UIF);
+ // FIXME clear overflow interrupt but what else ?
+ }
+}
+
+#endif
+
+#if USE_PWM_INPUT_TIM8
+
+#if defined(STM32F1)
+void tim8_up_isr(void)
+{
+#elif defined(STM32F4)
+void tim8_up_tim13_isr(void) {
+#endif
+ if ((TIM8_SR & TIM_SR_UIF) != 0) {
+ timer_clear_flag(TIM8, TIM_SR_UIF);
+ // FIXME clear overflow interrupt but what else ?
+ }
+}
+
+void tim8_cc_isr(void) {
+ if ((TIM8_SR & TIM8_CC_IF_PERIOD) != 0) {
+ timer_clear_flag(TIM8, TIM8_CC_IF_PERIOD);
+ pwm_input_period_tics[TIM8_PWM_INPUT_IDX] = TIM8_CCR_PERIOD;
+ pwm_input_period_valid[TIM8_PWM_INPUT_IDX] = TRUE;
+ }
+ if ((TIM8_SR & TIM8_CC_IF_DUTY) != 0) {
+ timer_clear_flag(TIM8, TIM8_CC_IF_DUTY);
+ pwm_input_duty_tics[TIM8_PWM_INPUT_IDX] = TIM8_CCR_DUTY;
+ pwm_input_duty_valid[TIM8_PWM_INPUT_IDX] = TRUE;
+ }
+}
+
+#endif
+
+#if USE_PWM_INPUT_TIM9
+
+// TIM1 break interrupt (which we don't care here) and TIM9 global interrupt
+void tim1_brk_tim9_isr(void) {
+ if ((TIM9_SR & TIM9_CC_IF_PERIOD) != 0) {
+ timer_clear_flag(TIM9, TIM9_CC_IF_PERIOD);
+ pwm_input_period_tics[TIM9_PWM_INPUT_IDX] = TIM9_CCR_PERIOD;
+ pwm_input_period_valid[TIM9_PWM_INPUT_IDX] = TRUE;
+ }
+ if ((TIM9_SR & TIM9_CC_IF_DUTY) != 0) {
+ timer_clear_flag(TIM9, TIM9_CC_IF_DUTY);
+ pwm_input_duty_tics[TIM9_PWM_INPUT_IDX] = TIM9_CCR_DUTY;
+ pwm_input_duty_valid[TIM9_PWM_INPUT_IDX] = TRUE;
+ }
+ if ((TIM9_SR & TIM_SR_UIF) != 0) {
+ timer_clear_flag(TIM9, TIM_SR_UIF);
+ // FIXME clear overflow interrupt but what else ?
+ }
+}
+
+#endif
+
diff --git a/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.h b/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.h
index be748c192c..8529d87b38 100644
--- a/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.h
+++ b/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.h
@@ -49,15 +49,13 @@ enum pwm_input_channels {
* TIM1 -> 2 * APB2 = 2 * 84MHz = 168MHz
* TIM2 -> 2 * APB1 = 2 * 42MHz = 84MHz
*/
-#ifndef PWM_INPUT_TICKS_PER_USEC
-#define PWM_INPUT_TICKS_PER_USEC 6
+#ifndef PWM_INPUT1_TICKS_PER_USEC
+#define PWM_INPUT1_TICKS_PER_USEC 6
#endif
-#define PWM_INPUT_TICKS_OF_USEC(_v) ((_v)*PWM_INPUT_TICKS_PER_USEC)
-#define PWM_INPUT_SIGNED_TICKS_OF_USEC(_v) (int32_t)((_v)*PWM_INPUT_TICKS_PER_USEC)
-#define USEC_OF_PWM_INPUT_TICKS(_v) ((_v)/PWM_INPUT_TICKS_PER_USEC)
-
-#include "mcu_periph/pwm_input.h"
+#ifndef PWM_INPUT2_TICKS_PER_USEC
+#define PWM_INPUT2_TICKS_PER_USEC 6
+#endif
#endif /* PWM_INPUT_ARCH_H */
diff --git a/sw/airborne/boards/apogee_1.0.h b/sw/airborne/boards/apogee_1.0.h
index b4702f77eb..84da460cf0 100644
--- a/sw/airborne/boards/apogee_1.0.h
+++ b/sw/airborne/boards/apogee_1.0.h
@@ -355,7 +355,11 @@
/*
* PWM input
*/
+// PWM_INPUT1 on TIM1
#define PWM_INPUT1_TIMER TIM1
+#ifdef PWM_INPUT1_TICKS_PER_USEC
+#define PWM_INPUT_TIM1_TICKS_PER_USEC PWM_INPUT1_TICKS_PER_USEC
+#endif
#define PWM_INPUT1_CHANNEL_PERIOD TIM_IC1
#define PWM_INPUT1_CHANNEL_DUTY TIM_IC2
#define PWM_INPUT1_TIMER_INPUT TIM_IC_IN_TI1
@@ -374,6 +378,35 @@
#define PWM_INPUT1_GPIO_PIN GPIO8
#define PWM_INPUT1_GPIO_AF GPIO_AF1
+// PWM_INPUT2 on TIM9
+#define PWM_INPUT2_TIMER TIM9
+#ifdef PWM_INPUT2_TICKS_PER_USEC
+#define PWM_INPUT_TIM9_TICKS_PER_USEC PWM_INPUT2_TICKS_PER_USEC
+#endif
+#define PWM_INPUT2_CHANNEL_PERIOD TIM_IC1
+#define PWM_INPUT2_CHANNEL_DUTY TIM_IC2
+#define PWM_INPUT2_TIMER_INPUT TIM_IC_IN_TI1
+#define PWM_INPUT2_SLAVE_TRIG TIM_SMCR_TS_IT1FP1
+#define PWM_INPUT2_IRQ NVIC_TIM1_BRK_TIM9_IRQ
+#define PWM_INPUT2_CC_IE (TIM_DIER_CC3IE | TIM_DIER_CC4IE)
+#ifdef USE_PWM_INPUT2
+#define USE_PWM_INPUT_TIM9 TRUE
+#else
+#define USE_PWM_INPUT_TIM9 FALSE
+#endif
+#define TIM9_PWM_INPUT_IDX 1
+#define TIM9_CC_IF_PERIOD TIM_SR_CC1IF
+#define TIM9_CC_IF_DUTY TIM_SR_CC2IF
+#define TIM9_CCR_PERIOD TIM9_CCR1
+#define TIM9_CCR_DUTY TIM9_CCR2
+// Servo 1 (aka PA2) is used: not compatible with PWM1 (and should be disabled)
+#if (USE_PWM1 && USE_PWM_INPUT2)
+#error "PW1 and PWM_INPUT2 are not compatible"
+#endif
+#define PWM_INPUT2_GPIO_PORT GPIOA
+#define PWM_INPUT2_GPIO_PIN GPIO2
+#define PWM_INPUT2_GPIO_AF GPIO_AF3
+
/*
* Spektrum
*/
diff --git a/sw/airborne/mcu_periph/pwm_input.c b/sw/airborne/mcu_periph/pwm_input.c
index ee02d32dc9..b39c877b30 100644
--- a/sw/airborne/mcu_periph/pwm_input.c
+++ b/sw/airborne/mcu_periph/pwm_input.c
@@ -30,3 +30,6 @@ volatile uint32_t pwm_input_duty_tics[PWM_INPUT_NB];
volatile uint8_t pwm_input_duty_valid[PWM_INPUT_NB];
volatile uint32_t pwm_input_period_tics[PWM_INPUT_NB];
volatile uint8_t pwm_input_period_valid[PWM_INPUT_NB];
+
+__attribute__((weak)) uint32_t get_pwm_input_duty_in_usec(uint32_t channel __attribute__((unused))) { return 0; }
+__attribute__((weak)) uint32_t get_pwm_input_period_in_usec(uint32_t channel __attribute__((unused))) { return 0; }
diff --git a/sw/airborne/mcu_periph/pwm_input.h b/sw/airborne/mcu_periph/pwm_input.h
index 88f8e727fd..621948e13e 100644
--- a/sw/airborne/mcu_periph/pwm_input.h
+++ b/sw/airborne/mcu_periph/pwm_input.h
@@ -41,6 +41,8 @@ extern volatile uint32_t pwm_input_period_tics[PWM_INPUT_NB];
extern volatile uint8_t pwm_input_period_valid[PWM_INPUT_NB];
extern void pwm_input_init(void);
+extern uint32_t get_pwm_input_duty_in_usec(uint32_t channel);
+extern uint32_t get_pwm_input_period_in_usec(uint32_t channel);
#endif /* USE_PWM_INPUT */
diff --git a/sw/airborne/modules/sensors/aoa_pwm.c b/sw/airborne/modules/sensors/aoa_pwm.c
index bde6e0f065..0ce31d7345 100644
--- a/sw/airborne/modules/sensors/aoa_pwm.c
+++ b/sw/airborne/modules/sensors/aoa_pwm.c
@@ -113,7 +113,7 @@ void aoa_pwm_update(void) {
static float prev_aoa = 0.0f;
// raw duty cycle in usec
- uint32_t duty_raw = pwm_input_duty_tics[AOA_PWM_CHANNEL] / PWM_INPUT_TICKS_PER_USEC;
+ uint32_t duty_raw = get_pwm_input_duty_in_usec(AOA_PWM_CHANNEL);
// remove some offset if needed
aoa_pwm.raw = duty_raw - AOA_PWM_OFFSET;