summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--atmel-samd/common-hal/pulseio/PWMOut.c38
-rw-r--r--atmel-samd/common-hal/pulseio/PWMOut.h1
2 files changed, 24 insertions, 15 deletions
diff --git a/atmel-samd/common-hal/pulseio/PWMOut.c b/atmel-samd/common-hal/pulseio/PWMOut.c
index 336948a2e..5354a33fb 100644
--- a/atmel-samd/common-hal/pulseio/PWMOut.c
+++ b/atmel-samd/common-hal/pulseio/PWMOut.c
@@ -39,6 +39,7 @@
# define TCC_SIZES { MREPEAT(TCC_INST_NUM, _TCC_SIZE, 0) }
uint32_t target_timer_frequencies[TC_INST_NUM + TCC_INST_NUM];
+static uint32_t timer_periods[TC_INST_NUM + TCC_INST_NUM];
uint8_t timer_refcount[TC_INST_NUM + TCC_INST_NUM];
const uint16_t prescaler[8] = {1, 2, 4, 8, 16, 64, 256, 1024};
@@ -88,6 +89,10 @@ bool channel_ok(const pin_timer_t* t, uint8_t index) {
t->is_tc;
}
+static uint8_t timer_index(uint32_t base_timer_address) {
+ return (base_timer_address - ((uint32_t) TCC0)) / 0x400;
+}
+
void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
const mcu_pin_obj_t* pin,
uint16_t duty,
@@ -107,10 +112,10 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
uint16_t primary_timer_index = 0xff;
uint16_t secondary_timer_index = 0xff;
if (pin->primary_timer.tc != NULL) {
- primary_timer_index = (((uint32_t) pin->primary_timer.tcc) - ((uint32_t) TCC0)) / 0x400;
+ primary_timer_index = timer_index((uint32_t) pin->primary_timer.tcc);
}
if (pin->secondary_timer.tc != NULL) {
- secondary_timer_index = (((uint32_t) pin->secondary_timer.tcc) - ((uint32_t) TCC0)) / 0x400;
+ secondary_timer_index = timer_index((uint32_t) pin->secondary_timer.tcc);
}
// Figure out which timer we are using.
@@ -159,6 +164,7 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
mp_raise_RuntimeError("All timers in use");
return;
}
+
uint8_t resolution = 0;
if (t->is_tc) {
resolution = 16;
@@ -177,7 +183,7 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
break;
}
}
- self->period = top;
+ timer_periods[index] = top;
if (t->is_tc) {
struct tc_config config_tc;
tc_get_config_defaults(&config_tc);
@@ -258,11 +264,14 @@ extern void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) {
const pin_timer_t* t = self->timer;
+ uint8_t index;
if (t->is_tc) {
- uint16_t adjusted_duty = self->period * duty / 0xffff;
+ index = timer_index((uint32_t) self->timer->tc);
+ uint16_t adjusted_duty = timer_periods[index] * duty / 0xffff;
tc_set_compare_value(&self->tc_instance, t->channel, adjusted_duty);
} else {
- uint32_t adjusted_duty = ((uint64_t) self->period) * duty / 0xffff;
+ index = timer_index((uint32_t) self->timer->tcc);
+ uint32_t adjusted_duty = ((uint64_t) timer_periods[index]) * duty / 0xffff;
tcc_set_compare_value(&self->tcc_instance, t->channel, adjusted_duty);
}
}
@@ -274,7 +283,7 @@ uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
/* Wait for sync */
}
uint16_t cv = t->tc->COUNT16.CC[t->channel].reg;
- return cv * 0xffff / self->period;
+ return cv * 0xffff / timer_periods[timer_index((uint32_t) self->timer->tc)];
} else {
uint32_t cv = 0;
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) {
cv = t->tcc->CC[t->channel].reg;
}
- uint32_t duty_cycle = ((uint64_t) cv) * 0xffff / self->period;
+ uint32_t duty_cycle = ((uint64_t) cv) * 0xffff / timer_periods[timer_index((uint32_t) self->timer->tcc)];
return duty_cycle;
}
@@ -313,9 +322,12 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
}
uint16_t old_duty = common_hal_pulseio_pwmout_get_duty_cycle(self);
uint8_t old_divisor;
+ uint8_t index;
if (t->is_tc) {
+ index = timer_index((uint32_t) self->timer->tc);
old_divisor = t->tc->COUNT16.CTRLA.bit.PRESCALER;
} else {
+ index = timer_index((uint32_t) self->timer->tcc);
old_divisor = t->tcc->CTRLA.bit.PRESCALER;
}
if (new_divisor != old_divisor) {
@@ -329,7 +341,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
tcc_enable(&self->tcc_instance);
}
}
- self->period = new_top;
+ timer_periods[index] = new_top;
if (t->is_tc) {
while (tc_is_syncing(&self->tc_instance)) {
/* Wait for sync */
@@ -345,18 +357,16 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) {
uint32_t system_clock = system_cpu_clock_get_hz();
const pin_timer_t* t = self->timer;
- uint32_t top;
+ uint8_t index;
uint8_t divisor;
if (t->is_tc) {
- top = t->tc->COUNT16.CC[0].reg;
+ index = timer_index((uint32_t) self->timer->tc);
divisor = t->tc->COUNT16.CTRLA.bit.PRESCALER;
} else {
- top = t->tcc->PER.reg;
- if (t->tcc->STATUS.bit.PERBV) {
- top = t->tcc->PERB.reg;
- }
+ index = timer_index((uint32_t) self->timer->tcc);
divisor = t->tcc->CTRLA.bit.PRESCALER;
}
+ uint32_t top = timer_periods[index];
return (system_clock / prescaler[divisor]) / (top + 1);
}
diff --git a/atmel-samd/common-hal/pulseio/PWMOut.h b/atmel-samd/common-hal/pulseio/PWMOut.h
index 287d73653..2673078e9 100644
--- a/atmel-samd/common-hal/pulseio/PWMOut.h
+++ b/atmel-samd/common-hal/pulseio/PWMOut.h
@@ -38,7 +38,6 @@ typedef struct {
const mcu_pin_obj_t *pin;
const pin_timer_t* timer;
bool variable_frequency;
- uint32_t period;
union {
struct tc_module tc_instance;
struct tcc_module tcc_instance;