BBIO_err pwm_set_duty_cycle(const char *key, float duty) { int len; char buffer[20]; struct pwm_exp *pwm; if (duty < 0.0 || duty > 100.0) return BBIO_INVARG; pwm = lookup_exported_pwm(key); if (pwm == NULL) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_duty_cycle: %s couldn't find key", key); return BBIO_GEN; } pwm->duty = duty; pwm->duty_ns = (unsigned long)(pwm->period_ns * (duty / 100.0)); len = snprintf(buffer, sizeof(buffer), "%lu", pwm->duty_ns); lseek(pwm->duty_fd, 0, SEEK_SET); // Seek to beginning of file if (write(pwm->duty_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_duty_cycle: %s couldn't write duty: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } syslog(LOG_DEBUG, "Adafruit_BBIO: pwm_set_duty_cycle: %s %f OK", key, duty); return BBIO_OK; }
int pwm_set_frequency(const char *key, float freq) { int len; char buffer[20]; unsigned long period_ns; struct pwm_exp *pwm; if (freq <= 0.0) return -1; pwm = lookup_exported_pwm(key); if (pwm == NULL) { return -1; } period_ns = (unsigned long)(1e9 / freq); if (period_ns != pwm->period_ns) { pwm->period_ns = period_ns; len = snprintf(buffer, sizeof(buffer), "%lu", period_ns); write(pwm->period_fd, buffer, len); } return 1; }
int pwm_set_polarity(const char *key, int polarity) { int len; char buffer[7]; /* allow room for trailing NUL byte */ struct pwm_exp *pwm; pwm = lookup_exported_pwm(key); if (pwm == NULL) { return -1; } len = snprintf(buffer, sizeof(buffer), "%d", polarity); write(pwm->polarity_fd, buffer, len); return 0; }
int softpwm_set_frequency(const char *key, float freq) { struct softpwm *pwm; if (freq <= 0.0) return -1; pwm = lookup_exported_pwm(key); if (pwm == NULL) { return -1; } pthread_mutex_lock(pwm->params_lock); pwm->params.freq = freq; pthread_mutex_unlock(pwm->params_lock); return 0; }
int softpwm_set_duty_cycle(const char *key, float duty) {; struct softpwm *pwm; if (duty < 0.0 || duty > 100.0) return -1; pwm = lookup_exported_pwm(key); if (pwm == NULL) { return -1; } pthread_mutex_lock(pwm->params_lock); pwm->params.duty = duty; pthread_mutex_unlock(pwm->params_lock); return 0; }
int softpwm_set_polarity(const char *key, int polarity) { struct softpwm *pwm; pwm = lookup_exported_pwm(key); if (pwm == NULL) { return -1; } if (polarity < 0 || polarity > 1) { return -1; } pthread_mutex_lock(pwm->params_lock); pwm->params.polarity = polarity; pthread_mutex_unlock(pwm->params_lock); return 0; }
int pwm_set_duty_cycle(const char *key, float duty) { int len; char buffer[20]; struct pwm_exp *pwm; if (duty < 0.0 || duty > 100.0) return -1; pwm = lookup_exported_pwm(key); if (pwm == NULL) { return -1; } pwm->duty = (unsigned long)(pwm->period_ns * (duty / 100.0)); len = snprintf(buffer, sizeof(buffer), "%lu", pwm->duty); write(pwm->duty_fd, buffer, len); return 0; }
// Only works before chip is enabled BBIO_err pwm_set_polarity(const char *key, int polarity) { int len; char buffer[9]; /* allow room for trailing NUL byte */ struct pwm_exp *pwm; #ifdef BBBVERSION41 int enabled; /* Maintain original state */ #endif pwm = lookup_exported_pwm(key); if (pwm == NULL) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_polarity: %s couldn't find key", key); return BBIO_GEN; } // polarity can't be changed with enabled. #ifdef BBBVERSION41 // Read the current enabled status len = 1; memset(buffer, 0, 9); // Initialize buffer lseek(pwm->enable_fd, 0, SEEK_SET); if (read(pwm->enable_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_polarity: %s couldn't read enable: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } // If the PWM is enabled, disable it // Can't set the polarity with device enabled // It will be reenabled after the parameters are set if (buffer[0] == '1') { enabled = 1; lseek(pwm->enable_fd, 0, SEEK_SET); len = snprintf(buffer, sizeof(buffer), "0"); if (write(pwm->enable_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_polarity: %s couldn't write enable: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } } // Treating 0 as normal, 1 as inversed // See documentation of sysfs interface at // https://www.kernel.org/doc/Documentation/pwm.txt if (polarity == 0) { len = snprintf(buffer, sizeof(buffer), "normal"); } else if (polarity == 1) { len = snprintf(buffer, sizeof(buffer), "inversed"); } else { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_polarity: %s invalid argument value: %i", key, polarity); return BBIO_INVARG; } #else len = snprintf(buffer, sizeof(buffer), "%d", polarity); #endif lseek(pwm->polarity_fd, 0, SEEK_SET); // Seek to beginning of file if (write(pwm->polarity_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_polarity: %s couldn't write polarity: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } /* If we were enabled before, restore state */ #ifdef BBBVERSION41 if (enabled) { lseek(pwm->enable_fd, 0, SEEK_SET); len = snprintf(buffer, sizeof(buffer), "1"); if (write(pwm->enable_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_polarity: %s couldn't write enable: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } } #endif syslog(LOG_DEBUG, "Adafruit_BBIO: pwm_set_polarity: %s %i OK", key, polarity); return BBIO_OK; }
BBIO_err initialize_pwm(void) { #ifdef BBBVERSION41 // don't load overlay in 4.1+ if (!pwm_initialized) { strncpy(ocp_dir, "/sys/devices/platform/ocp", sizeof(ocp_dir)); #else BBIO_err err; if (!pwm_initialized && load_device_tree("am33xx_pwm")) { err = build_path("/sys/devices", "ocp", ocp_dir, sizeof(ocp_dir)); if (err != BBIO_OK) { return BBIO_SYSFS; } #endif pwm_initialized = 1; #ifdef DEBUGINFO syslog(LOG_DEBUG, "Adafruit_BBIO: initialize_pwm: OK"); #endif return BBIO_OK; } #ifdef DEBUGINFO syslog(LOG_DEBUG, "Adafruit_BBIO: initialize_pwm: OK"); #endif return BBIO_OK; } BBIO_err pwm_set_frequency(const char *key, float freq) { int len; char buffer[20]; unsigned long period_ns; struct pwm_exp *pwm; if (freq <= 0.0) { #ifdef DEBUGINFO syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_frequency: %s freq %f <= 0.0", key, freq); #endif return BBIO_INVARG; } pwm = lookup_exported_pwm(key); if (pwm == NULL) { #ifdef DEBUGINFO syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_frequency: %s couldn't find key", key); #endif return BBIO_GEN; } period_ns = (unsigned long)(1e9 / freq); // If we're going to a shorter period, update the // duty cycle first, in order to avoid ever setting // the period < duty cycle (which would throw error) if (period_ns < pwm->period_ns) { pwm->period_ns = period_ns; // Update duty ns pwm->duty_ns = (unsigned long)(period_ns * (pwm->duty / 100.0)); len = snprintf(buffer, sizeof(buffer), "%lu", pwm->duty_ns); lseek(pwm->duty_fd, 0, SEEK_SET); // Seek to beginning of file if (write(pwm->duty_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_frequency: %s couldn't write duty: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } // Update period ns len = snprintf(buffer, sizeof(buffer), "%lu", period_ns); lseek(pwm->period_fd, 0, SEEK_SET); // Seek to beginning of file if (write(pwm->period_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_frequency: %s couldn't write period: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } } else if (period_ns > pwm->period_ns) { pwm->period_ns = period_ns; // Ordinarily update the period first, // to avoid the opposite bug - kernel won't // let us set duty greater than period // Update period ns len = snprintf(buffer, sizeof(buffer), "%lu", period_ns); lseek(pwm->period_fd, 0, SEEK_SET); // Seek to beginning of file if (write(pwm->period_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_frequency: %s couldn't write period: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } // Update duty ns pwm->duty_ns = (unsigned long)(period_ns * (pwm->duty / 100.0)); len = snprintf(buffer, sizeof(buffer), "%lu", pwm->duty_ns); lseek(pwm->duty_fd, 0, SEEK_SET); // Seek to beginning of file if (write(pwm->duty_fd, buffer, len) < 0) { syslog(LOG_ERR, "Adafruit_BBIO: pwm_set_frequency: %s couldn't write duty: %i-%s", key, errno, strerror(errno)); return BBIO_SYSFS; } } // else do nothing syslog(LOG_DEBUG, "Adafruit_BBIO: pwm_set_frequency: %s %f OK", key, freq); return BBIO_OK; }