@@ -78,15 +78,16 @@ uint32_t pwmout_get_channel_route(uint32_t channel)
78
78
/*
79
79
* Disables the route location given. Returns true if it was enabled, false if it wasn't.
80
80
*/
81
- bool pwmout_disable_channel_route (uint32_t routeloc ) {
81
+ bool pwmout_disable_channel_route (uint32_t routeloc )
82
+ {
82
83
#ifdef TIMER_ROUTEPEN_CC0PEN
83
- if (PWM_TIMER -> ROUTEPEN & routeloc ) {
84
+ if (PWM_TIMER -> ROUTEPEN & routeloc ) {
84
85
//This channel was in use, so disable
85
86
PWM_TIMER -> ROUTEPEN &= ~routeloc ;
86
87
return true;
87
88
}
88
89
#else
89
- if (PWM_TIMER -> ROUTE & routeloc ) {
90
+ if (PWM_TIMER -> ROUTE & routeloc ) {
90
91
//This channel was in use, so disable
91
92
PWM_TIMER -> ROUTE &= ~routeloc ;
92
93
return true;
@@ -98,13 +99,14 @@ bool pwmout_disable_channel_route(uint32_t routeloc) {
98
99
/*
99
100
* Check if a channel is active
100
101
*/
101
- bool pwmout_channel_route_active (uint32_t routeloc ) {
102
+ bool pwmout_channel_route_active (uint32_t routeloc )
103
+ {
102
104
#ifdef TIMER_ROUTEPEN_CC0PEN
103
- if (PWM_TIMER -> ROUTEPEN & routeloc ) {
105
+ if (PWM_TIMER -> ROUTEPEN & routeloc ) {
104
106
return true;
105
107
}
106
108
#else
107
- if (PWM_TIMER -> ROUTE & routeloc ) {
109
+ if (PWM_TIMER -> ROUTE & routeloc ) {
108
110
return true;
109
111
}
110
112
#endif
@@ -114,7 +116,8 @@ bool pwmout_channel_route_active(uint32_t routeloc) {
114
116
/*
115
117
* Set the given route PEN flag
116
118
*/
117
- void pwmout_set_channel_route (uint32_t routeloc ) {
119
+ void pwmout_set_channel_route (uint32_t routeloc )
120
+ {
118
121
#ifdef TIMER_ROUTEPEN_CC0PEN
119
122
PWM_TIMER -> ROUTEPEN |= routeloc ;
120
123
#else
@@ -125,9 +128,10 @@ void pwmout_set_channel_route(uint32_t routeloc) {
125
128
/*
126
129
* Check if all routes are disabled
127
130
*/
128
- bool pwmout_all_inactive (void ) {
131
+ bool pwmout_all_inactive (void )
132
+ {
129
133
#ifdef TIMER_ROUTEPEN_CC0PEN
130
- if (PWM_TIMER -> ROUTEPEN == _TIMER_ROUTEPEN_RESETVALUE ) {
134
+ if (PWM_TIMER -> ROUTEPEN == _TIMER_ROUTEPEN_RESETVALUE ) {
131
135
return true;
132
136
}
133
137
#else
@@ -148,7 +152,8 @@ void pwmout_enable_pins(pwmout_t *obj, uint8_t enable)
148
152
}
149
153
}
150
154
151
- void pwmout_enable (pwmout_t * obj , uint8_t enable ){
155
+ void pwmout_enable (pwmout_t * obj , uint8_t enable )
156
+ {
152
157
if (enable ) {
153
158
// Set mode to PWM
154
159
PWM_TIMER -> CC [obj -> channel ].CTRL = TIMER_CC_CTRL_MODE_PWM ;
@@ -168,13 +173,13 @@ void pwmout_init(pwmout_t *obj, PinName pin)
168
173
CMU_ClockEnable (PWM_TIMER_CLOCK , true);
169
174
170
175
/* Turn on timer */
171
- if (!(PWM_TIMER -> STATUS & TIMER_STATUS_RUNNING )) {
176
+ if (!(PWM_TIMER -> STATUS & TIMER_STATUS_RUNNING )) {
172
177
TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT ;
173
178
TIMER_Init (PWM_TIMER , & timerInit );
174
179
}
175
180
176
181
// 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 ))) {
178
183
//This channel was already in use
179
184
//TODO: gracefully handle this case. mbed_error?
180
185
return ;
@@ -190,19 +195,19 @@ void pwmout_init(pwmout_t *obj, PinName pin)
190
195
switch (obj -> channel ) {
191
196
case PWM_CH0 :
192
197
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 ;
194
199
break ;
195
200
case PWM_CH1 :
196
201
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 ;
198
203
break ;
199
204
case PWM_CH2 :
200
205
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 ;
202
207
break ;
203
208
case PWM_CH3 :
204
209
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 ;
206
211
break ;
207
212
default :
208
213
MBED_ASSERT (false);
@@ -211,10 +216,10 @@ void pwmout_init(pwmout_t *obj, PinName pin)
211
216
// On P1, the route location is statically defined for the entire timer.
212
217
PWM_TIMER -> ROUTE &= ~_TIMER_ROUTE_LOCATION_MASK ;
213
218
// 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 ;
216
221
} 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 );
218
223
}
219
224
#endif
220
225
@@ -224,7 +229,7 @@ void pwmout_init(pwmout_t *obj, PinName pin)
224
229
225
230
void pwmout_free (pwmout_t * obj )
226
231
{
227
- if (pwmout_disable_channel_route (pwmout_get_channel_route (obj -> channel ))) {
232
+ if (pwmout_disable_channel_route (pwmout_get_channel_route (obj -> channel ))) {
228
233
//Channel was previously enabled, so do housekeeping
229
234
sleep_manager_unlock_deep_sleep ();
230
235
} else {
@@ -233,10 +238,10 @@ void pwmout_free(pwmout_t *obj)
233
238
234
239
pwmout_enable_pins (obj , false);
235
240
236
- if (pwmout_all_inactive ()) {
241
+ if (pwmout_all_inactive ()) {
237
242
//Stop timer
238
243
PWM_TIMER -> CMD = TIMER_CMD_STOP ;
239
- while (PWM_TIMER -> STATUS & TIMER_STATUS_RUNNING );
244
+ while (PWM_TIMER -> STATUS & TIMER_STATUS_RUNNING );
240
245
241
246
//Disable clock
242
247
CMU_ClockEnable (PWM_TIMER_CLOCK , false);
@@ -248,14 +253,15 @@ void pwmout_write(pwmout_t *obj, float value)
248
253
pwmout_write_channel (obj -> channel , value );
249
254
}
250
255
251
- void pwmout_write_channel (uint32_t channel , float value ) {
256
+ void pwmout_write_channel (uint32_t channel , float value )
257
+ {
252
258
uint32_t width_cycles = 0 ;
253
259
if (value < 0.0f ) {
254
260
width_cycles = 0 ;
255
261
} else if (value >= 1.0f ) {
256
262
width_cycles = PWM_TIMER -> TOPB + 1 ;
257
263
} else {
258
- width_cycles = (uint16_t )((float )PWM_TIMER -> TOPB * value );
264
+ width_cycles = (uint16_t )((float )PWM_TIMER -> TOPB * value );
259
265
}
260
266
261
267
TIMER_CompareBufSet (PWM_TIMER , channel , width_cycles );
@@ -266,14 +272,13 @@ float pwmout_read(pwmout_t *obj)
266
272
return pwmout_calculate_duty (TIMER_CaptureGet (PWM_TIMER , obj -> channel ), TIMER_TopGet (PWM_TIMER ));
267
273
}
268
274
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 ) {
271
278
return 1.0f ;
272
- }
273
- else if (width_cycles == 0 ) {
279
+ } else if (width_cycles == 0 ) {
274
280
return 0.0f ;
275
- }
276
- else {
281
+ } else {
277
282
return (float ) width_cycles / (float ) period_cycles ;
278
283
}
279
284
}
@@ -302,7 +307,9 @@ void pwmout_period(pwmout_t *obj, float seconds)
302
307
}
303
308
304
309
//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
+ }
306
313
307
314
//Save previous period for recalculation of duty cycles
308
315
uint32_t previous_period_cycles = PWM_TIMER -> TOPB ;
@@ -315,8 +322,8 @@ void pwmout_period(pwmout_t *obj, float seconds)
315
322
316
323
//For each active channel, re-calculate the compare value
317
324
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 )) {
320
327
//recalc and reset compare value
321
328
pwmout_write_channel (channel , pwmout_calculate_duty (PWM_TIMER -> CC [channel ].CCVB , previous_period_cycles ));
322
329
}
@@ -334,24 +341,34 @@ void pwmout_period_us(pwmout_t *obj, int us)
334
341
pwmout_period (obj , us / 1000000.0f );
335
342
}
336
343
344
+ int pwmout_read_period_us (pwmout_t * obj )
345
+ {
346
+ return TIMER_TopGet (PWM_TIMER ) / REFERENCE_FREQUENCY * 1000000 ;
347
+ }
348
+
337
349
void pwmout_pulsewidth (pwmout_t * obj , float seconds )
338
350
{
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 );
340
352
TIMER_CompareBufSet (PWM_TIMER , obj -> channel , width_cycles );
341
353
}
342
354
343
355
void pwmout_pulsewidth_ms (pwmout_t * obj , int ms )
344
356
{
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 );
346
358
TIMER_CompareBufSet (PWM_TIMER , obj -> channel , width_cycles );
347
359
}
348
360
349
361
void pwmout_pulsewidth_us (pwmout_t * obj , int us )
350
362
{
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 );
352
364
TIMER_CompareBufSet (PWM_TIMER , obj -> channel , width_cycles );
353
365
}
354
366
367
+ int pwmout_read_pulsewidth_us (pwmout_t * obj )
368
+ {
369
+ return TIMER_CaptureGet (PWM_TIMER , obj -> channel ) / REFERENCE_FREQUENCY * 1000000 ;
370
+ }
371
+
355
372
const PinMap * pwmout_pinmap ()
356
373
{
357
374
return PinMap_PWM ;
0 commit comments