Skip to content

Commit 58ab584

Browse files
committed
atmel-samd: Fix sharing TCCs by statically storing the current period.
A previous fix improved the duty_cycle channel value computation by removing the reliance on the PER register which gave old values. It saved the period on the object but failed to set anything for reused timers. So, this breaks it out into a separate array that can be shared across all object regardless of whether it used a new or existing timer.
1 parent c61e1b8 commit 58ab584

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

atmel-samd/common-hal/pulseio/PWMOut.c

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
# define TCC_SIZES { MREPEAT(TCC_INST_NUM, _TCC_SIZE, 0) }
4040

4141
uint32_t target_timer_frequencies[TC_INST_NUM + TCC_INST_NUM];
42+
static uint32_t timer_periods[TC_INST_NUM + TCC_INST_NUM];
4243
uint8_t timer_refcount[TC_INST_NUM + TCC_INST_NUM];
4344
const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024};
4445

@@ -88,6 +89,10 @@ bool channel_ok(const pin_timer_t* t, uint8_t index) {
8889
t->is_tc;
8990
}
9091

92+
static uint8_t timer_index(uint32_t base_timer_address) {
93+
return (base_timer_address - ((uint32_t) TCC0)) / 0x400;
94+
}
95+
9196
void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
9297
const mcu_pin_obj_t* pin,
9398
uint16_t duty,
@@ -107,10 +112,10 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
107112
uint16_t primary_timer_index = 0xff;
108113
uint16_t secondary_timer_index = 0xff;
109114
if (pin->primary_timer.tc != NULL) {
110-
primary_timer_index = (((uint32_t) pin->primary_timer.tcc) - ((uint32_t) TCC0)) / 0x400;
115+
primary_timer_index = timer_index((uint32_t) pin->primary_timer.tcc);
111116
}
112117
if (pin->secondary_timer.tc != NULL) {
113-
secondary_timer_index = (((uint32_t) pin->secondary_timer.tcc) - ((uint32_t) TCC0)) / 0x400;
118+
secondary_timer_index = timer_index((uint32_t) pin->secondary_timer.tcc);
114119
}
115120

116121
// Figure out which timer we are using.
@@ -159,6 +164,7 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
159164
mp_raise_RuntimeError("All timers in use");
160165
return;
161166
}
167+
162168
uint8_t resolution = 0;
163169
if (t->is_tc) {
164170
resolution = 16;
@@ -177,7 +183,7 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
177183
break;
178184
}
179185
}
180-
self->period = top;
186+
timer_periods[index] = top;
181187
if (t->is_tc) {
182188
struct tc_config config_tc;
183189
tc_get_config_defaults(&config_tc);
@@ -258,11 +264,14 @@ extern void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
258264

259265
extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) {
260266
const pin_timer_t* t = self->timer;
267+
uint8_t index;
261268
if (t->is_tc) {
262-
uint16_t adjusted_duty = self->period * duty / 0xffff;
269+
index = timer_index((uint32_t) self->timer->tc);
270+
uint16_t adjusted_duty = timer_periods[index] * duty / 0xffff;
263271
tc_set_compare_value(&self->tc_instance, t->channel, adjusted_duty);
264272
} else {
265-
uint32_t adjusted_duty = ((uint64_t) self->period) * duty / 0xffff;
273+
index = timer_index((uint32_t) self->timer->tcc);
274+
uint32_t adjusted_duty = ((uint64_t) timer_periods[index]) * duty / 0xffff;
266275
tcc_set_compare_value(&self->tcc_instance, t->channel, adjusted_duty);
267276
}
268277
}
@@ -274,7 +283,7 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
274283
/* Wait for sync */
275284
}
276285
uint16_t cv = t->tc->COUNT16.CC[t->channel].reg;
277-
return cv * 0xffff / self->period;
286+
return cv * 0xffff / timer_periods[timer_index((uint32_t) self->timer->tc)];
278287
} else {
279288
uint32_t cv = 0;
280289
if ((t->tcc->STATUS.vec.CCBV & (1 << t->channel)) != 0) {
@@ -283,7 +292,7 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
283292
cv = t->tcc->CC[t->channel].reg;
284293
}
285294

286-
uint32_t duty_cycle = ((uint64_t) cv) * 0xffff / self->period;
295+
uint32_t duty_cycle = ((uint64_t) cv) * 0xffff / timer_periods[timer_index((uint32_t) self->timer->tcc)];
287296

288297
return duty_cycle;
289298
}
@@ -313,9 +322,12 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
313322
}
314323
uint16_t old_duty = common_hal_pulseio_pwmout_get_duty_cycle(self);
315324
uint8_t old_divisor;
325+
uint8_t index;
316326
if (t->is_tc) {
327+
index = timer_index((uint32_t) self->timer->tc);
317328
old_divisor = t->tc->COUNT16.CTRLA.bit.PRESCALER;
318329
} else {
330+
index = timer_index((uint32_t) self->timer->tcc);
319331
old_divisor = t->tcc->CTRLA.bit.PRESCALER;
320332
}
321333
if (new_divisor != old_divisor) {
@@ -329,7 +341,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
329341
tcc_enable(&self->tcc_instance);
330342
}
331343
}
332-
self->period = new_top;
344+
timer_periods[index] = new_top;
333345
if (t->is_tc) {
334346
while (tc_is_syncing(&self->tc_instance)) {
335347
/* Wait for sync */
@@ -345,18 +357,16 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
345357
uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) {
346358
uint32_t system_clock = system_cpu_clock_get_hz();
347359
const pin_timer_t* t = self->timer;
348-
uint32_t top;
360+
uint8_t index;
349361
uint8_t divisor;
350362
if (t->is_tc) {
351-
top = t->tc->COUNT16.CC[0].reg;
363+
index = timer_index((uint32_t) self->timer->tc);
352364
divisor = t->tc->COUNT16.CTRLA.bit.PRESCALER;
353365
} else {
354-
top = t->tcc->PER.reg;
355-
if (t->tcc->STATUS.bit.PERBV) {
356-
top = t->tcc->PERB.reg;
357-
}
366+
index = timer_index((uint32_t) self->timer->tcc);
358367
divisor = t->tcc->CTRLA.bit.PRESCALER;
359368
}
369+
uint32_t top = timer_periods[index];
360370
return (system_clock / prescaler[divisor]) / (top + 1);
361371
}
362372

atmel-samd/common-hal/pulseio/PWMOut.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ typedef struct {
3838
const mcu_pin_obj_t *pin;
3939
const pin_timer_t* timer;
4040
bool variable_frequency;
41-
uint32_t period;
4241
union {
4342
struct tc_module tc_instance;
4443
struct tcc_module tcc_instance;

0 commit comments

Comments
 (0)