3636
3737#include "timers.h"
3838
39- #define ALL_CLOCKS 0xFFFF
40-
41- STATIC uint8_t reserved_tim [ TIM_BANK_ARRAY_LEN ];
39+ // Bitmask of channels taken.
40+ STATIC uint8_t tim_channels_taken [ TIM_BANK_ARRAY_LEN ];
41+ // Initial frequency timer is set to.
4242STATIC uint32_t tim_frequencies [TIM_BANK_ARRAY_LEN ];
4343STATIC bool never_reset_tim [TIM_BANK_ARRAY_LEN ];
4444
4545STATIC uint32_t timer_get_internal_duty (uint16_t duty , uint32_t period ) {
4646 // duty cycle is duty/0xFFFF fraction x (number of pulses per period)
47- return (duty * period ) / (( 1 << 16 ) - 1 ) ;
47+ return (duty * period ) / 0xffff ;
4848}
4949
5050STATIC bool timer_get_optimal_divisors (uint32_t * period , uint32_t * prescaler ,
5151 uint32_t frequency , uint32_t source_freq ) {
5252 // Find the largest possible period supported by this frequency
53- for (int i = 0 ; i < (1 << 16 ); i ++ ) {
53+ * prescaler = 0 ;
54+ for (uint32_t i = 1 ; i <= 0xffff ; i ++ ) {
5455 * period = source_freq / (i * frequency );
55- if (* period < ( 1 << 16 ) && * period >= 2 ) {
56+ if (* period <= 0xffff && * period >= 2 ) {
5657 * prescaler = i ;
5758 break ;
5859 }
@@ -62,13 +63,10 @@ STATIC bool timer_get_optimal_divisors(uint32_t *period, uint32_t *prescaler,
6263}
6364
6465void pwmout_reset (void ) {
65- uint16_t never_reset_mask = 0x00 ;
6666 for (int i = 0 ; i < TIM_BANK_ARRAY_LEN ; i ++ ) {
6767 if (!never_reset_tim [i ]) {
68- reserved_tim [i ] = 0x00 ;
69- tim_frequencies [i ] = 0x00 ;
70- } else {
71- never_reset_mask |= 1 << i ;
68+ tim_channels_taken [i ] = 0x00 ;
69+ tim_frequencies [i ] = 0 ;
7270 }
7371 }
7472}
@@ -78,73 +76,69 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
7876 uint16_t duty ,
7977 uint32_t frequency ,
8078 bool variable_frequency ) {
81- TIM_TypeDef * TIMx ;
82- uint8_t tim_num = MP_ARRAY_SIZE (mcu_tim_pin_list );
83- bool tim_taken_internal = false;
84- bool tim_chan_taken = false;
85- bool tim_taken_f_mismatch = false;
86- bool var_freq_mismatch = false;
79+ // Default error is no timer at all on pin.
80+ pwmout_result_t last_failure = PWMOUT_INVALID_PIN ;
8781 bool first_time_setup = true;
8882
89- for (uint i = 0 ; i < tim_num ; i ++ ) {
90- const mcu_tim_pin_obj_t * l_tim = & mcu_tim_pin_list [i ];
91- uint8_t l_tim_index = l_tim -> tim_index ;
92- uint8_t l_tim_channel = l_tim -> channel_index ;
83+ uint8_t tim_index ;
84+ uint8_t tim_channel_index ;
85+
86+ self -> tim = NULL ;
87+ for (uint i = 0 ; i < MP_ARRAY_SIZE (mcu_tim_pin_list ); i ++ ) {
88+ const mcu_tim_pin_obj_t * tim = & mcu_tim_pin_list [i ];
89+ tim_index = tim -> tim_index ;
90+ tim_channel_index = tim -> channel_index ;
9391
9492 // if pin is same
95- if (l_tim -> pin == pin ) {
93+ if (tim -> pin == pin ) {
9694 // check if the timer has a channel active, or is reserved by main timer system
97- if (l_tim_index < TIM_BANK_ARRAY_LEN && reserved_tim [ l_tim_index ] != 0 ) {
95+ if (tim_index < TIM_BANK_ARRAY_LEN && tim_channels_taken [ tim_index ] != 0 ) {
9896 // Timer has already been reserved by an internal module
99- if (stm_peripherals_timer_is_reserved (mcu_tim_banks [l_tim_index ])) {
100- tim_taken_internal = true ;
97+ if (stm_peripherals_timer_is_reserved (mcu_tim_banks [tim_index ])) {
98+ last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE ;
10199 continue ; // keep looking
102100 }
103101 // is it the same channel? (or all channels reserved by a var-freq)
104- if (reserved_tim [ l_tim_index ] & 1 << ( l_tim_channel )) {
105- tim_chan_taken = true ;
102+ if (tim_channels_taken [ tim_index ] & ( 1 << tim_channel_index )) {
103+ last_failure = PWMOUT_ALL_TIMERS_ON_PIN_IN_USE ;
106104 continue ; // keep looking, might be another viable option
107105 }
108106 // If the frequencies are the same it's ok
109- if (tim_frequencies [l_tim_index ] != frequency ) {
110- tim_taken_f_mismatch = true ;
107+ if (tim_frequencies [tim_index ] != frequency ) {
108+ last_failure = PWMOUT_INVALID_FREQUENCY_ON_PIN ;
111109 continue ; // keep looking
112110 }
113111 // you can't put a variable frequency on a partially reserved timer
114112 if (variable_frequency ) {
115- var_freq_mismatch = true ;
113+ last_failure = PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE ;
116114 continue ; // keep looking
117115 }
118116 first_time_setup = false; // skip setting up the timer
119117 }
120118 // No problems taken, so set it up
121- self -> tim = l_tim ;
119+ self -> tim = tim ;
122120 break ;
123121 }
124122 }
125123
124+ TIM_TypeDef * TIMx ;
125+
126126 // handle valid/invalid timer instance
127127 if (self -> tim != NULL ) {
128128 // create instance
129- TIMx = mcu_tim_banks [self -> tim -> tim_index ];
129+ TIMx = mcu_tim_banks [tim_index ];
130130 // reserve timer/channel
131131 if (variable_frequency ) {
132- reserved_tim [self -> tim -> tim_index ] = 0x0F ;
132+ // Take all the channels.
133+ tim_channels_taken [tim_index ] = 0x0F ;
133134 } else {
134- reserved_tim [ self -> tim -> tim_index ] |= 1 << self -> tim -> channel_index ;
135+ tim_channels_taken [ tim_index ] |= 1 << tim_channel_index ;
135136 }
136- tim_frequencies [self -> tim -> tim_index ] = frequency ;
137+ tim_frequencies [tim_index ] = frequency ;
137138 stm_peripherals_timer_reserve (TIMx );
138- } else { // no match found
139- if (tim_chan_taken || tim_taken_internal ) {
140- return PWMOUT_ALL_TIMERS_ON_PIN_IN_USE ;
141- } else if (tim_taken_f_mismatch ) {
142- return PWMOUT_INVALID_FREQUENCY_ON_PIN ;
143- } else if (var_freq_mismatch ) {
144- return PWMOUT_VARIABLE_FREQUENCY_NOT_AVAILABLE ;
145- } else {
146- return PWMOUT_INVALID_PIN ;
147- }
139+ } else {
140+ // no match found
141+ return last_failure ;
148142 }
149143
150144 uint32_t prescaler = 0 ; // prescaler is 15 bit
@@ -163,10 +157,10 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
163157 HAL_GPIO_Init (pin_port (pin -> port ), & GPIO_InitStruct );
164158 self -> pin = pin ;
165159
166- tim_clock_enable (1 << ( self -> tim -> tim_index ) );
160+ tim_clock_enable (1 << tim_index );
167161
168- // translate channel into handle value
169- self -> channel = 4 * self -> tim -> channel_index ;
162+ // translate channel into handle value: TIM_CHANNEL_1, _2, _3, _4.
163+ self -> channel = 4 * tim_channel_index ;
170164
171165 // Timer init
172166 self -> handle .Instance = TIMx ;
@@ -175,6 +169,7 @@ pwmout_result_t common_hal_pwmio_pwmout_construct(pwmio_pwmout_obj_t *self,
175169 self -> handle .Init .ClockDivision = TIM_CLOCKDIVISION_DIV1 ;
176170 self -> handle .Init .CounterMode = TIM_COUNTERMODE_UP ;
177171 self -> handle .Init .RepetitionCounter = 0 ;
172+ self -> handle .Init .AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE ;
178173
179174 // only run init if this is the first instance of this timer
180175 if (first_time_setup ) {
@@ -232,15 +227,15 @@ void common_hal_pwmio_pwmout_deinit(pwmio_pwmout_obj_t *self) {
232227 }
233228 // var freq shuts down entire timer, others just their channel
234229 if (self -> variable_frequency ) {
235- reserved_tim [self -> tim -> tim_index ] = 0x00 ;
230+ tim_channels_taken [self -> tim -> tim_index ] = 0x00 ;
236231 } else {
237- reserved_tim [self -> tim -> tim_index ] &= ~(1 << self -> tim -> channel_index );
232+ tim_channels_taken [self -> tim -> tim_index ] &= ~(1 << self -> tim -> channel_index );
238233 HAL_TIM_PWM_Stop (& self -> handle , self -> channel );
239234 }
240235 common_hal_reset_pin (self -> pin );
241236
242237 // if reserved timer has no active channels, we can disable it
243- if (reserved_tim [self -> tim -> tim_index ] == 0 ) {
238+ if (tim_channels_taken [self -> tim -> tim_index ] == 0 ) {
244239 tim_frequencies [self -> tim -> tim_index ] = 0x00 ;
245240 stm_peripherals_timer_free (self -> handle .Instance );
246241 }
0 commit comments