@@ -83,10 +83,6 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
83
83
// halt and clear the counter
84
84
pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
85
85
86
- // System Clock -> us_ticker (1)MHz
87
- pwm -> CTRL &= ~(0x7F << 5 );
88
- pwm -> CTRL |= (((SystemCoreClock /1000000 - 1 ) & 0x7F ) << 5 );
89
-
90
86
switch (pwm_mapped ) {
91
87
case SCT0_0 :
92
88
case SCT1_0 :
@@ -117,14 +113,6 @@ void pwmout_init(pwmout_t* obj, PinName pin) {
117
113
// Event 1 : MATCH and MATCHSEL=1
118
114
pwm -> EV1_CTRL = (1 << 12 ) | (1 << 0 );
119
115
pwm -> EV1_STATE = 0xFFFFFFFF ;
120
-
121
- // Match reload register
122
- pwm -> MATCHREL0 = 20000 ; // 20ms
123
- pwm -> MATCHREL1 = (pwm -> MATCHREL0 / 4 ); // 50% duty
124
-
125
- // unhalt the counter:
126
- // - clearing bit 2 of the CTRL register
127
- pwm -> CTRL &= ~(1 << 2 );
128
116
129
117
// default to 20ms: standard for servos, and fine for e.g. brightness control
130
118
pwmout_period_ms (obj , 20 );
@@ -140,18 +128,25 @@ void pwmout_free(pwmout_t* obj) {
140
128
}
141
129
142
130
void pwmout_write (pwmout_t * obj , float value ) {
131
+ LPC_SCT0_Type * pwm = obj -> pwm ;
143
132
if (value < 0.0f ) {
144
133
value = 0.0 ;
145
134
} else if (value > 1.0f ) {
146
135
value = 1.0 ;
147
136
}
148
- uint32_t t_on = (uint32_t )((float )(obj -> pwm -> MATCHREL0 ) * value );
149
- obj -> pwm -> MATCHREL1 = t_on ;
137
+ uint32_t t_on = (uint32_t )((float )(pwm -> MATCHREL0 + 1 ) * value );
138
+ if (t_on > 0 ) {
139
+ pwm -> MATCHREL1 = t_on - 1 ;
140
+ pwm -> CTRL &= ~(1 << 2 );
141
+ } else {
142
+ pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
143
+ pwm -> OUTPUT = 0x00000000 ;
144
+ }
150
145
}
151
146
152
147
float pwmout_read (pwmout_t * obj ) {
153
- uint32_t t_off = obj -> pwm -> MATCHREL0 ;
154
- uint32_t t_on = obj -> pwm -> MATCHREL1 ;
148
+ uint32_t t_off = obj -> pwm -> MATCHREL0 + 1 ;
149
+ uint32_t t_on = obj -> pwm -> MATCHREL1 + 1 ;
155
150
float v = (float )t_on /(float )t_off ;
156
151
return (v > 1.0f ) ? (1.0f ) : (v );
157
152
}
@@ -166,11 +161,20 @@ void pwmout_period_ms(pwmout_t* obj, int ms) {
166
161
167
162
// Set the PWM period, keeping the duty cycle the same.
168
163
void pwmout_period_us (pwmout_t * obj , int us ) {
169
- uint32_t t_off = obj -> pwm -> MATCHREL0 ;
170
- uint32_t t_on = obj -> pwm -> MATCHREL1 ;
164
+ LPC_SCT0_Type * pwm = obj -> pwm ;
165
+ uint32_t t_off = pwm -> MATCHREL0 + 1 ;
166
+ uint32_t t_on = pwm -> MATCHREL1 + 1 ;
171
167
float v = (float )t_on /(float )t_off ;
172
- obj -> pwm -> MATCHREL0 = (uint32_t )us ;
173
- obj -> pwm -> MATCHREL1 = (uint32_t )((float )us * (float )v );
168
+ uint32_t period_ticks = (uint32_t )(((uint64_t )SystemCoreClock * (uint64_t )us ) / (uint64_t )1000000 );
169
+ uint32_t pulsewidth_ticks = period_ticks * v ;
170
+ pwm -> MATCHREL0 = period_ticks - 1 ;
171
+ if (pulsewidth_ticks > 0 ) {
172
+ pwm -> MATCHREL1 = pulsewidth_ticks - 1 ;
173
+ pwm -> CTRL &= ~(1 << 2 );
174
+ } else {
175
+ pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
176
+ pwm -> OUTPUT = 0x00000000 ;
177
+ }
174
178
}
175
179
176
180
void pwmout_pulsewidth (pwmout_t * obj , float seconds ) {
@@ -182,7 +186,14 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms) {
182
186
}
183
187
184
188
void pwmout_pulsewidth_us (pwmout_t * obj , int us ) {
185
- obj -> pwm -> MATCHREL1 = (uint32_t )us ;
189
+ LPC_SCT0_Type * pwm = obj -> pwm ;
190
+ if (us > 0 ) {
191
+ pwm -> MATCHREL1 = (uint32_t )(((uint64_t )SystemCoreClock * (uint64_t )us ) / (uint64_t )1000000 ) - 1 ;
192
+ pwm -> CTRL &= ~(1 << 2 );
193
+ } else {
194
+ pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
195
+ pwm -> OUTPUT = 0x00000000 ;
196
+ }
186
197
}
187
198
188
199
#endif
0 commit comments