@@ -135,6 +135,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
135
135
bool variable_frequency ) {
136
136
self -> pin = pin ;
137
137
self -> variable_frequency = variable_frequency ;
138
+ self -> duty_cycle = duty ;
138
139
139
140
if (pin -> timer [0 ].index >= TC_INST_NUM &&
140
141
pin -> timer [1 ].index >= TCC_INST_NUM
@@ -322,6 +323,13 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
322
323
}
323
324
324
325
extern void common_hal_pulseio_pwmout_set_duty_cycle (pulseio_pwmout_obj_t * self , uint16_t duty ) {
326
+ // Store the unadjusted duty cycle. It turns out the the process of adjusting and calculating
327
+ // the duty cycle here and reading it back is lossy - the value will decay over time.
328
+ // Track it here so that if frequency is changed we can use this value to recalculate the
329
+ // proper duty cycle.
330
+ // See https://github.com/adafruit/circuitpython/issues/2086 for more details
331
+ self -> duty_cycle = duty ;
332
+
325
333
const pin_timer_t * t = self -> timer ;
326
334
if (t -> is_tc ) {
327
335
uint16_t adjusted_duty = tc_periods [t -> index ] * duty / 0xffff ;
@@ -415,7 +423,6 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
415
423
break ;
416
424
}
417
425
}
418
- uint16_t old_duty = common_hal_pulseio_pwmout_get_duty_cycle (self );
419
426
if (t -> is_tc ) {
420
427
Tc * tc = tc_insts [t -> index ];
421
428
uint8_t old_divisor = tc -> COUNT16 .CTRLA .bit .PRESCALER ;
@@ -450,7 +457,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
450
457
#endif
451
458
}
452
459
453
- common_hal_pulseio_pwmout_set_duty_cycle (self , old_duty );
460
+ common_hal_pulseio_pwmout_set_duty_cycle (self , self -> duty_cycle );
454
461
}
455
462
456
463
uint32_t common_hal_pulseio_pwmout_get_frequency (pulseio_pwmout_obj_t * self ) {
0 commit comments