Skip to content

Commit 067431e

Browse files
committed
pwmout - EFM32 - add read methods for period and pulsewidth
1 parent 6a50eca commit 067431e

File tree

1 file changed

+53
-36
lines changed

1 file changed

+53
-36
lines changed

targets/TARGET_Silicon_Labs/TARGET_EFM32/pwmout_api.c

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,16 @@ uint32_t pwmout_get_channel_route(uint32_t channel)
7878
/*
7979
* Disables the route location given. Returns true if it was enabled, false if it wasn't.
8080
*/
81-
bool pwmout_disable_channel_route(uint32_t routeloc) {
81+
bool pwmout_disable_channel_route(uint32_t routeloc)
82+
{
8283
#ifdef TIMER_ROUTEPEN_CC0PEN
83-
if(PWM_TIMER->ROUTEPEN & routeloc) {
84+
if (PWM_TIMER->ROUTEPEN & routeloc) {
8485
//This channel was in use, so disable
8586
PWM_TIMER->ROUTEPEN &= ~routeloc;
8687
return true;
8788
}
8889
#else
89-
if(PWM_TIMER->ROUTE & routeloc) {
90+
if (PWM_TIMER->ROUTE & routeloc) {
9091
//This channel was in use, so disable
9192
PWM_TIMER->ROUTE &= ~routeloc;
9293
return true;
@@ -98,13 +99,14 @@ bool pwmout_disable_channel_route(uint32_t routeloc) {
9899
/*
99100
* Check if a channel is active
100101
*/
101-
bool pwmout_channel_route_active(uint32_t routeloc) {
102+
bool pwmout_channel_route_active(uint32_t routeloc)
103+
{
102104
#ifdef TIMER_ROUTEPEN_CC0PEN
103-
if(PWM_TIMER->ROUTEPEN & routeloc) {
105+
if (PWM_TIMER->ROUTEPEN & routeloc) {
104106
return true;
105107
}
106108
#else
107-
if(PWM_TIMER->ROUTE & routeloc) {
109+
if (PWM_TIMER->ROUTE & routeloc) {
108110
return true;
109111
}
110112
#endif
@@ -114,7 +116,8 @@ bool pwmout_channel_route_active(uint32_t routeloc) {
114116
/*
115117
* Set the given route PEN flag
116118
*/
117-
void pwmout_set_channel_route(uint32_t routeloc) {
119+
void pwmout_set_channel_route(uint32_t routeloc)
120+
{
118121
#ifdef TIMER_ROUTEPEN_CC0PEN
119122
PWM_TIMER->ROUTEPEN |= routeloc;
120123
#else
@@ -125,9 +128,10 @@ void pwmout_set_channel_route(uint32_t routeloc) {
125128
/*
126129
* Check if all routes are disabled
127130
*/
128-
bool pwmout_all_inactive(void) {
131+
bool pwmout_all_inactive(void)
132+
{
129133
#ifdef TIMER_ROUTEPEN_CC0PEN
130-
if(PWM_TIMER->ROUTEPEN == _TIMER_ROUTEPEN_RESETVALUE) {
134+
if (PWM_TIMER->ROUTEPEN == _TIMER_ROUTEPEN_RESETVALUE) {
131135
return true;
132136
}
133137
#else
@@ -148,7 +152,8 @@ void pwmout_enable_pins(pwmout_t *obj, uint8_t enable)
148152
}
149153
}
150154

151-
void pwmout_enable(pwmout_t *obj, uint8_t enable){
155+
void pwmout_enable(pwmout_t *obj, uint8_t enable)
156+
{
152157
if (enable) {
153158
// Set mode to PWM
154159
PWM_TIMER->CC[obj->channel].CTRL = TIMER_CC_CTRL_MODE_PWM;
@@ -168,13 +173,13 @@ void pwmout_init(pwmout_t *obj, PinName pin)
168173
CMU_ClockEnable(PWM_TIMER_CLOCK, true);
169174

170175
/* Turn on timer */
171-
if(!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
176+
if (!(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING)) {
172177
TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
173178
TIMER_Init(PWM_TIMER, &timerInit);
174179
}
175180

176181
// Set route enable
177-
if(pwmout_channel_route_active(pwmout_get_channel_route(obj->channel))) {
182+
if (pwmout_channel_route_active(pwmout_get_channel_route(obj->channel))) {
178183
//This channel was already in use
179184
//TODO: gracefully handle this case. mbed_error?
180185
return;
@@ -190,19 +195,19 @@ void pwmout_init(pwmout_t *obj, PinName pin)
190195
switch (obj->channel) {
191196
case PWM_CH0:
192197
PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC0LOC_MASK;
193-
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC0LOC_SHIFT;
198+
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTELOC0_CC0LOC_SHIFT;
194199
break;
195200
case PWM_CH1:
196201
PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC1LOC_MASK;
197-
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM)<< _TIMER_ROUTELOC0_CC1LOC_SHIFT;
202+
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTELOC0_CC1LOC_SHIFT;
198203
break;
199204
case PWM_CH2:
200205
PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC2LOC_MASK;
201-
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC2LOC_SHIFT;
206+
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTELOC0_CC2LOC_SHIFT;
202207
break;
203208
case PWM_CH3:
204209
PWM_TIMER->ROUTELOC0 &= ~_TIMER_ROUTELOC0_CC3LOC_MASK;
205-
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTELOC0_CC3LOC_SHIFT;
210+
PWM_TIMER->ROUTELOC0 |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTELOC0_CC3LOC_SHIFT;
206211
break;
207212
default:
208213
MBED_ASSERT(false);
@@ -211,10 +216,10 @@ void pwmout_init(pwmout_t *obj, PinName pin)
211216
// On P1, the route location is statically defined for the entire timer.
212217
PWM_TIMER->ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK;
213218
// Make sure the route location is not overwritten
214-
if(pwmout_all_inactive()) {
215-
PWM_TIMER->ROUTE |= pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT;
219+
if (pwmout_all_inactive()) {
220+
PWM_TIMER->ROUTE |= pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT;
216221
} else {
217-
MBED_ASSERT((PWM_TIMER->ROUTE & _TIMER_ROUTE_LOCATION_MASK) == pinmap_find_function(pin,PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT);
222+
MBED_ASSERT((PWM_TIMER->ROUTE & _TIMER_ROUTE_LOCATION_MASK) == pinmap_find_function(pin, PinMap_PWM) << _TIMER_ROUTE_LOCATION_SHIFT);
218223
}
219224
#endif
220225

@@ -224,7 +229,7 @@ void pwmout_init(pwmout_t *obj, PinName pin)
224229

225230
void pwmout_free(pwmout_t *obj)
226231
{
227-
if(pwmout_disable_channel_route(pwmout_get_channel_route(obj->channel))) {
232+
if (pwmout_disable_channel_route(pwmout_get_channel_route(obj->channel))) {
228233
//Channel was previously enabled, so do housekeeping
229234
sleep_manager_unlock_deep_sleep();
230235
} else {
@@ -233,10 +238,10 @@ void pwmout_free(pwmout_t *obj)
233238

234239
pwmout_enable_pins(obj, false);
235240

236-
if(pwmout_all_inactive()) {
241+
if (pwmout_all_inactive()) {
237242
//Stop timer
238243
PWM_TIMER->CMD = TIMER_CMD_STOP;
239-
while(PWM_TIMER->STATUS & TIMER_STATUS_RUNNING);
244+
while (PWM_TIMER->STATUS & TIMER_STATUS_RUNNING);
240245

241246
//Disable clock
242247
CMU_ClockEnable(PWM_TIMER_CLOCK, false);
@@ -248,14 +253,15 @@ void pwmout_write(pwmout_t *obj, float value)
248253
pwmout_write_channel(obj->channel, value);
249254
}
250255

251-
void pwmout_write_channel(uint32_t channel, float value) {
256+
void pwmout_write_channel(uint32_t channel, float value)
257+
{
252258
uint32_t width_cycles = 0;
253259
if (value < 0.0f) {
254260
width_cycles = 0;
255261
} else if (value >= 1.0f) {
256262
width_cycles = PWM_TIMER->TOPB + 1;
257263
} else {
258-
width_cycles = (uint16_t)((float)PWM_TIMER->TOPB * value);
264+
width_cycles = (uint16_t)((float)PWM_TIMER->TOPB * value);
259265
}
260266

261267
TIMER_CompareBufSet(PWM_TIMER, channel, width_cycles);
@@ -266,14 +272,13 @@ float pwmout_read(pwmout_t *obj)
266272
return pwmout_calculate_duty(TIMER_CaptureGet(PWM_TIMER, obj->channel), TIMER_TopGet(PWM_TIMER));
267273
}
268274

269-
float pwmout_calculate_duty(uint32_t width_cycles, uint32_t period_cycles) {
270-
if(width_cycles > period_cycles) {
275+
float pwmout_calculate_duty(uint32_t width_cycles, uint32_t period_cycles)
276+
{
277+
if (width_cycles > period_cycles) {
271278
return 1.0f;
272-
}
273-
else if (width_cycles == 0) {
279+
} else if (width_cycles == 0) {
274280
return 0.0f;
275-
}
276-
else {
281+
} else {
277282
return (float) width_cycles / (float) period_cycles;
278283
}
279284
}
@@ -302,7 +307,9 @@ void pwmout_period(pwmout_t *obj, float seconds)
302307
}
303308

304309
//Check if anything changed
305-
if(((PWM_TIMER->CTRL & _TIMER_CTRL_PRESC_MASK) == (pwm_prescaler_div << _TIMER_CTRL_PRESC_SHIFT)) && (TIMER_TopGet(PWM_TIMER) == cycles)) return;
310+
if (((PWM_TIMER->CTRL & _TIMER_CTRL_PRESC_MASK) == (pwm_prescaler_div << _TIMER_CTRL_PRESC_SHIFT)) && (TIMER_TopGet(PWM_TIMER) == cycles)) {
311+
return;
312+
}
306313

307314
//Save previous period for recalculation of duty cycles
308315
uint32_t previous_period_cycles = PWM_TIMER->TOPB;
@@ -315,8 +322,8 @@ void pwmout_period(pwmout_t *obj, float seconds)
315322

316323
//For each active channel, re-calculate the compare value
317324
uint32_t channel = 0;
318-
while(pwmout_get_channel_route(channel) != 0) {
319-
if(pwmout_channel_route_active(channel)) {
325+
while (pwmout_get_channel_route(channel) != 0) {
326+
if (pwmout_channel_route_active(channel)) {
320327
//recalc and reset compare value
321328
pwmout_write_channel(channel, pwmout_calculate_duty(PWM_TIMER->CC[channel].CCVB, previous_period_cycles));
322329
}
@@ -334,24 +341,34 @@ void pwmout_period_us(pwmout_t *obj, int us)
334341
pwmout_period(obj, us / 1000000.0f);
335342
}
336343

344+
int pwmout_read_period_us(pwmout_t *obj)
345+
{
346+
return TIMER_TopGet(PWM_TIMER) / REFERENCE_FREQUENCY * 1000000;
347+
}
348+
337349
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
338350
{
339-
uint16_t width_cycles = (uint16_t) (((float) (REFERENCE_FREQUENCY >> pwm_prescaler_div)) * seconds);
351+
uint16_t width_cycles = (uint16_t)(((float)(REFERENCE_FREQUENCY >> pwm_prescaler_div)) * seconds);
340352
TIMER_CompareBufSet(PWM_TIMER, obj->channel, width_cycles);
341353
}
342354

343355
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
344356
{
345-
uint16_t width_cycles = (uint16_t) (((REFERENCE_FREQUENCY >> pwm_prescaler_div) * ms) / 1000);
357+
uint16_t width_cycles = (uint16_t)(((REFERENCE_FREQUENCY >> pwm_prescaler_div) * ms) / 1000);
346358
TIMER_CompareBufSet(PWM_TIMER, obj->channel, width_cycles);
347359
}
348360

349361
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
350362
{
351-
uint16_t width_cycles = (uint16_t) (((uint64_t)(REFERENCE_FREQUENCY >> pwm_prescaler_div) * (uint64_t)us) / 1000000UL);
363+
uint16_t width_cycles = (uint16_t)(((uint64_t)(REFERENCE_FREQUENCY >> pwm_prescaler_div) * (uint64_t)us) / 1000000UL);
352364
TIMER_CompareBufSet(PWM_TIMER, obj->channel, width_cycles);
353365
}
354366

367+
int pwmout_read_pulsewidth_us(pwmout_t *obj)
368+
{
369+
return TIMER_CaptureGet(PWM_TIMER, obj->channel) / REFERENCE_FREQUENCY * 1000000;
370+
}
371+
355372
const PinMap *pwmout_pinmap()
356373
{
357374
return PinMap_PWM;

0 commit comments

Comments
 (0)