47
47
#include "app_util_platform.h"
48
48
#include "nrf_drv_pwm.h"
49
49
50
-
51
- #define MAX_PWM_PERIOD_US (0x7FFF << 3) // -> 7FFF (1_us/16) * 128
50
+ #define MAX_PWM_COUNTERTOP (0x7FFF) // 0x7FFF is the max of COUNTERTOP value for the PWM peripherial of the nRF52.
51
+ #define MAX_PWM_PERIOD_US (MAX_PWM_COUNTERTOP * 8) // PWM hw is driven by 16 MHz clock, hence the tick is 1_us/16,
52
+ // and 128 is the max prescaler value.
52
53
#define MAX_PWM_PERIOD_MS ((MAX_PWM_PERIOD_US / 1000) + 1) // approximations advance
53
54
#define MAX_PWM_PERIOD_S ((MAX_PWM_PERIOD_US / 1000000) + 1) // approximations advance
54
55
55
- #define PWM_INSTANCE_COUNT 3
56
+ #ifdef PWM0_ENABLED
57
+ #define __PWM0_NUM 1
58
+ #else
59
+ #define __PWM0_NUM 0
60
+ #endif
61
+
62
+ #ifdef PWM1_ENABLED
63
+ #define __PWM1_NUM 1
64
+ #else
65
+ #define __PWM1_NUM 0
66
+ #endif
67
+
68
+ #ifdef PWM2_ENABLED
69
+ #define __PWM2_NUM 1
70
+ #else
71
+ #define __PWM2_NUM 0
72
+ #endif
73
+
74
+
75
+ #define PWM_INSTANCE_COUNT (__PWM0_NUM + __PWM1_NUM + __PWM2_NUM)
56
76
57
77
///> instances of nRF52 PWM driver
58
- static nrf_drv_pwm_t m_pwm_driver [PWM_INSTANCE_COUNT ] =
78
+ static const nrf_drv_pwm_t m_pwm_driver [PWM_INSTANCE_COUNT ] =
59
79
{
80
+ #ifdef PWM0_ENABLED
60
81
NRF_DRV_PWM_INSTANCE (0 ),
82
+ #endif
83
+ #ifdef PWM1_ENABLED
61
84
NRF_DRV_PWM_INSTANCE (1 ),
85
+ #endif
86
+ #ifdef PWM2_ENABLED
62
87
NRF_DRV_PWM_INSTANCE (2 )
88
+ #endif
63
89
};
64
90
65
91
typedef struct
@@ -78,20 +104,26 @@ typedef struct
78
104
79
105
static pwm_t m_pwm [PWM_INSTANCE_COUNT ] =
80
106
{
107
+ #ifdef PWM0_ENABLED
81
108
{.p_pwm_driver = NULL },
109
+ #endif
110
+ #ifdef PWM0_ENABLED
82
111
{.p_pwm_driver = NULL },
112
+ #endif
113
+ #ifdef PWM0_ENABLED
83
114
{.p_pwm_driver = NULL }
115
+ #endif
84
116
}; /// Array of internal PWM instances.
85
117
86
118
typedef struct
87
119
{
88
- uint16_t period_hwu ;
89
- uint16_t duty_hwu ;
120
+ uint16_t period_hwu ; // unit related to pwm_clk
121
+ uint16_t duty_hwu ; // unit related to pwm_clk
90
122
nrf_pwm_clk_t pwm_clk ;
91
123
} pulsewidth_set_t ; /// helper type for timing calculations
92
124
93
125
94
- static void internal_pwmout_exe (pwmout_t * obj , bool new_period );
126
+ static void internal_pwmout_exe (pwmout_t * obj , bool new_period , bool initialization );
95
127
96
128
void pwmout_init (pwmout_t * obj , PinName pin )
97
129
{
@@ -105,14 +137,14 @@ void pwmout_init(pwmout_t *obj, PinName pin)
105
137
106
138
obj -> pwm_channel = i ;
107
139
108
- m_pwm [i ].p_pwm_driver = & m_pwm_driver [i ];
140
+ m_pwm [i ].p_pwm_driver = ( nrf_drv_pwm_t * ) & m_pwm_driver [i ];
109
141
m_pwm [i ].signal .period_us = 200000 ; // 0.02 s
110
142
m_pwm [i ].signal .duty_us = 100000 ;
111
- m_pwm [i ].signal .duty = ( 0.5 ) ;
143
+ m_pwm [i ].signal .duty = 0.5f ;
112
144
113
145
obj -> pwm_struct = & m_pwm [i ];
114
146
115
- internal_pwmout_exe (obj , true);
147
+ internal_pwmout_exe (obj , true, true );
116
148
117
149
break ;
118
150
}
@@ -135,16 +167,16 @@ void pwmout_write(pwmout_t *obj, float percent)
135
167
{
136
168
percent = 0 ;
137
169
}
138
- else if (percent > 100 )
170
+ else if (percent > 1 )
139
171
{
140
- percent = 100 ;
172
+ percent = 1 ;
141
173
}
142
174
143
175
pwm_signal_t * p_pwm_signal = & (((pwm_t * )obj -> pwm_struct )-> signal );
144
176
145
- p_pwm_signal -> duty = percent / 100 ;
177
+ p_pwm_signal -> duty = percent ;
146
178
147
- int us = (((int )p_pwm_signal -> period_us ) * percent ) / 100 ;
179
+ int us = (((int )p_pwm_signal -> period_us ) * percent );
148
180
149
181
pwmout_pulsewidth_us (obj , us );
150
182
}
@@ -153,7 +185,7 @@ float pwmout_read(pwmout_t *obj)
153
185
{
154
186
pwm_signal_t * p_pwm_signal = & (((pwm_t * )obj -> pwm_struct )-> signal );
155
187
156
- return (float )p_pwm_signal -> duty_us / (float )p_pwm_signal -> period_us * 100 ;
188
+ return (float )p_pwm_signal -> duty_us / (float )p_pwm_signal -> period_us ;
157
189
}
158
190
159
191
void pwmout_period (pwmout_t * obj , float seconds )
@@ -209,7 +241,7 @@ void pwmout_period_us(pwmout_t *obj, int us)
209
241
210
242
p_pwm_signal -> period_us = us ;
211
243
212
- internal_pwmout_exe (obj , true);
244
+ internal_pwmout_exe (obj , true, false );
213
245
}
214
246
215
247
void pwmout_pulsewidth (pwmout_t * obj , float seconds )
@@ -263,40 +295,40 @@ void pwmout_pulsewidth_us(pwmout_t *obj, int us)
263
295
p_pwm_signal -> duty_us = us ;
264
296
p_pwm_signal -> duty = us / p_pwm_signal -> period_us ;
265
297
266
- internal_pwmout_exe (obj , false);
298
+ internal_pwmout_exe (obj , false, false );
267
299
}
268
300
269
301
270
302
271
303
272
304
273
305
274
- static ret_code_t pulsewidth_us_set_get (int period_us , int duty_us , pulsewidth_set_t * const p_settings )
306
+ static ret_code_t pulsewidth_us_set_get (int period_hwu , int duty_hwu , pulsewidth_set_t * p_settings )
275
307
{
276
308
uint16_t div ;
277
309
nrf_pwm_clk_t pwm_clk = NRF_PWM_CLK_16MHz ;
278
310
279
- for (div = 1 ; div <= 128 ; div <<= 1 )
311
+ for (div = 1 ; div <= 128 ; div <<= 1 ) // 128 is the maximum of clock prescaler for PWM peripherial
280
312
{
281
- if (0x7FFF >= period_us )
313
+ if (MAX_PWM_COUNTERTOP >= period_hwu )
282
314
{
283
- p_settings -> period_hwu = period_us ; // unit [us/16 * div]
284
- p_settings -> duty_hwu = duty_us ; // unit [us/16 * div]
315
+ p_settings -> period_hwu = period_hwu ; // unit [us/16 * div]
316
+ p_settings -> duty_hwu = duty_hwu ; // unit [us/16 * div]
285
317
p_settings -> pwm_clk = pwm_clk ;
286
318
287
319
return NRF_SUCCESS ;
288
320
}
289
321
290
- period_us >>= 1 ;
291
- duty_us >>= 1 ;
322
+ period_hwu >>= 1 ;
323
+ duty_hwu >>= 1 ;
292
324
pwm_clk ++ ;
293
325
}
294
326
295
327
return NRF_ERROR_INVALID_PARAM ;
296
328
}
297
329
298
330
299
- static void internal_pwmout_exe (pwmout_t * obj , bool new_period )
331
+ static void internal_pwmout_exe (pwmout_t * obj , bool new_period , bool initialization )
300
332
{
301
333
pulsewidth_set_t pulsewidth_set ;
302
334
pwm_signal_t * p_pwm_signal ;
@@ -305,13 +337,13 @@ static void internal_pwmout_exe(pwmout_t *obj, bool new_period)
305
337
306
338
p_pwm_signal = & (((pwm_t * )obj -> pwm_struct )-> signal );
307
339
308
- if (NRF_SUCCESS == pulsewidth_us_set_get (p_pwm_signal -> period_us * 16 ,
309
- p_pwm_signal -> duty_us * 16 ,
340
+ if (NRF_SUCCESS == pulsewidth_us_set_get (p_pwm_signal -> period_us * 16 , // base clk for PWM is 16 MHz
341
+ p_pwm_signal -> duty_us * 16 , // base clk for PWM is 16 MHz
310
342
& pulsewidth_set ))
311
343
{
312
344
p_pwm_driver = (((pwm_t * )obj -> pwm_struct )-> p_pwm_driver );
313
345
314
- nrf_pwm_sequence_t seq =
346
+ const nrf_pwm_sequence_t seq =
315
347
{
316
348
.values .p_common = (nrf_pwm_values_common_t * ) (((pwm_t * )obj -> pwm_struct )-> seq_values ),
317
349
.length = 1 ,
@@ -340,7 +372,10 @@ static void internal_pwmout_exe(pwmout_t *obj, bool new_period)
340
372
.step_mode = NRF_PWM_STEP_AUTO
341
373
};
342
374
343
- nrf_drv_pwm_uninit (p_pwm_driver );
375
+ if (!initialization )
376
+ {
377
+ nrf_drv_pwm_uninit (p_pwm_driver );
378
+ }
344
379
345
380
ret_code = nrf_drv_pwm_init ( p_pwm_driver , & config0 , NULL );
346
381
0 commit comments