5 * th9x - http://code.google.com/p/th9x
6 * er9x - http://code.google.com/p/er9x
7 * gruvin9x - http://code.google.com/p/gruvin9x
9 * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
23 bool sticks_pwm_disabled
= false;
24 volatile uint32_t pwm_interrupt_count
;
25 volatile uint16_t timer_capture_values
[NUM_PWMSTICKS
];
29 GPIO_InitTypeDef GPIO_InitStructure
;
30 GPIO_InitStructure
.GPIO_Pin
= PWM_GPIOA_PINS
;
31 GPIO_InitStructure
.GPIO_Mode
= GPIO_Mode_AF
;
32 GPIO_InitStructure
.GPIO_Speed
= GPIO_Speed_50MHz
;
33 GPIO_InitStructure
.GPIO_OType
= GPIO_OType_PP
;
34 GPIO_InitStructure
.GPIO_PuPd
= GPIO_PuPd_UP
;
35 GPIO_Init(PWM_GPIO
, &GPIO_InitStructure
);
37 GPIO_PinAFConfig(PWM_GPIO
, GPIO_PinSource0
, PWM_GPIO_AF
);
38 GPIO_PinAFConfig(PWM_GPIO
, GPIO_PinSource1
, PWM_GPIO_AF
);
39 GPIO_PinAFConfig(PWM_GPIO
, GPIO_PinSource2
, PWM_GPIO_AF
);
40 GPIO_PinAFConfig(PWM_GPIO
, GPIO_PinSource3
, PWM_GPIO_AF
);
42 PWM_TIMER
->CR1
&= ~TIM_CR1_CEN
; // Stop timer
44 PWM_TIMER
->ARR
= 0xffff;
45 PWM_TIMER
->CCMR1
= TIM_CCMR1_CC1S_0
| TIM_CCMR1_CC2S_0
;
46 PWM_TIMER
->CCMR2
= TIM_CCMR2_CC3S_0
| TIM_CCMR2_CC4S_0
;
47 PWM_TIMER
->CCER
= TIM_CCER_CC1E
| TIM_CCER_CC2E
| TIM_CCER_CC3E
| TIM_CCER_CC4E
;
48 PWM_TIMER
->DIER
|= TIM_IT_CC1
|TIM_IT_CC2
|TIM_IT_CC3
|TIM_IT_CC4
;
49 PWM_TIMER
->CR1
= TIM_CR1_CEN
; // Start timer
51 NVIC_EnableIRQ(PWM_IRQn
);
52 NVIC_SetPriority(PWM_IRQn
, 10);
55 inline uint32_t TIM_GetCapture_Stick(uint8_t n
)
59 return PWM_TIMER
->CCR1
;
61 return PWM_TIMER
->CCR2
;
63 return PWM_TIMER
->CCR3
;
65 return PWM_TIMER
->CCR4
;
71 inline void TIM_SetPolarityRising(uint8_t n
)
73 PWM_TIMER
->CCER
&= ~(TIM_CCER_CC1P
<< (n
* 4));
76 inline void TIM_SetPolarityFalling(uint8_t n
)
78 PWM_TIMER
->CCER
|= (TIM_CCER_CC1P
<< (n
* 4));
81 inline void TIM_ClearITPendingBit(uint8_t n
)
83 PWM_TIMER
->SR
= ~(TIM_IT_CC1
<< n
);
86 inline uint32_t diff_with_16bits_overflow(uint32_t a
, uint32_t b
)
91 return b
+ 0xffff - a
;
94 extern "C" void PWM_IRQHandler(void)
96 static uint8_t timer_capture_states
[NUM_PWMSTICKS
];
97 static uint32_t timer_capture_rising_time
[NUM_PWMSTICKS
];
99 for (uint8_t i
=0; i
<NUM_PWMSTICKS
; i
++) {
100 if (PWM_TIMER
->SR
& (TIM_DIER_CC1IE
<< i
)) {
101 uint32_t capture
= TIM_GetCapture_Stick(i
);
102 pwm_interrupt_count
++; // overflow may happen but we only use this to detect PWM / ADC on radio startup
103 if (timer_capture_states
[i
] != 0) {
104 uint32_t value
= diff_with_16bits_overflow(timer_capture_rising_time
[i
], capture
);
106 timer_capture_values
[i
] = (uint16_t) value
;
108 TIM_SetPolarityRising(i
);
109 timer_capture_states
[i
] = 0;
112 timer_capture_rising_time
[i
] = capture
;
113 TIM_SetPolarityFalling(i
);
114 timer_capture_states
[i
] = 0x80;
116 TIM_ClearITPendingBit(i
);
121 void sticksPwmRead(uint16_t * values
)
123 values
[0] = timer_capture_values
[0];
124 values
[1] = timer_capture_values
[1];
125 values
[2] = timer_capture_values
[3];
126 values
[3] = timer_capture_values
[2];