Skip to content

Commit a884acc

Browse files
committed
atmel-samd: Fix PWMOut duty_cycle when used with TCC peripherals.
Fixes adafruit#148. Fixes adafruit#151
1 parent 9345562 commit a884acc

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

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

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*
44
* The MIT License (MIT)
55
*
6+
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
67
* Copyright (c) 2016 Damien P. George
78
*
89
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -104,10 +105,10 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
104105
const pin_timer_t* t = NULL;
105106
uint8_t index = 0;
106107
if (!variable_frequency &&
107-
primary_timer_index != 0xff &&
108-
target_timer_frequencies[primary_timer_index] == frequency &&
109-
pin->primary_timer.tcc->CTRLA.bit.ENABLE == 1 &&
110-
channel_ok(&pin->primary_timer, primary_timer_index)) {
108+
primary_timer_index != 0xff &&
109+
target_timer_frequencies[primary_timer_index] == frequency &&
110+
pin->primary_timer.tcc->CTRLA.bit.ENABLE == 1 &&
111+
channel_ok(&pin->primary_timer, primary_timer_index)) {
111112
t = &pin->primary_timer;
112113
index = primary_timer_index;
113114
} else if (!variable_frequency &&
@@ -153,6 +154,7 @@ void common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
153154
break;
154155
}
155156
}
157+
self->period = top;
156158
if (t->is_tc) {
157159
struct tc_config config_tc;
158160
tc_get_config_defaults(&config_tc);
@@ -228,34 +230,33 @@ extern void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
228230
extern void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) {
229231
const pin_timer_t* t = self->timer;
230232
if (t->is_tc) {
231-
uint32_t top = ((uint32_t) t->tc->COUNT16.CC[0].reg + 1);
232-
uint16_t adjusted_duty = top * duty / 0xffff;
233+
uint16_t adjusted_duty = self->period * duty / 0xffff;
233234
tc_set_compare_value(&self->tc_instance, t->channel, adjusted_duty);
234235
} else {
235-
uint32_t top = t->tcc->PER.reg + 1;
236-
uint32_t adjusted_duty = ((uint64_t) top) * duty / 0xffff;
236+
uint32_t adjusted_duty = ((uint64_t) self->period) * duty / 0xffff;
237237
tcc_set_compare_value(&self->tcc_instance, t->channel, adjusted_duty);
238238
}
239239
}
240240

241241
uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
242242
const pin_timer_t* t = self->timer;
243243
if (t->is_tc) {
244-
uint16_t top = t->tc->COUNT16.CC[0].reg;
245244
while (tc_is_syncing(&self->tc_instance)) {
246245
/* Wait for sync */
247246
}
248247
uint16_t cv = t->tc->COUNT16.CC[t->channel].reg;
249-
return cv * 0xffff / top;
248+
return cv * 0xffff / self->period;
250249
} else {
251-
uint32_t top = t->tcc->PER.reg;
252250
uint32_t cv = 0;
253251
if ((t->tcc->STATUS.vec.CCBV & (1 << t->channel)) != 0) {
254252
cv = t->tcc->CCB[t->channel].reg;
255253
} else {
256254
cv = t->tcc->CC[t->channel].reg;
257255
}
258-
return cv * 0xffff / top;
256+
257+
uint32_t duty_cycle = ((uint64_t) cv) * 0xffff / self->period;
258+
259+
return duty_cycle;
259260
}
260261
}
261262

@@ -299,6 +300,7 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self,
299300
tcc_enable(&self->tcc_instance);
300301
}
301302
}
303+
self->period = new_top;
302304
if (t->is_tc) {
303305
while (tc_is_syncing(&self->tc_instance)) {
304306
/* Wait for sync */
@@ -321,6 +323,9 @@ uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) {
321323
divisor = t->tc->COUNT16.CTRLA.bit.PRESCALER;
322324
} else {
323325
top = t->tcc->PER.reg;
326+
if (t->tcc->STATUS.bit.PERBV) {
327+
top = t->tcc->PERB.reg;
328+
}
324329
divisor = t->tcc->CTRLA.bit.PRESCALER;
325330
}
326331
return (system_clock / prescaler[divisor]) / (top + 1);

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

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

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy