35
35
#include "stm32f4xx_hal.h"
36
36
#include "common-hal/microcontroller/Pin.h"
37
37
38
- #define PWM_MAX_FREQ 6000000
38
+ #define PULSE_RESOLUTION 256 //8 bit
39
39
#define ALL_CLOCKS 0xFFFF
40
40
41
41
STATIC uint8_t reserved_tim [TIM_BANK_ARRAY_LEN ];
@@ -45,8 +45,6 @@ STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN];
45
45
STATIC void tim_clock_enable (uint16_t mask );
46
46
STATIC void tim_clock_disable (uint16_t mask );
47
47
48
- RCC -> CFGR & RCC_CFGR_PPRE1
49
-
50
48
// Get the frequency (in Hz) of the source clock for the given timer.
51
49
// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set.
52
50
// If the APB prescaler is 1, then the timer clock is equal to its respective
@@ -107,10 +105,6 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
107
105
uint16_t duty ,
108
106
uint32_t frequency ,
109
107
bool variable_frequency ) {
110
- if (frequency == 0 || frequency > 6000000 ) {
111
- mp_raise_ValueError (translate ("Invalid frequency supplied" ));
112
- }
113
-
114
108
TIM_TypeDef * TIMx ;
115
109
uint8_t tim_num = sizeof (mcu_tim_pin_list )/sizeof (* mcu_tim_pin_list );
116
110
bool tim_chan_taken = false;
@@ -189,43 +183,49 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
189
183
}
190
184
191
185
uint32_t source_freq = timer_get_source_freq (self -> tim -> tim_index );
192
- uint32_t period = PWM_MAX_FREQ /frequency ;
186
+ if (frequency == 0 || frequency * PULSE_RESOLUTION > (source_freq )) {
187
+ mp_raise_ValueError (translate ("Invalid frequency supplied" ));
188
+ }
189
+ uint32_t prescaler = source_freq /(frequency * PULSE_RESOLUTION );
190
+ uint32_t period = PULSE_RESOLUTION ;
191
+ uint32_t input = (duty * PULSE_RESOLUTION )/65535 ;
193
192
//Used for Debugging
194
- // mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock);
195
- // mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq);
196
- // mp_printf(&mp_plat_print, "Timer Freq: %d\n", source_freq/(source_freq / PWM_MAX_FREQ));
197
- // mp_printf(&mp_plat_print, "Actual Freq: %d\n", (source_freq/(source_freq / PWM_MAX_FREQ))/period);
198
- // mp_printf(&mp_plat_print, "Duty: %d\n", duty);
199
- // mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index);
193
+ mp_printf (& mp_plat_print , "Duty:%d, Pulses:%d\n" , duty ,input );
194
+ mp_printf (& mp_plat_print , "SysCoreClock: %d\n" , SystemCoreClock );
195
+ mp_printf (& mp_plat_print , "Source Freq: %d\n" , source_freq );
196
+ mp_printf (& mp_plat_print , "Prescaler %d, Timer Freq: %d\n" , prescaler , source_freq /prescaler );
197
+ mp_printf (& mp_plat_print , "Output Freq: %d\n" , (source_freq /prescaler )/period );
198
+ mp_printf (& mp_plat_print , "Duty: %d\n" , duty );
199
+ mp_printf (& mp_plat_print , "TIM#:%d CH:%d ALTF:%d\n" , self -> tim -> tim_index , self -> tim -> channel_index , self -> tim -> altfn_index );
200
200
201
201
//Timer init
202
202
self -> handle .Instance = TIMx ;
203
203
self -> handle .Init .Period = period - 1 ;
204
- self -> handle .Init .Prescaler = ( source_freq / PWM_MAX_FREQ ) - 1 ; // TIM runs at ~6MHz
204
+ self -> handle .Init .Prescaler = prescaler - 1 ;
205
205
self -> handle .Init .ClockDivision = TIM_CLOCKDIVISION_DIV1 ;
206
206
self -> handle .Init .CounterMode = TIM_COUNTERMODE_UP ;
207
207
self -> handle .Init .RepetitionCounter = 0 ;
208
208
209
209
//only run init if this is the first instance of this timer
210
210
if (first_time_setup ) {
211
211
if (HAL_TIM_PWM_Init (& self -> handle ) != HAL_OK ) {
212
- mp_raise_ValueError (translate ("Timer Init Error " ));
212
+ mp_raise_ValueError (translate ("Could not initialize timer " ));
213
213
}
214
214
}
215
215
216
216
//Channel/PWM init
217
217
self -> chan_handle .OCMode = TIM_OCMODE_PWM1 ;
218
- self -> chan_handle .Pulse = ( period * duty )/ 100 - 1 ;
218
+ self -> chan_handle .Pulse = input ; //-1?
219
219
self -> chan_handle .OCPolarity = TIM_OCPOLARITY_LOW ;
220
220
self -> chan_handle .OCFastMode = TIM_OCFAST_DISABLE ;
221
221
self -> chan_handle .OCNPolarity = TIM_OCNPOLARITY_LOW ; // needed for TIM1 and TIM8
222
222
self -> chan_handle .OCIdleState = TIM_OCIDLESTATE_SET ; // needed for TIM1 and TIM8
223
223
self -> chan_handle .OCNIdleState = TIM_OCNIDLESTATE_SET ; // needed for TIM1 and TIM8
224
224
if (HAL_TIM_PWM_ConfigChannel (& self -> handle , & self -> chan_handle , self -> channel ) != HAL_OK ) {
225
- mp_raise_ValueError (translate ("Channel Init Error " ));
225
+ mp_raise_ValueError (translate ("Could not initialize channel " ));
226
226
}
227
227
if (HAL_TIM_PWM_Start (& self -> handle , self -> channel ) != HAL_OK ) {
228
- mp_raise_ValueError (translate ("Error starting PWM" ));
228
+ mp_raise_ValueError (translate ("Could not start PWM" ));
229
229
}
230
230
231
231
self -> variable_frequency = variable_frequency ;
@@ -261,46 +261,51 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
261
261
}
262
262
263
263
void common_hal_pulseio_pwmout_set_duty_cycle (pulseio_pwmout_obj_t * self , uint16_t duty_cycle ) {
264
- uint16_t duty = duty_cycle /655 ;
265
- uint32_t period = PWM_MAX_FREQ /self -> frequency ;
266
- uint32_t input = (period * duty )/100 ;
264
+ uint32_t input = (duty_cycle * PULSE_RESOLUTION )/65535 ;
267
265
//Used for debugging
268
266
//mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input);
269
267
__HAL_TIM_SET_COMPARE (& self -> handle , self -> channel , input );
270
268
271
- self -> duty_cycle = duty ;
269
+ self -> duty_cycle = duty_cycle ;
272
270
}
273
271
274
272
uint16_t common_hal_pulseio_pwmout_get_duty_cycle (pulseio_pwmout_obj_t * self ) {
275
273
return self -> duty_cycle ;
276
274
}
277
275
278
276
void common_hal_pulseio_pwmout_set_frequency (pulseio_pwmout_obj_t * self , uint32_t frequency ) {
279
- if (frequency == 0 || frequency > 6000000 ) {
280
- mp_raise_ValueError (translate ("Invalid PWM frequency" ));
281
- }
277
+ //don't halt setup for the same frequency
282
278
if (frequency == self -> frequency ) return ;
283
279
280
+ //calculate new values
284
281
uint32_t source_freq = timer_get_source_freq (self -> tim -> tim_index );
285
- uint32_t period = PWM_MAX_FREQ /frequency ;
282
+ if (frequency == 0 || frequency * PULSE_RESOLUTION > (source_freq )) {
283
+ mp_raise_ValueError (translate ("Invalid frequency supplied" ));
284
+ }
285
+ uint32_t prescaler = source_freq /(frequency * PULSE_RESOLUTION );
286
+ uint32_t period = PULSE_RESOLUTION ;
287
+ //this shouldn't ever exceed 0xffff*0xffff = 0xfffe0001, so it won't integer overflow.
288
+ uint32_t input = (self -> duty_cycle * PULSE_RESOLUTION )/65535 ;
286
289
287
290
//shut down
288
291
HAL_TIM_PWM_Stop (& self -> handle , self -> channel );
289
292
290
293
//Only change altered values
291
294
self -> handle .Init .Period = period - 1 ;
292
- self -> handle .Init .Prescaler = ( source_freq / PWM_MAX_FREQ ) - 1 ; // TIM runs at ~6MHz
295
+ self -> handle .Init .Prescaler = prescaler - 1 ;
293
296
294
297
//restart everything, adjusting for new speed
295
298
if (HAL_TIM_PWM_Init (& self -> handle ) != HAL_OK ) {
296
- mp_raise_ValueError (translate ("Timer Re-Init Error " ));
299
+ mp_raise_ValueError (translate ("Could not re-init timer " ));
297
300
}
298
- self -> chan_handle .Pulse = (period * self -> duty_cycle )/100 - 1 ;
301
+
302
+ self -> chan_handle .Pulse = input ;
303
+
299
304
if (HAL_TIM_PWM_ConfigChannel (& self -> handle , & self -> chan_handle , self -> channel ) != HAL_OK ) {
300
- mp_raise_ValueError (translate ("Channel Re-Init Error " ));
305
+ mp_raise_ValueError (translate ("Could not re-init channel " ));
301
306
}
302
307
if (HAL_TIM_PWM_Start (& self -> handle , self -> channel ) != HAL_OK ) {
303
- mp_raise_ValueError (translate ("Error restarting PWM" ));
308
+ mp_raise_ValueError (translate ("Could not restart PWM" ));
304
309
}
305
310
306
311
tim_frequencies [self -> tim -> tim_index - 1 ] = frequency ;
0 commit comments