25
25
26
26
static const PinMap PinMap_PWM [] = {
27
27
{P1_19 , SCT0_0 , 2 },
28
- {P2_2 , SCT0_1 , 3 },
29
- {P2_7 , SCT0_2 , 2 },
28
+ {P2_2 , SCT0_1 , 3 },
29
+ {P2_7 , SCT0_2 , 2 },
30
30
{P1_13 , SCT0_3 , 2 },
31
31
{P2_16 , SCT1_0 , 1 },
32
32
{P2_17 , SCT1_1 , 1 },
33
33
{P2_18 , SCT1_2 , 1 },
34
34
{P2_19 , SCT1_3 , 1 },
35
- {NC , NC , 0 }
35
+ {NC , NC , 0 }
36
36
};
37
37
38
38
39
39
static LPC_SCT0_Type * SCTs [SCT_CHANNELS ] = {
40
- (LPC_SCT0_Type * )LPC_SCT0 ,
41
- (LPC_SCT0_Type * )LPC_SCT1 ,
40
+ (LPC_SCT0_Type * )LPC_SCT0 ,
41
+ (LPC_SCT0_Type * )LPC_SCT1 ,
42
42
43
43
};
44
44
45
45
// bit flags for used SCTs
46
46
static unsigned char sct_used = 0 ;
47
47
48
- static int get_available_sct (void ) {
48
+ static int get_available_sct (void )
49
+ {
49
50
int i ;
50
- for (i = 0 ; i < SCT_CHANNELS ; i ++ ) {
51
- if ((sct_used & (1 << i )) == 0 )
51
+ for (i = 0 ; i < SCT_CHANNELS ; i ++ ) {
52
+ if ((sct_used & (1 << i )) == 0 ) {
52
53
return i ;
54
+ }
53
55
}
54
56
return -1 ;
55
57
}
56
58
57
- void pwmout_init (pwmout_t * obj , PinName pin ) {
59
+ void pwmout_init (pwmout_t * obj , PinName pin )
60
+ {
58
61
// determine the SPI to use
59
62
PWMName pwm_mapped = (PWMName )pinmap_peripheral (pin , PinMap_PWM );
60
63
if (pwm_mapped == (PWMName )NC ) {
@@ -73,17 +76,17 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
73
76
LPC_SYSCON -> SYSAHBCLKCTRL |= (1UL << 31 );
74
77
75
78
// Clear peripheral reset the SCT:
76
- LPC_SYSCON -> PRESETCTRL |= (1 << (obj -> pwm_ch + 9 ));
79
+ LPC_SYSCON -> PRESETCTRL |= (1 << (obj -> pwm_ch + 9 ));
77
80
pinmap_pinout (pin , PinMap_PWM );
78
- LPC_SCT0_Type * pwm = obj -> pwm ;
79
-
81
+ LPC_SCT0_Type * pwm = obj -> pwm ;
82
+
80
83
// Unified 32-bit counter, autolimit
81
84
pwm -> CONFIG |= ((0x3 << 17 ) | 0x01 );
82
-
85
+
83
86
// halt and clear the counter
84
87
pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
85
-
86
- switch (pwm_mapped ) {
88
+
89
+ switch (pwm_mapped ) {
87
90
case SCT0_0 :
88
91
case SCT1_0 :
89
92
pwm -> OUT0_SET = (1 << 0 ); // event 0
@@ -116,19 +119,21 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
116
119
117
120
// default to 20ms: standard for servos, and fine for e.g. brightness control
118
121
pwmout_period_ms (obj , 20 );
119
- pwmout_write (obj , 0 );
122
+ pwmout_write (obj , 0 );
120
123
}
121
124
122
- void pwmout_free (pwmout_t * obj ) {
125
+ void pwmout_free (pwmout_t * obj )
126
+ {
123
127
sct_used &= ~(1 << obj -> pwm_ch );
124
128
if (sct_used == 0 ) {
125
129
// Disable the SCT clock
126
130
LPC_SYSCON -> SYSAHBCLKCTRL &= ~(1UL << 31 );
127
131
}
128
132
}
129
133
130
- void pwmout_write (pwmout_t * obj , float value ) {
131
- LPC_SCT0_Type * pwm = obj -> pwm ;
134
+ void pwmout_write (pwmout_t * obj , float value )
135
+ {
136
+ LPC_SCT0_Type * pwm = obj -> pwm ;
132
137
if (value < 0.0f ) {
133
138
value = 0.0 ;
134
139
} else if (value > 1.0f ) {
@@ -137,7 +142,7 @@ void pwmout_write(pwmout_t* obj, float value) {
137
142
uint32_t t_on = (uint32_t )((float )(pwm -> MATCHREL0 + 1 ) * value );
138
143
if (t_on > 0 ) {
139
144
pwm -> MATCHREL1 = t_on - 1 ;
140
-
145
+
141
146
// Un-halt the timer and ensure the new pulse-width takes immediate effect if necessary
142
147
if (pwm -> CTRL & (1 << 2 )) {
143
148
pwm -> MATCH1 = pwm -> MATCHREL1 ;
@@ -150,34 +155,38 @@ void pwmout_write(pwmout_t* obj, float value) {
150
155
}
151
156
}
152
157
153
- float pwmout_read (pwmout_t * obj ) {
154
- LPC_SCT0_Type * pwm = obj -> pwm ;
158
+ float pwmout_read (pwmout_t * obj )
159
+ {
160
+ LPC_SCT0_Type * pwm = obj -> pwm ;
155
161
uint32_t t_off = pwm -> MATCHREL0 + 1 ;
156
162
uint32_t t_on = (!(pwm -> CTRL & (1 << 2 ))) ? pwm -> MATCHREL1 + 1 : 0 ;
157
- float v = (float )t_on / (float )t_off ;
163
+ float v = (float )t_on / (float )t_off ;
158
164
return (v > 1.0f ) ? (1.0f ) : (v );
159
165
}
160
166
161
- void pwmout_period (pwmout_t * obj , float seconds ) {
167
+ void pwmout_period (pwmout_t * obj , float seconds )
168
+ {
162
169
pwmout_period_us (obj , seconds * 1000000.0f );
163
170
}
164
171
165
- void pwmout_period_ms (pwmout_t * obj , int ms ) {
172
+ void pwmout_period_ms (pwmout_t * obj , int ms )
173
+ {
166
174
pwmout_period_us (obj , ms * 1000 );
167
175
}
168
176
169
177
// Set the PWM period, keeping the duty cycle the same.
170
- void pwmout_period_us (pwmout_t * obj , int us ) {
171
- LPC_SCT0_Type * pwm = obj -> pwm ;
178
+ void pwmout_period_us (pwmout_t * obj , int us )
179
+ {
180
+ LPC_SCT0_Type * pwm = obj -> pwm ;
172
181
uint32_t t_off = pwm -> MATCHREL0 + 1 ;
173
182
uint32_t t_on = (!(pwm -> CTRL & (1 << 2 ))) ? pwm -> MATCHREL1 + 1 : 0 ;
174
- float v = (float )t_on / (float )t_off ;
183
+ float v = (float )t_on / (float )t_off ;
175
184
uint32_t period_ticks = (uint32_t )(((uint64_t )SystemCoreClock * (uint64_t )us ) / (uint64_t )1000000 );
176
185
uint32_t pulsewidth_ticks = period_ticks * v ;
177
186
pwm -> MATCHREL0 = period_ticks - 1 ;
178
187
if (pulsewidth_ticks > 0 ) {
179
188
pwm -> MATCHREL1 = pulsewidth_ticks - 1 ;
180
-
189
+
181
190
// Un-halt the timer and ensure the new period & pulse-width take immediate effect if necessary
182
191
if (pwm -> CTRL & (1 << 2 )) {
183
192
pwm -> MATCH0 = pwm -> MATCHREL0 ;
@@ -188,25 +197,33 @@ void pwmout_period_us(pwmout_t* obj, int us) {
188
197
// Halt the timer and force the output low
189
198
pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
190
199
pwm -> OUTPUT = 0x00000000 ;
191
-
200
+
192
201
// Ensure the new period will take immediate effect when the timer is un-halted
193
202
pwm -> MATCH0 = pwm -> MATCHREL0 ;
194
203
}
195
204
}
196
205
197
- void pwmout_pulsewidth (pwmout_t * obj , float seconds ) {
206
+ int pwmout_read_period_us (pwmout_t * obj )
207
+ {
208
+ return pwm -> MATCHREL0 + 1 ;
209
+ }
210
+
211
+ void pwmout_pulsewidth (pwmout_t * obj , float seconds )
212
+ {
198
213
pwmout_pulsewidth_us (obj , seconds * 1000000.0f );
199
214
}
200
215
201
- void pwmout_pulsewidth_ms (pwmout_t * obj , int ms ) {
216
+ void pwmout_pulsewidth_ms (pwmout_t * obj , int ms )
217
+ {
202
218
pwmout_pulsewidth_us (obj , ms * 1000 );
203
219
}
204
220
205
- void pwmout_pulsewidth_us (pwmout_t * obj , int us ) {
206
- LPC_SCT0_Type * pwm = obj -> pwm ;
221
+ void pwmout_pulsewidth_us (pwmout_t * obj , int us )
222
+ {
223
+ LPC_SCT0_Type * pwm = obj -> pwm ;
207
224
if (us > 0 ) {
208
225
pwm -> MATCHREL1 = (uint32_t )(((uint64_t )SystemCoreClock * (uint64_t )us ) / (uint64_t )1000000 ) - 1 ;
209
-
226
+
210
227
// Un-halt the timer and ensure the new pulse-width takes immediate effect if necessary
211
228
if (pwm -> CTRL & (1 << 2 )) {
212
229
pwm -> MATCH1 = pwm -> MATCHREL1 ;
@@ -219,6 +236,10 @@ void pwmout_pulsewidth_us(pwmout_t* obj, int us) {
219
236
}
220
237
}
221
238
239
+ int pwmout_read_pulsewidth_us (pwmout_t * obj {
240
+ return (!(pwm -> CTRL & (1 << 2 ))) ? pwm -> MATCHREL1 + 1 : 0 ;
241
+ }
242
+
222
243
const PinMap * pwmout_pinmap ()
223
244
{
224
245
return PinMap_PWM ;
0 commit comments