@@ -91,6 +91,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
91
91
pwm -> CTRL &= ~(0x7F << 5 );
92
92
pwm -> CTRL |= (((SystemCoreClock /1000000 - 1 ) & 0x7F ) << 5 );
93
93
94
+ // Set event number
94
95
pwm -> OUT [sct_n ].SET = (1 << ((sct_n * 2 ) + 0 ));
95
96
pwm -> OUT [sct_n ].CLR = (1 << ((sct_n * 2 ) + 1 ));
96
97
@@ -99,10 +100,6 @@ void pwmout_init(pwmout_t* obj, PinName pin)
99
100
pwm -> EVENT [(sct_n * 2 ) + 1 ].CTRL = (1 << 12 ) | ((sct_n * 2 ) + 1 );
100
101
pwm -> EVENT [(sct_n * 2 ) + 1 ].STATE = 0xFFFFFFFF ;
101
102
102
- // unhalt the counter:
103
- // - clearing bit 2 of the CTRL register
104
- pwm -> CTRL &= ~(1 << 2 );
105
-
106
103
// default to 20ms: standard for servos, and fine for e.g. brightness control
107
104
pwmout_period_ms (obj , 20 );
108
105
pwmout_write (obj , 0 );
@@ -120,16 +117,32 @@ void pwmout_write(pwmout_t* obj, float value)
120
117
if (value < 0.0f ) {
121
118
value = 0.0 ;
122
119
} else if (value > 1.0f ) {
123
- value = 1.0 ;
120
+ value = 1.0f ;
121
+ }
122
+ uint32_t t_on = (uint32_t )((float )(obj -> pwm -> MATCHREL [obj -> pwm_ch * 2 ] + 1 ) * value );
123
+ if (t_on > 0 ) { // duty is not 0%
124
+ if (value != 1.0f ) { // duty is not 100%
125
+ obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ] = t_on - 1 ;
126
+ // unhalt the counter
127
+ obj -> pwm -> CTRL &= ~(1 << 2 );
128
+ } else { // duty is 100%
129
+ // halt and clear the counter
130
+ obj -> pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
131
+ // output level tied to high
132
+ obj -> pwm -> OUTPUT |= (1 << obj -> pwm_ch );
133
+ }
134
+ } else { // duty is 0%
135
+ // halt and clear the counter
136
+ obj -> pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
137
+ // output level tied to low
138
+ obj -> pwm -> OUTPUT &= ~(1 << obj -> pwm_ch );
124
139
}
125
- uint32_t t_on = (uint32_t )((float )(obj -> pwm -> MATCHREL [obj -> pwm_ch * 2 ]) * value );
126
- obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ] = t_on ;
127
140
}
128
141
129
142
float pwmout_read (pwmout_t * obj )
130
143
{
131
- uint32_t t_off = obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 0 ];
132
- uint32_t t_on = obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ];
144
+ uint32_t t_off = obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 0 ] + 1 ;
145
+ uint32_t t_on = obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ] + 1 ;
133
146
float v = (float )t_on /(float )t_off ;
134
147
return (v > 1.0f ) ? (1.0f ) : (v );
135
148
}
@@ -147,11 +160,21 @@ void pwmout_period_ms(pwmout_t* obj, int ms)
147
160
// Set the PWM period, keeping the duty cycle the same.
148
161
void pwmout_period_us (pwmout_t * obj , int us )
149
162
{
150
- uint32_t t_off = obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 0 ];
151
- uint32_t t_on = obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ];
163
+ // The period are off by one for MATCHREL, so +1 to get actual value
164
+ uint32_t t_off = obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 0 ] + 1 ;
165
+ uint32_t t_on = obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ] + 1 ;
152
166
float v = (float )t_on /(float )t_off ;
153
- obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 0 ] = (uint32_t )us ;
154
- obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ] = (uint32_t )((float )us * (float )v );
167
+ obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 0 ] = (uint32_t )us - 1 ;
168
+ if (us > 0 ) { // PWM period is not 0
169
+ obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ] = (uint32_t )((float )us * (float )v ) - 1 ;
170
+ // unhalt the counter
171
+ obj -> pwm -> CTRL &= ~(1 << 2 );
172
+ } else { // PWM period is 0
173
+ // halt and clear the counter
174
+ obj -> pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
175
+ // output level tied to low
176
+ obj -> pwm -> OUTPUT &= ~(1 << obj -> pwm_ch );
177
+ }
155
178
}
156
179
157
180
void pwmout_pulsewidth (pwmout_t * obj , float seconds )
@@ -166,7 +189,15 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
166
189
167
190
void pwmout_pulsewidth_us (pwmout_t * obj , int us )
168
191
{
169
- obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ] = (uint32_t )us ;
192
+ if (us > 0 ) { // PWM peried is not 0
193
+ obj -> pwm -> MATCHREL [(obj -> pwm_ch * 2 ) + 1 ] = (uint32_t )us - 1 ;
194
+ obj -> pwm -> CTRL &= ~(1 << 2 );
195
+ } else { //PWM period is 0
196
+ // halt and clear the counter
197
+ obj -> pwm -> CTRL |= (1 << 2 ) | (1 << 3 );
198
+ // output level tied to low
199
+ obj -> pwm -> OUTPUT &= ~(1 << obj -> pwm_ch );
200
+ }
170
201
}
171
202
172
203
#endif
0 commit comments