@@ -249,34 +249,41 @@ extern void common_hal_pwmio_pwmout_set_duty_cycle(pwmio_pwmout_obj_t *self, uin
249
249
// Track it here so that if frequency is changed we can use this value to recalculate the
250
250
// proper duty cycle.
251
251
// See https://github.com/adafruit/circuitpython/issues/2086 for more details
252
-
253
252
self -> duty_cycle = duty ;
253
+
254
254
const pin_timer_t * t = self -> timer ;
255
255
if (t -> is_tc ) {
256
256
uint16_t adjusted_duty = tc_periods [t -> index ] * duty / 0xffff ;
257
- if (adjusted_duty == 0 && duty != 0 ) {
258
- adjusted_duty = 1 ; // prevent rounding down to 0
259
- }
260
257
#ifdef SAMD21
261
258
tc_insts [t -> index ]-> COUNT16 .CC [t -> wave_output ].reg = adjusted_duty ;
262
259
#endif
263
260
#ifdef SAM_D5X_E5X
264
261
Tc * tc = tc_insts [t -> index ];
262
+ while (tc -> COUNT16 .SYNCBUSY .bit .CC1 != 0 ) {
263
+ }
265
264
tc -> COUNT16 .CCBUF [1 ].reg = adjusted_duty ;
266
265
#endif
267
266
} else {
268
267
uint32_t adjusted_duty = ((uint64_t )tcc_periods [t -> index ]) * duty / 0xffff ;
269
- if (adjusted_duty == 0 && duty != 0 ) {
270
- adjusted_duty = 1 ; // prevent rounding down to 0
271
- }
272
268
uint8_t channel = tcc_channel (t );
273
269
Tcc * tcc = tcc_insts [t -> index ];
270
+
271
+ // Write into the CC buffer register, which will be transferred to the
272
+ // CC register on an UPDATE (when period is finished).
273
+ // Do clock domain syncing as necessary.
274
+
275
+ while (tcc -> SYNCBUSY .reg != 0 ) {
276
+ }
277
+
278
+ // Lock out double-buffering while updating the CCB value.
279
+ tcc -> CTRLBSET .bit .LUPD = 1 ;
274
280
#ifdef SAMD21
275
281
tcc -> CCB [channel ].reg = adjusted_duty ;
276
282
#endif
277
283
#ifdef SAM_D5X_E5X
278
284
tcc -> CCBUF [channel ].reg = adjusted_duty ;
279
285
#endif
286
+ tcc -> CTRLBCLR .bit .LUPD = 1 ;
280
287
}
281
288
}
282
289
0 commit comments