From cea44c287d29b6ed0ab3e442570276fef24d2ba1 Mon Sep 17 00:00:00 2001 From: Robert Wolterman Date: Mon, 29 Feb 2016 13:04:35 -0600 Subject: [PATCH] PWM support fixed, the test fails when trying to change the frequency, but I don't think that's an issue. Have not run this against something that needs PWM to operate, but the .dtb I have loaded has /sys/class/pwm/pwmchip0 and it can be configured with this code --- setup.py | 2 +- source/c_pwm.c | 63 ++++++++++++++++++++++++++++++++++++++---- source/c_pwm.h | 1 + source/common.c | 16 +++++------ source/constants.c | 2 +- test/test_pwm_setup.py | 18 ++++++------ 6 files changed, 78 insertions(+), 24 deletions(-) diff --git a/setup.py b/setup.py index 18df3ed..10c9668 100644 --- a/setup.py +++ b/setup.py @@ -20,7 +20,7 @@ classifiers = ['Development Status :: 3 - Alpha', 'Topic :: System :: Hardware'] setup(name = 'CHIP_IO', - version = '0.0.5', + version = '0.0.6', author = 'Robert Wolterman', author_email = 'robert.wolterman@gmail.com', description = 'A module to control CHIP IO channels', diff --git a/source/c_pwm.c b/source/c_pwm.c index 355ec55..c38657c 100644 --- a/source/c_pwm.c +++ b/source/c_pwm.c @@ -52,6 +52,8 @@ struct pwm_exp int period_fd; int duty_fd; int polarity_fd; + int enable_fd; + int enable; unsigned long duty; unsigned long period_ns; struct pwm_exp *next; @@ -126,7 +128,7 @@ int pwm_set_frequency(const char *key, float freq) { int pwm_set_polarity(const char *key, int polarity) { int len; - char buffer[7]; /* allow room for trailing NUL byte */ + char buffer[9]; /* allow room for trailing NUL byte */ struct pwm_exp *pwm; pwm = lookup_exported_pwm(key); @@ -135,7 +137,17 @@ int pwm_set_polarity(const char *key, int polarity) { return -1; } - len = snprintf(buffer, sizeof(buffer), "%d", polarity); + if (polarity < 0 || polarity > 1) { + return -1; + } + + if (polarity == 0) { + len = snprintf(buffer, sizeof(buffer), "%s", "normal"); + } + else + { + len = snprintf(buffer, sizeof(buffer), "%s", "inverted"); + } write(pwm->polarity_fd, buffer, len); return 0; @@ -163,13 +175,37 @@ int pwm_set_duty_cycle(const char *key, float duty) { return 0; } +int pwm_set_enable(const char *key, int enable) +{ + int len; + char buffer[20]; + struct pwm_exp *pwm; + + if (enable != 0 || enable != 1) + return -1; + + pwm = lookup_exported_pwm(key); + + if (pwm == NULL) { + return -1; + } + + pwm->enable = enable; + + len = snprintf(buffer, sizeof(buffer), "%d", pwm->enable); + write(pwm->enable_fd, buffer, len); + + return 0; +} + int pwm_start(const char *key, float duty, float freq, int polarity) { char pwm_base_path[45]; char period_path[50]; char duty_path[50]; + char enable_path[50]; char polarity_path[55]; - int period_fd, duty_fd, polarity_fd; + int period_fd, duty_fd, polarity_fd, enable_fd; struct pwm_exp *new_pwm, *pwm; if(!pwm_initialized) { @@ -180,23 +216,31 @@ int pwm_start(const char *key, float duty, float freq, int polarity) snprintf(pwm_base_path, sizeof(pwm_base_path), "/sys/class/pwm/pwmchip0/%d", "pwm0"); //create the path for the period and duty + snprintf(enable_path, sizeof(enable_path), "%s/enable", pwm_base_path); snprintf(period_path, sizeof(period_path), "%s/period", pwm_base_path); - snprintf(duty_path, sizeof(duty_path), "%s/duty", pwm_base_path); + snprintf(duty_path, sizeof(duty_path), "%s/duty_cycle", pwm_base_path); snprintf(polarity_path, sizeof(polarity_path), "%s/polarity", pwm_base_path); //add period and duty fd to pwm list - if ((period_fd = open(period_path, O_RDWR)) < 0) + if ((enable_fd = open(enable_path, O_RDWR)) < 0) return -1; + if ((period_fd = open(period_path, O_RDWR)) < 0) { + close(enable_fd); + return -1; + } + if ((duty_fd = open(duty_path, O_RDWR)) < 0) { //error, close already opened period_fd. + close(enable_fd); close(period_fd); return -1; } if ((polarity_fd = open(polarity_path, O_RDWR)) < 0) { //error, close already opened period_fd and duty_fd. + close(enable_fd); close(period_fd); close(duty_fd); return -1; @@ -213,6 +257,7 @@ int pwm_start(const char *key, float duty, float freq, int polarity) new_pwm->period_fd = period_fd; new_pwm->duty_fd = duty_fd; new_pwm->polarity_fd = polarity_fd; + new_pwm->enable_fd = enable_fd; new_pwm->next = NULL; if (exported_pwms == NULL) @@ -229,6 +274,7 @@ int pwm_start(const char *key, float duty, float freq, int polarity) pwm_set_frequency(key, freq); pwm_set_polarity(key, polarity); + pwm_set_enable(key, 1); pwm_set_duty_cycle(key, duty); return 1; @@ -245,6 +291,12 @@ int pwm_disable(const char *key) // we need to export 0 here to enable pwm0 int gpio = 0; + // Disable the PWM + pwm_set_frequency(key, 0); + pwm_set_polarity(key, 0); + pwm_set_enable(key, 0); + pwm_set_duty_cycle(key, 0); + if ((fd = open("/sys/class/pwm/pwmchip0/unexport", O_WRONLY)) < 0) { return -1; @@ -260,6 +312,7 @@ int pwm_disable(const char *key) if (strcmp(pwm->key, key) == 0) { //close the fd + close(pwm->enable_fd); close(pwm->period_fd); close(pwm->duty_fd); close(pwm->polarity_fd); diff --git a/source/c_pwm.h b/source/c_pwm.h index 319e1d6..77e6f56 100644 --- a/source/c_pwm.h +++ b/source/c_pwm.h @@ -33,4 +33,5 @@ int pwm_start(const char *key, float duty, float freq, int polarity); int pwm_disable(const char *key); 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); diff --git a/source/common.c b/source/common.c index 05b6091..2f3e7dd 100644 --- a/source/common.c +++ b/source/common.c @@ -121,19 +121,19 @@ pins_t table[] = { { "TWI2-SDA", "U14_25", 50, -1, -1}, { "TWI2-SCK", "U14_26", 49, -1, -1}, { "CSIPCK", "U14_27", 128, -1, -1}, - { "CSICK", "U14_28", 129, 4, -1}, + { "CSICK", "U14_28", 129, -1, -1}, { "CSIHSYNC", "U14_29", 130, 1, -1}, { "CSIVSYNC", "U14_30", 131, -1, -1}, { "CSID0", "U14_31", 132, 1, -1}, { "CSID1", "U14_32", 133, -1, -1}, - { "CSID2", "U14_33", 134, -1, 4}, + { "CSID2", "U14_33", 134, -1, -1}, { "CSID3", "U14_34", 135, -1, -1}, - { "CSID4", "U14_35", 136, -1, 6}, - { "CSID5", "U14_36", 137, -1, 5}, - { "CSID6", "U14_37", 138, -1, 2}, - { "CSID7", "U14_38", 139, -1, 3}, - { "GND", "U14_39", 0, -1, 0}, - { "GND", "U14_40", 0, -1, 1}, + { "CSID4", "U14_35", 136, -1, -1}, + { "CSID5", "U14_36", 137, -1, -1}, + { "CSID6", "U14_37", 138, -1, -1}, + { "CSID7", "U14_38", 139, -1, -1}, + { "GND", "U14_39", 0, -1, -1}, + { "GND", "U14_40", 0, -1, -1}, { NULL, NULL, 0 } }; diff --git a/source/constants.c b/source/constants.c index 0b3ba73..bec6d8d 100644 --- a/source/constants.c +++ b/source/constants.c @@ -76,6 +76,6 @@ void define_constants(PyObject *module) both_edge = Py_BuildValue("i", BOTH_EDGE); PyModule_AddObject(module, "BOTH", both_edge); - version = Py_BuildValue("s", "0.0.4"); + version = Py_BuildValue("s", "0.0.6"); PyModule_AddObject(module, "VERSION", version); } diff --git a/test/test_pwm_setup.py b/test/test_pwm_setup.py index 065f6bc..e5944dd 100644 --- a/test/test_pwm_setup.py +++ b/test/test_pwm_setup.py @@ -13,7 +13,7 @@ class TestPwmSetup: pwm_test = '/sys/class/pwm/pwmchip0/pwm0' assert os.path.exists(pwm_test) - duty = open(pwm_test + '/duty').read() + duty = open(pwm_test + '/duty_cycle').read() period = open(pwm_test + '/period').read() assert int(duty) == 0 assert int(period) == 500000 @@ -25,12 +25,12 @@ class TestPwmSetup: pwm_test = '/sys/class/pwm/pwmchip0/pwm0' assert os.path.exists(pwm_test) - duty = open(pwm_test + '/duty').read() + duty = open(pwm_test + '/duty_cycle').read() period = open(pwm_test + '/period').read() polarity = open(pwm_test + '/polarity').read() assert int(duty) == 0 assert int(period) == 500000 - assert int(polarity) == 1 + assert string(polarity) == "inverted" PWM.cleanup() def test_start_pwm_with_polarity_default(self): @@ -39,12 +39,12 @@ class TestPwmSetup: pwm_test = '/sys/class/pwm/pwmchip0/pwm0' assert os.path.exists(pwm_test) - duty = open(pwm_test + '/duty').read() + duty = open(pwm_test + '/duty_cycle').read() period = open(pwm_test + '/period').read() polarity = open(pwm_test + '/polarity').read() assert int(duty) == 0 assert int(period) == 500000 - assert int(polarity) == 0 + assert string(polarity) == "normal" PWM.cleanup() def test_start_pwm_with_polarity_zero(self): @@ -53,12 +53,12 @@ class TestPwmSetup: pwm_test = '/sys/class/pwm/pwmchip0/pwm0' assert os.path.exists(pwm_test) - duty = open(pwm_test + '/duty').read() + duty = open(pwm_test + '/duty_cycle').read() period = open(pwm_test + '/period').read() polarity = open(pwm_test + '/polarity').read() assert int(duty) == 0 assert int(period) == 500000 - assert int(polarity) == 0 + assert string(polarity) == "normal" PWM.cleanup() def test_pwm_start_invalid_pwm_key(self): @@ -113,13 +113,13 @@ class TestPwmSetup: pwm_test = '/sys/class/pwm/pwmchip0/pwm0' assert os.path.exists(pwm_test) - duty = open(pwm_test + '/duty').read() + duty = open(pwm_test + '/duty_cycle').read() period = open(pwm_test + '/period').read() assert int(duty) == 0 assert int(period) == 500000 PWM.set_duty_cycle("PWM0", 100) - duty = open(pwm_test + '/duty').read() + duty = open(pwm_test + '/duty_cycle').read() period = open(pwm_test + '/period').read() assert int(duty) == 500000 assert int(period) == 500000