1
0
mirror of https://github.com/xtacocorex/CHIP_IO synced 2025-07-20 04:43:21 +00:00

fixes for #17, hardware pwm works now, still can't change polarity, but i think that's a kernel driver/dtb thing.

This commit is contained in:
Robert Wolterman
2016-12-31 01:43:42 +00:00
parent b12c0ad2fe
commit 7d91bbc47e
9 changed files with 180 additions and 95 deletions

View File

@ -42,8 +42,23 @@ SOFTWARE.
#define PERIOD 0
#define DUTY 1
#define ENABLE 1
#define DISABLE 0
// Global variables
int pwm_initialized = 0;
int DEBUG = 0;
//int ENABLE = 1;
//int DISABLE = 0;
// pwm devices (future chip pro use)
struct pwm_dev
{
char key[KEYLEN+1]; /* leave room for terminating NUL byte */
int gpio;
int initialized;
};
struct pwm_dev *initialized_pwms = NULL;
// pwm exports
struct pwm_exp
@ -71,27 +86,28 @@ struct pwm_exp *lookup_exported_pwm(const char *key)
}
pwm = pwm->next;
}
return NULL; /* standard for pointers */
}
int initialize_pwm(void)
{
if (!pwm_initialized) {
if (!pwm_initialized) {
int fd, len;
char str_gpio[80];
// Per https://github.com/NextThingCo/CHIP-linux/pull/4
// we need to export 0 here to enable pwm0
int gpio = 0;
printf(" ** EXPORTING PWM0 **\n");
if (DEBUG)
printf(" ** EXPORTING PWM0 **\n");
if ((fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY)) < 0)
{
return -1;
}
len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); //BUF2SMALL(str_gpio);
ssize_t s = write(fd, str_gpio, len); //ASSRT(s == len);
printf(" ** IN initialize_pwm: s = %d, len = %d\n", s, len);
len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); BUF2SMALL(str_gpio);
ssize_t s = write(fd, str_gpio, len); ASSRT(s == len);
if (DEBUG)
printf(" ** IN initialize_pwm: s = %d, len = %d\n", s, len);
close(fd);
pwm_initialized = 1;
@ -103,87 +119,128 @@ int initialize_pwm(void)
int pwm_set_frequency(const char *key, float freq) {
int len;
int rtnval = -1;
char buffer[80];
unsigned long period_ns;
struct pwm_exp *pwm;
if (freq <= 0.0)
return -1;
return rtnval;
pwm = lookup_exported_pwm(key);
if (pwm == NULL) {
return -1;
return rtnval;
}
period_ns = (unsigned long)(1e9 / freq);
printf(" ** IN pwm_set_frequency: pwm_initialized = %d\n", pwm_initialized);
if (period_ns != pwm->period_ns) {
pwm->period_ns = period_ns;
if (pwm->enable) {
if (DEBUG)
printf(" ** IN pwm_set_frequency: pwm_initialized = %d\n", pwm_initialized);
if (period_ns != pwm->period_ns) {
pwm->period_ns = period_ns;
len = snprintf(buffer, sizeof(buffer), "%lu", period_ns); //BUF2SMALL(buffer);
printf(" ** pwm_set_frequency: buffer: %s\n", buffer);
ssize_t s = write(pwm->period_fd, buffer, len); //ASSRT(s == len);
printf(" ** IN pwm_set_frequency: s = %d, len = %d\n", s, len);
len = snprintf(buffer, sizeof(buffer), "%lu", period_ns); BUF2SMALL(buffer);
if (DEBUG)
printf(" ** pwm_set_frequency: buffer: %s\n", buffer);
ssize_t s = write(pwm->period_fd, buffer, len); //ASSRT(s == len);
if (DEBUG)
printf(" ** IN pwm_set_frequency: s = %d, len = %d\n", s, len);
if (s != len) {
rtnval = -1;
} else {
rtnval = 1;
}
} else {
rtnval = 0;
}
} else {
rtnval = 0;
}
return 1;
return rtnval;
}
int pwm_set_polarity(const char *key, int polarity) {
int len;
int rtnval = -1;
char buffer[80];
struct pwm_exp *pwm;
pwm = lookup_exported_pwm(key);
if (pwm == NULL) {
return -1;
return rtnval;
}
if (polarity < 0 || polarity > 1) {
return -1;
if (polarity != 0 && polarity != 1) {
return rtnval;
}
printf(" ** IN pwm_set_polarity: pwm_initialized = %d\n", pwm_initialized);
if (polarity == 0) {
len = snprintf(buffer, sizeof(buffer), "%s", "normal"); //BUF2SMALL(buffer);
if (pwm->enable) {
if (DEBUG)
printf(" ** IN pwm_set_polarity: pwm_initialized = %d\n", pwm_initialized);
if (polarity == 0) {
len = snprintf(buffer, sizeof(buffer), "%s", "normal"); BUF2SMALL(buffer);
}
else
{
len = snprintf(buffer, sizeof(buffer), "%s", "inverted"); BUF2SMALL(buffer);
}
if (DEBUG)
printf(" ** pwm_set_poliarity: buffer: %s\n", buffer);
ssize_t s = write(pwm->polarity_fd, buffer, len); //ASSRT(s == len);
if (DEBUG)
printf(" ** IN pwm_set_polarity: s = %d, len = %d\n", s, len);
if (s != len) {
rtnval = -1;
} else {
rtnval = 1;
}
} else {
rtnval = 0;
}
else
{
len = snprintf(buffer, sizeof(buffer), "%s", "inverted"); //BUF2SMALL(buffer);
}
printf(" ** pwm_set_poliarity: buffer: %s\n", buffer);
ssize_t s = write(pwm->polarity_fd, buffer, len); //ASSRT(s == len);
printf(" ** IN pwm_set_polarity: s = %d, len = %d\n", s, len);
return 0;
return rtnval;
}
int pwm_set_duty_cycle(const char *key, float duty) {
int len;
int rtnval = -1;
char buffer[80];
struct pwm_exp *pwm;
if (duty < 0.0 || duty > 100.0)
return -1;
if (duty < 0.0 || duty > 100.0) {
return rtnval;
}
pwm = lookup_exported_pwm(key);
if (pwm == NULL) {
return -1;
return rtnval;
}
pwm->duty = (unsigned long)(pwm->period_ns * (duty / 100.0));
printf(" ** IN pwm_set_duty_cycle: pwm_initialized = %d\n", pwm_initialized);
len = snprintf(buffer, sizeof(buffer), "%lu", pwm->duty); //BUF2SMALL(buffer);
printf(" ** pwm_set_duty_cycle: buffer: %s\n", buffer);
ssize_t s = write(pwm->duty_fd, buffer, len); //ASSRT(s == len);
printf(" ** IN pwm_set_duty_cycle: s = %d, len = %d\n", s, len);
if (pwm->enable) {
if (DEBUG)
printf(" ** IN pwm_set_duty_cycle: pwm_initialized = %d\n", pwm_initialized);
len = snprintf(buffer, sizeof(buffer), "%lu", pwm->duty); BUF2SMALL(buffer);
if (DEBUG)
printf(" ** pwm_set_duty_cycle: buffer: %s\n", buffer);
ssize_t s = write(pwm->duty_fd, buffer, len); //ASSRT(s == len);
if (DEBUG)
printf(" ** IN pwm_set_duty_cycle: s = %d, len = %d\n", s, len);
if (s != len) {
rtnval = -1;
} else {
rtnval = 1;
}
} else {
rtnval = 0;
}
return 0;
return rtnval;
}
int pwm_set_enable(const char *key, int enable)
@ -193,31 +250,38 @@ int pwm_set_enable(const char *key, int enable)
char buffer[80];
struct pwm_exp *pwm;
if (enable != 0 || enable != 1)
if (enable != 0 && enable != 1) {
if (DEBUG)
printf(" ** INVALID ENABLE OPTION, NEEDS TO BE EITHER 0 OR 1! **\n");
return rtnval;
}
pwm = lookup_exported_pwm(key);
if (pwm == NULL) {
if (DEBUG)
printf(" ** SOMETHING BAD HAPPEND IN pwm_set_enable, WE'RE EXITING WITH -1 NOW! **\n");
return rtnval;
}
//pwm->enable = enable;
printf(" ** IN pwm_set_enable: pwm_initialized = %d\n", pwm_initialized);
len = snprintf(buffer, sizeof(buffer), "%d", enable); //BUF2SMALL(buffer);
printf(" ** pwm_set_enable: buffer: %s\n", buffer);
len = snprintf(buffer, sizeof(buffer), "%d", enable); BUF2SMALL(buffer);
ssize_t s = write(pwm->enable_fd, buffer, len); //ASSRT(s == len);
printf(" ** IN pwm_set_enable: s = %d, len = %d\n", s, len);
if (DEBUG) {
printf(" ** IN pwm_set_enable: pwm_initialized = %d\n", pwm_initialized);
printf(" ** pwm_set_enable: buffer: %s\n", buffer);
printf(" ** IN pwm_set_enable: s = %d, len = %d\n", s, len);
}
//if (s == len)
//{
printf(" ** SETTING pwm->enable to %d\n", enable);
if (s == len)
{
if (DEBUG)
printf(" ** SETTING pwm->enable to %d\n", enable);
pwm->enable = enable;
rtnval = 0;
//} else {
// rtnval = -1;
//}
} else {
rtnval = -1;
}
return rtnval;
}
@ -232,44 +296,52 @@ int pwm_start(const char *key, float duty, float freq, int polarity)
int period_fd, duty_fd, polarity_fd, enable_fd;
struct pwm_exp *new_pwm, *pwm;
printf(" ** IN pwm_start: pwm_initialized = %d\n", pwm_initialized);
if (DEBUG)
printf(" ** IN pwm_start: pwm_initialized = %d\n", pwm_initialized);
if(!pwm_initialized) {
initialize_pwm();
} else {
if (DEBUG)
printf(" ** ALREADY INITIALIZED, CALLING CLEANUP TO START FRESH **");
pwm_cleanup();
}
printf(" ** IN pwm_start: pwm_initialized = %d\n", pwm_initialized);
if (DEBUG)
printf(" ** IN pwm_start: pwm_initialized = %d\n", pwm_initialized);
//setup the pwm base path, the chip only has one pwm
snprintf(pwm_base_path, sizeof(pwm_base_path), "/sys/class/pwm/pwmchip0/pwm%d", 0); BUF2SMALL(pwm_base_path);
//create the path for the period and duty
snprintf(enable_path, sizeof(enable_path), "%s/enable", pwm_base_path); //BUF2SMALL(enable_path);
snprintf(period_path, sizeof(period_path), "%s/period", pwm_base_path); //BUF2SMALL(period_path);
snprintf(duty_path, sizeof(duty_path), "%s/duty_cycle", pwm_base_path); //BUF2SMALL(duty_path);
snprintf(polarity_path, sizeof(polarity_path), "%s/polarity", pwm_base_path); //BUF2SMALL(polarity_path);
printf(" ** IN pwm_start: pwm_base_path: %s\n", pwm_base_path);
printf(" ** IN pwm_start: enable_path: %s\n", enable_path);
printf(" ** IN pwm_start: period_path: %s\n", period_path);
printf(" ** IN pwm_start: duty_path: %s\n", duty_path);
printf(" ** IN pwm_start: polarity_path: %s\n", polarity_path);
snprintf(enable_path, sizeof(enable_path), "%s/enable", pwm_base_path); BUF2SMALL(enable_path);
snprintf(period_path, sizeof(period_path), "%s/period", pwm_base_path); BUF2SMALL(period_path);
snprintf(duty_path, sizeof(duty_path), "%s/duty_cycle", pwm_base_path); BUF2SMALL(duty_path);
snprintf(polarity_path, sizeof(polarity_path), "%s/polarity", pwm_base_path); BUF2SMALL(polarity_path);
if (DEBUG) {
printf(" ** IN pwm_start: pwm_base_path: %s\n", pwm_base_path);
printf(" ** IN pwm_start: enable_path: %s\n", enable_path);
printf(" ** IN pwm_start: period_path: %s\n", period_path);
printf(" ** IN pwm_start: duty_path: %s\n", duty_path);
printf(" **IN pwm_start: polarity_path: %s\n", polarity_path);
}
//add period and duty fd to pwm list
if ((enable_fd = open(enable_path, O_RDWR)) < 0)
if ((enable_fd = open(enable_path, O_WRONLY)) < 0)
return -1;
if ((period_fd = open(period_path, O_RDWR)) < 0) {
if ((period_fd = open(period_path, O_WRONLY)) < 0) {
close(enable_fd);
return -1;
}
if ((duty_fd = open(duty_path, O_RDWR)) < 0) {
if ((duty_fd = open(duty_path, O_WRONLY)) < 0) {
//error, close already opened period_fd.
close(enable_fd);
close(period_fd);
return -1;
}
if ((polarity_fd = open(polarity_path, O_RDWR)) < 0) {
if ((polarity_fd = open(polarity_path, O_WRONLY)) < 0) {
//error, close already opened period_fd and duty_fd.
close(enable_fd);
close(period_fd);
@ -283,7 +355,8 @@ int pwm_start(const char *key, float duty, float freq, int polarity)
return -1; // out of memory
}
printf(" ** IN pwm_start: IF WE MAKE IT HERE, THE FILES WERE SUCCESSFULLY OPEN **\n");
if (DEBUG)
printf(" ** IN pwm_start: IF WE MAKE IT HERE, THE FILES WERE SUCCESSFULLY OPEN **\n");
strncpy(new_pwm->key, key, KEYLEN); /* can leave string unterminated */
new_pwm->key[KEYLEN] = '\0'; /* terminate string */
new_pwm->period_fd = period_fd;
@ -304,22 +377,14 @@ int pwm_start(const char *key, float duty, float freq, int polarity)
pwm->next = new_pwm;
}
printf(" ** IN pwm_start: CALLING THE SET FUNCTIONS **\n");
int rtnval = 0;
rtnval = pwm_set_enable(key, 1);
printf(" ** pwm_set_enable rtnval = %d\n", rtnval);
rtnval = pwm_set_enable(key, ENABLE);
rtnval = 0;
rtnval = pwm_set_frequency(key, freq);
printf(" ** pwm_set_frequency rtnval = %d\n", rtnval);
rtnval = 0;
rtnval = pwm_set_polarity(key, polarity);
printf(" ** pwm_set_polarity rtnval = %d\n", rtnval);
//rtnval = pwm_set_polarity(key, polarity);
//rtnval = 0;
//rtnval = pwm_set_enable(key, 1);
//printf(" ** pwm_set_enable rtnval = %d\n", rtnval);
rtnval = 0;
rtnval = pwm_set_duty_cycle(key, duty);
printf(" ** pwm_set_duty_cycle rtnval = %d\n", rtnval);
rtnval = 0;
// TODO: SET RETURN BASED UPON 4 FUNCTIONS ABOVE
@ -339,15 +404,15 @@ int pwm_disable(const char *key)
// Disable the PWM
pwm_set_frequency(key, 0);
pwm_set_polarity(key, 0);
pwm_set_enable(key, 0);
pwm_set_duty_cycle(key, 0);
pwm_set_enable(key, DISABLE);
if ((fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY)) < 0)
{
return -1;
}
len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); //BUF2SMALL(str_gpio);
ssize_t s = write(fd, str_gpio, len); //ASSRT(s == len);
len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); BUF2SMALL(str_gpio);
ssize_t s = write(fd, str_gpio, len); ASSRT(s == len);
close(fd);
// remove from list
@ -361,7 +426,7 @@ int pwm_disable(const char *key)
close(pwm->period_fd);
close(pwm->duty_fd);
close(pwm->polarity_fd);
if (prev_pwm == NULL)
{
exported_pwms = pwm->next;
@ -369,7 +434,6 @@ int pwm_disable(const char *key)
} else {
prev_pwm->next = pwm->next;
}
temp = pwm;
pwm = pwm->next;
free(temp);
@ -387,3 +451,12 @@ void pwm_cleanup(void)
pwm_disable(exported_pwms->key);
}
}
void pwm_toggle_debug(void)
{
if (DEBUG) {
DEBUG = 0;
} else {
DEBUG = 1;
}
}