@@ -127,9 +127,33 @@ BBIO_err pwm_set_frequency(const char *key, float freq) {
127127
128128 period_ns = (unsigned long )(1e9 / freq );
129129
130- if (period_ns != pwm -> period_ns ) {
130+
131+ // If we're going to a shorter period, update the
132+ // duty cycle first, in order to avoid ever setting
133+ // the period < duty cycle (which would throw error)
134+ if (period_ns < pwm -> period_ns ) {
131135 pwm -> period_ns = period_ns ;
132136
137+ // Update duty ns
138+ pwm -> duty_ns = (unsigned long )(period_ns * (pwm -> duty / 100.0 ));
139+ len = snprintf (buffer , sizeof (buffer ), "%lu" , pwm -> duty_ns );
140+ lseek (pwm -> duty_fd , 0 , SEEK_SET ); // Seek to beginning of file
141+ if (write (pwm -> duty_fd , buffer , len ) < 0 ) {
142+ return BBIO_SYSFS ;
143+ }
144+
145+ // Update period ns
146+ len = snprintf (buffer , sizeof (buffer ), "%lu" , period_ns );
147+ lseek (pwm -> period_fd , 0 , SEEK_SET ); // Seek to beginning of file
148+ if (write (pwm -> period_fd , buffer , len ) < 0 ) {
149+ return BBIO_SYSFS ;
150+ }
151+
152+ } else if (period_ns > pwm -> period_ns ) {
153+ // Ordinarily update the period first,
154+ // to avoid the opposite bug - kernel won't
155+ // let us set duty greater than period
156+
133157 // Update period ns
134158 len = snprintf (buffer , sizeof (buffer ), "%lu" , period_ns );
135159 lseek (pwm -> period_fd , 0 , SEEK_SET ); // Seek to beginning of file
@@ -138,13 +162,13 @@ BBIO_err pwm_set_frequency(const char *key, float freq) {
138162 }
139163
140164 // Update duty ns
141- pwm -> duty_ns = (unsigned long )(pwm -> period_ns * (pwm -> duty / 100.0 ));
165+ pwm -> duty_ns = (unsigned long )(period_ns * (pwm -> duty / 100.0 ));
142166 len = snprintf (buffer , sizeof (buffer ), "%lu" , pwm -> duty_ns );
143167 lseek (pwm -> duty_fd , 0 , SEEK_SET ); // Seek to beginning of file
144168 if (write (pwm -> duty_fd , buffer , len ) < 0 ) {
145169 return BBIO_SYSFS ;
146170 }
147- }
171+ } // else do nothing
148172
149173 return BBIO_OK ;
150174}
@@ -154,6 +178,7 @@ BBIO_err pwm_set_polarity(const char *key, int polarity) {
154178 int len ;
155179 char buffer [9 ]; /* allow room for trailing NUL byte */
156180 struct pwm_exp * pwm ;
181+ int enabled ; /* Maintain original state */
157182
158183 pwm = lookup_exported_pwm (key );
159184
@@ -175,6 +200,7 @@ BBIO_err pwm_set_polarity(const char *key, int polarity) {
175200 // Can't set the polarity with device enabled
176201 // It will be reenabled after the parameters are set
177202 if (buffer [0 ] == '1' ) {
203+ enabled = 1 ;
178204 lseek (pwm -> enable_fd , 0 , SEEK_SET );
179205 len = snprintf (buffer , sizeof (buffer ), "0" );
180206 if (write (pwm -> enable_fd , buffer , len ) < 0 ) {
@@ -201,6 +227,17 @@ BBIO_err pwm_set_polarity(const char *key, int polarity) {
201227 return BBIO_SYSFS ;
202228 }
203229
230+ /* If we were enabled before, restore state */
231+ #ifdef BBBVERSION41
232+ if (enabled ) {
233+ lseek (pwm -> enable_fd , 0 , SEEK_SET );
234+ len = snprintf (buffer , sizeof (buffer ), "1" );
235+ if (write (pwm -> enable_fd , buffer , len ) < 0 ) {
236+ return BBIO_SYSFS ;
237+ }
238+ }
239+ #endif
240+
204241 return BBIO_OK ;
205242}
206243
@@ -475,9 +512,23 @@ BBIO_err pwm_start(const char *key, float duty, float freq, int polarity)
475512BBIO_err pwm_disable (const char * key )
476513{
477514 struct pwm_exp * pwm , * temp , * prev_pwm = NULL ;
515+ char buffer [2 ];
516+ size_t len ;
478517
479- #ifndef BBBVERSION41
480- BBIO_err err ;
518+ #ifdef BBBVERSION41
519+ pwm = lookup_exported_pwm (key );
520+
521+ // Disable the PWM
522+ lseek (pwm -> enable_fd , 0 , SEEK_SET );
523+ len = snprintf (buffer , sizeof (buffer ), "0" );
524+ if (write (pwm -> enable_fd , buffer , len ) < 0 ) {
525+ return BBIO_SYSFS ;
526+ }
527+
528+ // Unexport the PWM
529+ // TODO later
530+
531+ #else
481532 char fragment [18 ];
482533 snprintf (fragment , sizeof (fragment ), "bone_pwm_%s" , key );
483534 err = unload_device_tree (fragment );
0 commit comments