Skip to content

Commit 0a1a12b

Browse files
committed
Revise PWM period generation algorithm to match other ports
1 parent bb8046d commit 0a1a12b

File tree

2 files changed

+38
-12
lines changed

2 files changed

+38
-12
lines changed

ports/stm32f4/common-hal/pulseio/PWMOut.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#include "stm32f4xx_hal.h"
3636
#include "common-hal/microcontroller/Pin.h"
3737

38-
#define PULSE_RESOLUTION 256 //8 bit
3938
#define ALL_CLOCKS 0xFFFF
4039

4140
STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN];
@@ -183,12 +182,21 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
183182
}
184183

185184
uint32_t source_freq = timer_get_source_freq(self->tim->tim_index);
186-
if (frequency == 0 || frequency * PULSE_RESOLUTION > (source_freq)) {
185+
uint32_t prescaler = 0;
186+
uint32_t period = 0;
187+
188+
for (int i=0; i<32767;i++) {
189+
period = source_freq/(i*frequency);
190+
if (period <= 65535 && period>=2) {
191+
prescaler = i;
192+
break;
193+
}
194+
}
195+
if (prescaler == 0) {
187196
mp_raise_ValueError(translate("Invalid frequency supplied"));
188197
}
189-
uint32_t prescaler = source_freq/(frequency*PULSE_RESOLUTION);
190-
uint32_t period = PULSE_RESOLUTION;
191-
uint32_t input = (duty*PULSE_RESOLUTION)/65535;
198+
uint32_t input = (duty*period)/65535;
199+
192200
//Used for Debugging
193201
// mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", duty,input);
194202
// mp_printf(&mp_plat_print, "SysCoreClock: %d\n", SystemCoreClock);
@@ -231,6 +239,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
231239
self->variable_frequency = variable_frequency;
232240
self->frequency = frequency;
233241
self->duty_cycle = duty;
242+
self->period = period;
234243

235244
return PWMOUT_OK;
236245
}
@@ -261,7 +270,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
261270
}
262271

263272
void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty_cycle) {
264-
uint32_t input = (duty_cycle*PULSE_RESOLUTION)/65535;
273+
uint32_t input = (duty_cycle*self->period)/65535;
265274
//Used for debugging
266275
//mp_printf(&mp_plat_print, "duty_cycle %d, Duty: %d, Input %d\n", duty_cycle, duty, input);
267276
__HAL_TIM_SET_COMPARE(&self->handle, self->channel, input);
@@ -277,15 +286,30 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_
277286
//don't halt setup for the same frequency
278287
if (frequency == self->frequency) return;
279288

280-
//calculate new values
281289
uint32_t source_freq = timer_get_source_freq(self->tim->tim_index);
282-
if (frequency == 0 || frequency*PULSE_RESOLUTION > (source_freq)) {
290+
uint32_t prescaler = 0;
291+
uint32_t period = 0;
292+
293+
for (int i=0; i<32767;i++) {
294+
period = source_freq/(i*frequency);
295+
if (period <= 65535 && period>=2) {
296+
prescaler = i;
297+
break;
298+
}
299+
}
300+
if (prescaler == 0) {
283301
mp_raise_ValueError(translate("Invalid frequency supplied"));
284302
}
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;
303+
304+
uint32_t input = (self->duty_cycle*period)/65535;
305+
306+
//debugging output
307+
// mp_printf(&mp_plat_print, "Duty:%d, Pulses:%d\n", self->duty_cycle,input);
308+
// mp_printf(&mp_plat_print, "Period: %d\n", period);
309+
// mp_printf(&mp_plat_print, "Source Freq: %d\n", source_freq);
310+
// mp_printf(&mp_plat_print, "Prescaler %d, Timer Freq: %d\n", prescaler, source_freq/prescaler);
311+
// mp_printf(&mp_plat_print, "Output Freq: %d\n", (source_freq/prescaler)/period);
312+
// mp_printf(&mp_plat_print, "TIM#:%d CH:%d ALTF:%d\n", self->tim->tim_index, self->tim->channel_index, self->tim->altfn_index);
289313

290314
//shut down
291315
HAL_TIM_PWM_Stop(&self->handle, self->channel);
@@ -310,6 +334,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_
310334

311335
tim_frequencies[self->tim->tim_index-1] = frequency;
312336
self->frequency = frequency;
337+
self->period = period;
313338
}
314339

315340
uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) {

ports/stm32f4/common-hal/pulseio/PWMOut.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ typedef struct {
4343
bool variable_frequency: 1;
4444
uint16_t duty_cycle;
4545
uint32_t frequency;
46+
uint32_t period;
4647
} pulseio_pwmout_obj_t;
4748

4849
void pwmout_reset(void);

0 commit comments

Comments
 (0)