diff --git a/conf/boards/lisa_m_2.0.makefile b/conf/boards/lisa_m_2.0.makefile index d77dffe28d2..5de7c769dad 100644 --- a/conf/boards/lisa_m_2.0.makefile +++ b/conf/boards/lisa_m_2.0.makefile @@ -101,3 +101,10 @@ endif ifndef ADC_IR_NB_SAMPLES ADC_IR_NB_SAMPLES = 16 endif + +# default PPM CAPTURE configuration +ifndef RADIO_CONTROL_PPM_PIN +RADIO_CONTROL_PPM_PIN = SERVO6 +# RADIO_CONTROL_PPM_PIN = UART1 +endif + diff --git a/conf/firmwares/subsystems/shared/radio_control_ppm.makefile b/conf/firmwares/subsystems/shared/radio_control_ppm.makefile index 41b7f90729f..055335d6e00 100644 --- a/conf/firmwares/subsystems/shared/radio_control_ppm.makefile +++ b/conf/firmwares/subsystems/shared/radio_control_ppm.makefile @@ -1,5 +1,5 @@ # -# Makefile for shared radio_control ppm susbsytem +# Makefile for shared radio_control ppm subsystem # NORADIO = False @@ -14,6 +14,7 @@ ifeq ($(NORADIO), False) $(TARGET).CFLAGS += -DRADIO_CONTROL ifneq ($(RADIO_CONTROL_LED),none) ap.CFLAGS += -DRADIO_CONTROL_LED=$(RADIO_CONTROL_LED) + fbw.CFLAGS += -DRADIO_CONTROL_LED=$(RADIO_CONTROL_LED) endif $(TARGET).CFLAGS += -DRADIO_CONTROL_TYPE_H=\"subsystems/radio_control/ppm.h\" $(TARGET).CFLAGS += -DRADIO_CONTROL_TYPE_PPM @@ -22,6 +23,15 @@ ifeq ($(NORADIO), False) $(TARGET).srcs += $(SRC_ARCH)/subsystems/radio_control/ppm_arch.c ifeq ($(ARCH),stm32) - ap.CFLAGS += -DUSE_TIM2_IRQ + ifeq ($(RADIO_CONTROL_PPM_PIN),UART1) + ap.CFLAGS += -DUSE_TIM1_IRQ + fbw.CFLAGS += -DUSE_TIM1_IRQ + else ifeq ($(RADIO_CONTROL_PPM_PIN),SERVO6) + ap.CFLAGS += -DUSE_TIM2_IRQ + fbw.CFLAGS += -DUSE_TIM2_IRQ + else + $(error unknown configuration for RADIO_CONTROL_PPM_PIN) + endif endif endif + diff --git a/sw/airborne/arch/stm32/stm32_vector_table.c b/sw/airborne/arch/stm32/stm32_vector_table.c index a3f0ca529e6..6cd81a7ab65 100644 --- a/sw/airborne/arch/stm32/stm32_vector_table.c +++ b/sw/airborne/arch/stm32/stm32_vector_table.c @@ -159,6 +159,16 @@ extern void adc1_2_irq_handler(void); #define ADC1_2_IRQ_HANDLER null_handler #endif +#ifdef USE_TIM1_IRQ + extern void tim1_up_irq_handler(void); + extern void tim1_cc_irq_handler(void); +#define TIM1_UP_IRQ_HANDLER tim1_up_irq_handler +#define TIM1_CC_IRQ_HANDLER tim1_cc_irq_handler +#else +#define TIM1_UP_IRQ_HANDLER null_handler +#define TIM1_CC_IRQ_HANDLER null_handler +#endif + #ifdef USE_TIM2_IRQ extern void tim2_irq_handler(void); #define TIM2_IRQ_HANDLER tim2_irq_handler @@ -241,9 +251,9 @@ void (* const vector_table[])(void) = { null_handler, /* can_sce_irq_handler */ EXTI9_5_IRQ_HANDLER, /* exti9_5_irq_handler */ null_handler, /* tim1_brk_irq_handler */ - null_handler, /* tim1_up_irq_handler */ + TIM1_UP_IRQ_HANDLER, /* tim1_up_irq_handler */ null_handler, /* tim1_trg_com_irq_handler */ - null_handler, /* tim1_cc_irq_handler */ + TIM1_CC_IRQ_HANDLER, /* tim1_cc_irq_handler */ TIM2_IRQ_HANDLER, /* tim2_irq_handler */ null_handler, /* tim3_irq_handler */ null_handler, /* tim4_irq_handler */ diff --git a/sw/airborne/arch/stm32/subsystems/radio_control/ppm_arch.c b/sw/airborne/arch/stm32/subsystems/radio_control/ppm_arch.c index 97059d8bbce..82fa54316e6 100644 --- a/sw/airborne/arch/stm32/subsystems/radio_control/ppm_arch.c +++ b/sw/airborne/arch/stm32/subsystems/radio_control/ppm_arch.c @@ -32,29 +32,50 @@ #include "mcu_periph/sys_time.h" /* - * - * This a radio control ppm driver for stm32 - * signal on PA1 TIM2/CH2 (uart1 trig on lisa/L) - * - */ -uint8_t ppm_cur_pulse; +* +* This a radio control ppm driver for stm32 +* Either on: +* signal on PA1 TIM2/CH2 (uart1 trig on lisa/L) (Servo 6 on Lisa/M2) +* or signal on PA10 TIM1/CH3 (uart1 trig on lisa/L) (uart1 rx on Lisa/M2) +* +*/ +uint8_t ppm_cur_pulse; uint32_t ppm_last_pulse_time; -bool_t ppm_data_valid; +bool_t ppm_data_valid; static uint32_t timer_rollover_cnt; +#ifdef USE_TIM1_IRQ +#pragma message "UART1 RX pin is used for PPM input" +void tim1_up_irq_handler(void); +void tim1_cc_irq_handler(void); +#endif + +#ifdef USE_TIM2_IRQ +#pragma message "Servo pin 6 is used for PPM input" void tim2_irq_handler(void); +#endif -void ppm_arch_init ( void ) { - /* TIM2 channel 2 pin (PA.01) configuration */ +void ppm_arch_init ( void ) { GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; +#ifdef USE_TIM1_IRQ + /* TIM1 channel 3 pin (PA.10) configuration */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; +#elif defined USE_TIM2_IRQ + /* TIM2 channel 2 pin (PA.01) configuration */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; +#endif GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); +#ifdef USE_TIM1_IRQ + /* TIM1 clock enable */ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); +#elif defined USE_TIM2_IRQ /* TIM2 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); +#endif /* GPIOA clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); @@ -62,37 +83,69 @@ void ppm_arch_init ( void ) { /* Time Base configuration */ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); - TIM_TimeBaseStructure.TIM_Period = 0xFFFF; - TIM_TimeBaseStructure.TIM_Prescaler = 0x8; + TIM_TimeBaseStructure.TIM_Period = 0xFFFF; + TIM_TimeBaseStructure.TIM_Prescaler = 0x8; TIM_TimeBaseStructure.TIM_ClockDivision = 0x0; - TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; +#ifdef USE_TIM1_IRQ + TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); +#elif defined USE_TIM2_IRQ TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); - - /* TIM2 configuration: Input Capture mode --------------------- - The external signal is connected to TIM2 CH2 pin (PA.01) - The Rising edge is used as active edge, - ------------------------------------------------------------ */ - TIM_ICInitTypeDef TIM_ICInitStructure; +#endif + +/* TIM2 configuration: Input Capture mode --------------------- +The external signal is connected to TIM2 CH2 pin (PA.01) +TIM1 configuration: Input Capture mode --------------------- +The external signal is connected to TIM1 CH3 pin (PA.10) +The Rising edge is used as active edge, +------------------------------------------------------------ */ + TIM_ICInitTypeDef TIM_ICInitStructure; +#ifdef USE_TIM1_IRQ + TIM_ICInitStructure.TIM_Channel = TIM_Channel_3; +#elif defined USE_TIM2_IRQ TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; +#endif TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x00; +#ifdef USE_TIM1_IRQ + TIM_ICInit(TIM1, &TIM_ICInitStructure); +#elif defined USE_TIM2_IRQ TIM_ICInit(TIM2, &TIM_ICInitStructure); - +#endif + /* Enable the TIM1 global Interrupt */ /* Enable the TIM2 global Interrupt */ NVIC_InitTypeDef NVIC_InitStructure; +#ifdef USE_TIM1_IRQ + NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn; +#elif defined USE_TIM2_IRQ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; +#endif NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); +#ifdef USE_TIM1_IRQ + NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; + NVIC_Init(&NVIC_InitStructure); +#endif +#ifdef USE_TIM1_IRQ + /* TIM1 enable counter */ + TIM_Cmd(TIM1, ENABLE); +#elif defined USE_TIM2_IRQ /* TIM2 enable counter */ TIM_Cmd(TIM2, ENABLE); +#endif +#ifdef USE_TIM1_IRQ + /* Enable the CC3 Interrupt Request */ + TIM_ITConfig(TIM1, TIM_IT_CC3|TIM_IT_Update, ENABLE); +#elif defined USE_TIM2_IRQ /* Enable the CC2 Interrupt Request */ TIM_ITConfig(TIM2, TIM_IT_CC2|TIM_IT_Update, ENABLE); +#endif ppm_last_pulse_time = 0; ppm_cur_pulse = RADIO_CONTROL_NB_CHANNEL; @@ -100,18 +153,32 @@ void ppm_arch_init ( void ) { } +#ifdef USE_TIM1_IRQ +void tim1_up_irq_handler(void) { + if(TIM_GetITStatus(TIM1, TIM_IT_Update) == SET) { + timer_rollover_cnt+=(1<<16); + TIM_ClearITPendingBit(TIM1, TIM_IT_Update); + } +} -void tim2_irq_handler(void) { - - if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET) { - TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); +void tim1_cc_irq_handler(void) { + if(TIM_GetITStatus(TIM1, TIM_IT_CC3) == SET) { + TIM_ClearITPendingBit(TIM1, TIM_IT_CC3); - uint32_t now = TIM_GetCapture2(TIM2) + timer_rollover_cnt; + uint32_t now = TIM_GetCapture3(TIM1) + timer_rollover_cnt; DecodePpmFrame(now); } +} +#elif defined USE_TIM2_IRQ +void tim2_irq_handler(void) { + if(TIM_GetITStatus(TIM2, TIM_IT_CC2) == SET) { + TIM_ClearITPendingBit(TIM2, TIM_IT_CC2); + uint32_t now = TIM_GetCapture2(TIM2) + timer_rollover_cnt; + DecodePpmFrame(now); + } else if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) { timer_rollover_cnt+=(1<<16); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } - } +#endif