Skip to content

Commit ac1104c

Browse files
author
Matthew West
committed
Fix bug with setting frequency, fix stopping
1 parent 8fe1336 commit ac1104c

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

source/c_pwm.c

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
475512
BBIO_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);

source/py_pwm.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ static PyObject *py_stop_channel(PyObject *self, PyObject *args, PyObject *kwarg
115115
if (!PyArg_ParseTuple(args, "s", &channel))
116116
return NULL;
117117

118-
if (!get_pwm_key(channel, key)) {
118+
err = get_pwm_key(channel, key);
119+
if (err == BBIO_INVARG) {
119120
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
120121
return NULL;
121122
}

0 commit comments

Comments
 (0)