From 7d91bbc47e5197e201ee7ddef53d275b44f50a4f Mon Sep 17 00:00:00 2001 From: Robert Wolterman Date: Sat, 31 Dec 2016 01:43:42 +0000 Subject: [PATCH] fixes for #17, hardware pwm works now, still can't change polarity, but i think that's a kernel driver/dtb thing. --- source/c_pwm.c | 241 ++++++++++++++++++++++++++-------------- source/c_pwm.h | 1 + source/common.h | 1 - source/py_pwm.c | 14 ++- test/gptest.py | 0 test/omtest.py | 0 test/pwmtest.py | 18 +-- test/spwmtest.py | 0 test/test_gpio_input.py | 0 9 files changed, 180 insertions(+), 95 deletions(-) mode change 100755 => 100644 test/gptest.py mode change 100755 => 100644 test/omtest.py mode change 100755 => 100644 test/pwmtest.py mode change 100755 => 100644 test/spwmtest.py mode change 100755 => 100644 test/test_gpio_input.py diff --git a/source/c_pwm.c b/source/c_pwm.c index fdf689e..25730ae 100644 --- a/source/c_pwm.c +++ b/source/c_pwm.c @@ -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; + } +} diff --git a/source/c_pwm.h b/source/c_pwm.h index 77e6f56..dd29844 100644 --- a/source/c_pwm.h +++ b/source/c_pwm.h @@ -35,3 +35,4 @@ int pwm_set_frequency(const char *key, float freq); int pwm_set_duty_cycle(const char *key, float duty); int pwm_set_enable(const char *key, int enable); void pwm_cleanup(void); +void pwm_toggle_debug(void); diff --git a/source/common.h b/source/common.h index f27777f..0ca3430 100644 --- a/source/common.h +++ b/source/common.h @@ -77,7 +77,6 @@ struct dyn_int_array_s { }; typedef struct dyn_int_array_s dyn_int_array_t; - #define FILENAME_BUFFER_SIZE 128 int setup_error; diff --git a/source/py_pwm.c b/source/py_pwm.c index e1f87ba..3912a33 100644 --- a/source/py_pwm.c +++ b/source/py_pwm.c @@ -43,6 +43,15 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args) Py_RETURN_NONE; } +// python function toggle_debug() +static PyObject *py_toggle_debug(PyObject *self, PyObject *args) +{ + // toggle debug printing + pwm_toggle_debug(); + + Py_RETURN_NONE; +} + // python function start(channel, duty_cycle, freq) static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwargs) { @@ -170,9 +179,10 @@ static const char moduledocstring[] = "Hardware PWM functionality of a CHIP usin PyMethodDef pwm_methods[] = { {"start", (PyCFunction)py_start_channel, METH_VARARGS | METH_KEYWORDS, "Set up and start the PWM channel. channel can be in the form of 'PWM0', or 'U13_18'"}, {"stop", (PyCFunction)py_stop_channel, METH_VARARGS | METH_KEYWORDS, "Stop the PWM channel. channel can be in the form of 'PWM0', or 'U13_18'"}, - { "set_duty_cycle", (PyCFunction)py_set_duty_cycle, METH_VARARGS, "Change the duty cycle\ndutycycle - between 0.0 and 100.0" }, - { "set_frequency", (PyCFunction)py_set_frequency, METH_VARARGS, "Change the frequency\nfrequency - frequency in Hz (freq > 0.0)" }, + {"set_duty_cycle", (PyCFunction)py_set_duty_cycle, METH_VARARGS, "Change the duty cycle\ndutycycle - between 0.0 and 100.0" }, + {"set_frequency", (PyCFunction)py_set_frequency, METH_VARARGS, "Change the frequency\nfrequency - frequency in Hz (freq > 0.0)" }, {"cleanup", py_cleanup, METH_VARARGS, "Clean up by resetting all GPIO channels that have been used by this program to INPUT with no pullup/pulldown and no event detection"}, + {"toggle_debug", py_toggle_debug, METH_VARARGS, "Toggles the enabling/disabling of Debug print output"}, //{"setwarnings", py_setwarnings, METH_VARARGS, "Enable or disable warning messages"}, {NULL, NULL, 0, NULL} }; diff --git a/test/gptest.py b/test/gptest.py old mode 100755 new mode 100644 diff --git a/test/omtest.py b/test/omtest.py old mode 100755 new mode 100644 diff --git a/test/pwmtest.py b/test/pwmtest.py old mode 100755 new mode 100644 index 9140af1..5edb5a6 --- a/test/pwmtest.py +++ b/test/pwmtest.py @@ -49,7 +49,7 @@ if __name__ == "__main__": # SETUP VARIABLES PWMGPIO = "PWM0" RECEIVERGPIO = "CSID0" - COUNT = 50 + COUNT = 150 SLEEPTIME = 0.01 # LOAD THE PWM OVERLAY @@ -59,13 +59,14 @@ if __name__ == "__main__": time.sleep(1) # CLEANUP THE GPIO - GPIO.cleanup() - PWM.cleanup() + #GPIO.cleanup() + #PWM.cleanup() # SETUP PWM try: print("PWM START") - PWM.start(PWMGPIO, 35, 20, 0) + PWM.toggle_debug() + PWM.start(PWMGPIO, 15, 50, 1) PrintPwmData() # UNCOMMENT FOR CRASH @@ -79,10 +80,11 @@ if __name__ == "__main__": #PrintPwmData() # SETUP PWM RECEIVER - rcvr = PWMReceiver(GPIO, RECEIVERGPIO, COUNT, SLEEPTIME) - rcvr.start() + #rcvr = PWMReceiver(GPIO, RECEIVERGPIO, COUNT, SLEEPTIME) + #rcvr.start() - time.sleep(COUNT*SLEEPTIME + 1) + #time.sleep(COUNT*SLEEPTIME + 1) + raw_input("PRESS ENTER WHEN DONE") except: raise @@ -92,6 +94,6 @@ if __name__ == "__main__": PWM.stop(PWMGPIO) PWM.cleanup() #OM.unload("PWM0") - GPIO.cleanup() + #GPIO.cleanup() diff --git a/test/spwmtest.py b/test/spwmtest.py old mode 100755 new mode 100644 diff --git a/test/test_gpio_input.py b/test/test_gpio_input.py old mode 100755 new mode 100644