mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-26 16:30:07 +08:00
[pwm_input] add a few timers and a second pwm_input for apogee
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
<makefile target="ap">
|
||||
<file name="aoa_pwm.c" />
|
||||
<define name="AOA_PWM_CHANNEL" value="$(AOA_PWM_CHANNEL)" cond="ifdef AOA_PWM_CHANNEL" />
|
||||
<define name="PWM_INPUT_TICKS_PER_USEC" value="1" />
|
||||
<define name="$(AOA_PWM_CHANNEL)_TICKS_PER_USEC" value="1" />
|
||||
<define name="USE_$(AOA_PWM_CHANNEL)" value="PWM_PULSE_TYPE_ACTIVE_LOW" />
|
||||
</makefile>
|
||||
</module>
|
||||
|
||||
@@ -71,8 +71,8 @@ MS_SPI_DEV_LOWER=$(shell echo $(MS_SPI_DEV) | tr A-Z a-z)
|
||||
<define name="USE_SPI_SLAVE$(MS_EEPROM_SLAVE_IDX)" cond="ifdef MS_EEPROM_SLAVE_IDX"/>
|
||||
<define name="MS_SPI_DEV" value="$(MS_SPI_DEV_LOWER)"/>
|
||||
<define name="MS_HUMIDITY_PWM_INPUT" value="$(MS_HUMIDITY_PWM_INPUT)" cond="ifdef MS_HUMIDITY_PWM_INPUT"/>
|
||||
<define name="PWM_INPUT_TICKS_PER_USEC" value="42" cond="ifdef MS_HUMIDITY_PWM_INPUT"/> <!-- set timer clock to 42 MHz -->
|
||||
<define name="USE_$(MS_HUMIDITY_PWM_INPUT)" value="PWM_PULSE_TYPE_ACTIVE_LOW" cond="ifdef MS_MS_HUMIDITY_PWM_INPUT"/>
|
||||
<define name="$(MS_HUMIDITY_PWM_INPUT)_TICKS_PER_USEC" value="42" cond="ifdef MS_HUMIDITY_PWM_INPUT"/> <!-- set timer clock to 42 MHz -->
|
||||
<define name="USE_$(MS_HUMIDITY_PWM_INPUT)" value="PWM_PULSE_TYPE_ACTIVE_LOW" cond="ifdef MS_HUMIDITY_PWM_INPUT"/>
|
||||
</makefile>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user