@@ -91,6 +91,7 @@ void pwmout_init(pwmout_t* obj, PinName pin)
9191 pwm -> CTRL &= ~(0x7F << 5 );
9292 pwm -> CTRL |= (((SystemCoreClock /1000000 - 1 ) & 0x7F ) << 5 );
9393
94+ // Set event number
9495 pwm -> OUT [sct_n ].SET = (1 << ((sct_n * 2 ) + 0 ));
9596 pwm -> OUT [sct_n ].CLR = (1 << ((sct_n * 2 ) + 1 ));
9697
@@ -99,10 +100,6 @@ void pwmout_init(pwmout_t* obj, PinName pin)
99100 pwm -> EVENT [(sct_n * 2 ) + 1 ].CTRL = (1 << 12 ) | ((sct_n * 2 ) + 1 );
100101 pwm -> EVENT [(sct_n * 2 ) + 1 ].STATE = 0xFFFFFFFF ;
101102
102- // unhalt the counter:
103- // - clearing bit 2 of the CTRL register
104- pwm -> CTRL &= ~(1 << 2 );
105-
106103 // default to 20ms: standard for servos, and fine for e.g. brightness control
107104 pwmout_period_ms (obj , 20 );
108105 pwmout_write (obj , 0 );
@@ -120,16 +117,32 @@ void pwmout_write(pwmout_t* obj, float value)
120117 if (value < 0.0f ) {
121118 value = 0.0 ;
122119 } 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 );
124139 }
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 ;
127140}
128141
129142float pwmout_read (pwmout_t * obj )
130143{
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 ;
133146 float v = (float )t_on /(float )t_off ;
134147 return (v > 1.0f ) ? (1.0f ) : (v );
135148}
@@ -147,11 +160,21 @@ void pwmout_period_ms(pwmout_t* obj, int ms)
147160// Set the PWM period, keeping the duty cycle the same.
148161void pwmout_period_us (pwmout_t * obj , int us )
149162{
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 ;
152166 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+ }
155178}
156179
157180void pwmout_pulsewidth (pwmout_t * obj , float seconds )
@@ -166,7 +189,15 @@ void pwmout_pulsewidth_ms(pwmout_t* obj, int ms)
166189
167190void pwmout_pulsewidth_us (pwmout_t * obj , int us )
168191{
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+ }
170201}
171202
172203#endif
0 commit comments