From 8ecec67bad0f221135faaaec25463a64880d9404 Mon Sep 17 00:00:00 2001 From: Robert Wolterman Date: Thu, 5 Jan 2017 05:54:14 +0000 Subject: [PATCH] Fixing and Closing #43, #44, and #45. setmode() function added, per pin cleanup added for GPIO and SOFTPWM, and README updates --- CHANGELOG.rst | 7 +++++++ README.rst | 12 ++++++++++-- setup.py | 2 +- source/common.h | 2 ++ source/constants.c | 11 ++++++++++- source/constants.h | 5 ++++- source/py_gpio.c | 39 ++++++++++++++++++++++++++++++--------- source/py_softpwm.c | 26 ++++++++++++++++++++------ 8 files changed, 84 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 411c65b..f403d7a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,10 @@ +0.3.0 +---- +* Added setmode() function for GPIO to maintain compatibility with Raspberry Pi scripts, this function literally does nothing +* Added per pin cleanup functionality for GPIO and SoftPWM so you can unexport a pin without unexporting every pin +* Updated README to make edge detection wording a little better and to add the per pin cleanup code +* Version update since I blasted through 3 issues on github and feel like we need a nice bump to 0.3 + 0.2.7 ---- * Fix to the Enable 1.8V Pin code as it wasn't working due to bit shifting isn't allowed on a float. diff --git a/README.rst b/README.rst index b694270..1a29aad 100644 --- a/README.rst +++ b/README.rst @@ -191,12 +191,12 @@ Polling inputs:: else: print("LOW") +The edge detection code below only works for the AP-EINT1, AP-EINT3, and XPO Pins on the CHIP. + Waiting for an edge (GPIO.RISING, GPIO.FALLING, or GPIO.BOTH:: GPIO.wait_for_edge(channel, GPIO.RISING) -This only works for the AP-EINT1, AP-EINT3, and XPO Pins on the CHIP - Detecting events:: GPIO.setup("XIO-P0", GPIO.IN) @@ -206,11 +206,16 @@ Detecting events:: if GPIO.event_detected("XIO-P0"): print "event detected!" +CHIP_IO can also handle adding callback functions on any pin that supports edge detection. + **GPIO Cleanup** To clean up the GPIO when done, do the following:: + # Clean up every exported GPIO Pin GPIO.cleanup() + # Clean up a single pin (keeping everything else intact) + GPIO.cleanup("XIO-P0") **PWM**:: @@ -239,7 +244,10 @@ Hardware PWM requires a DTB Overlay loaded on the CHIP to allow the kernel to kn SPWM.set_frequency("XIO-P7", 10) # To Stop SPWM SPWM.stop("XIO-P7") + # Cleanup can have no argument to clean up all SoftPWM outputs SPWM.cleanup() + # Or you can specify a single SoftPWM output to cleanup (keeping the rest intact) + SPWM.cleanup("XIO-P7") #For specific polarity: this example sets polarity to 1 on start: SPWM.start("XIO-P7", 50, 2000, 1) diff --git a/setup.py b/setup.py index bdc68bd..6a44668 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.2.7', + version = '0.3.0', author = 'Robert Wolterman', author_email = 'robert.wolterman@gmail.com', description = 'A module to control CHIP IO channels', diff --git a/source/common.h b/source/common.h index 4a61759..76c08f1 100644 --- a/source/common.h +++ b/source/common.h @@ -52,6 +52,8 @@ SOFTWARE. } while (0) #define MODE_UNKNOWN -1 +#define BOARD 10 +#define BCM 11 #define CHIP 0 #define CHIPPRO 1 diff --git a/source/constants.c b/source/constants.c index f09122d..e22f76a 100644 --- a/source/constants.c +++ b/source/constants.c @@ -76,6 +76,15 @@ void define_constants(PyObject *module) both_edge = Py_BuildValue("i", BOTH_EDGE); PyModule_AddObject(module, "BOTH", both_edge); - version = Py_BuildValue("s", "0.2.7"); + unknown = Py_BuildValue("i", MODE_UNKNOWN); + PyModule_AddObject(module, "UNKNOWN", unknown); + + board = Py_BuildValue("i", BOARD); + PyModule_AddObject(module, "BOARD", board); + + bcm = Py_BuildValue("i", BCM); + PyModule_AddObject(module, "BCM", bcm); + + version = Py_BuildValue("s", "0.3.0"); PyModule_AddObject(module, "VERSION", version); } diff --git a/source/constants.h b/source/constants.h index e43921f..7ffb302 100644 --- a/source/constants.h +++ b/source/constants.h @@ -10,5 +10,8 @@ PyObject *rising_edge; PyObject *falling_edge; PyObject *both_edge; PyObject *version; +PyObject *unknown; +PyObject *board; +PyObject *bcm; -void define_constants(PyObject *module); \ No newline at end of file +void define_constants(PyObject *module); diff --git a/source/py_gpio.c b/source/py_gpio.c index d757123..c48d5a9 100644 --- a/source/py_gpio.c +++ b/source/py_gpio.c @@ -71,13 +71,36 @@ static void remember_gpio_direction(int gpio, int direction) dyn_int_array_set(&gpio_direction, gpio, direction, -1); } -// python function cleanup() +// Dummy function to mimic RPi.GPIO for easier porting. +// python function setmode(mode) +static PyObject *py_setmode(PyObject *self, PyObject *args) +{ + Py_RETURN_NONE; +} + +// python function cleanup(channel=None) static PyObject *py_cleanup(PyObject *self, PyObject *args) { - clear_error_msg(); + int gpio; + char *channel; - // clean up any exports - event_cleanup(); + clear_error_msg(); + + // Channel is optional + if (!PyArg_ParseTuple(args, "|s", &channel)) + return NULL; + + if (strcmp(channel, "") == 0) { + event_cleanup(); + } else { + if (get_gpio_number(channel, &gpio) < 0) { + char err[2000]; + snprintf(err, sizeof(err), "Invalid channel %s. (%s)", channel, get_error_msg()); + PyErr_SetString(PyExc_ValueError, err); + return NULL; + } + gpio_unexport(gpio); + } Py_RETURN_NONE; } @@ -749,9 +772,6 @@ static PyObject *py_selftest(PyObject *self, PyObject *args) static const char moduledocstring[] = "GPIO functionality of a CHIP using Python"; - - - /* mine for changing pin directipn */ @@ -811,7 +831,8 @@ PyMethodDef gpio_methods[] = { {"setwarnings", py_setwarnings, METH_VARARGS, "Enable or disable warning messages"}, {"get_gpio_base", py_gpio_base, METH_VARARGS, "Get the XIO base number for sysfs"}, {"selftest", py_selftest, METH_VARARGS, "Internal unit tests"}, - { "direction", (PyCFunction)py_set_direction, METH_VARARGS, "Change direction of gpio channel. Either INPUT or OUTPUT\n" }, + {"direction", (PyCFunction)py_set_direction, METH_VARARGS, "Change direction of gpio channel. Either INPUT or OUTPUT\n" }, + {"setmode", (PyCFunction)py_setmode, METH_VARARGS, "Dummy function that does nothing but maintain compatibility with RPi.GPIO\n" }, {NULL, NULL, 0, NULL} }; @@ -865,4 +886,4 @@ PyMODINIT_FUNC initGPIO(void) #else return; #endif -} \ No newline at end of file +} diff --git a/source/py_softpwm.c b/source/py_softpwm.c index e2f91d7..e22b169 100644 --- a/source/py_softpwm.c +++ b/source/py_softpwm.c @@ -34,11 +34,26 @@ SOFTWARE. #include "common.h" #include "c_softpwm.h" -// python function cleanup() +// python function cleanup(channel=None) static PyObject *py_cleanup(PyObject *self, PyObject *args) { // unexport the PWM - softpwm_cleanup(); + char key[8]; + char *channel = NULL; + + // Channel is optional + if (!PyArg_ParseTuple(args, "|s", &channel)) + return NULL; + + if (strcmp(channel, "") == 0) { + softpwm_cleanup(); + } else { + if (!get_key(channel, key)) { + PyErr_SetString(PyExc_ValueError, "Invalid SOFTPWM key or name."); + return NULL; + } + softpwm_disable(key); + } Py_RETURN_NONE; } @@ -171,15 +186,14 @@ static PyObject *py_set_frequency(PyObject *self, PyObject *args, PyObject *kwar Py_RETURN_NONE; } - static const char moduledocstring[] = "Software PWM functionality of a CHIP using Python"; 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 'XIO-P0', or 'U14_13'"}, - {"stop", (PyCFunction)py_stop_channel, METH_VARARGS | METH_KEYWORDS, "Stop the PWM channel. channel can be in the form of 'XIO-P0', or 'U14_13'"}, + { "start", (PyCFunction)py_start_channel, METH_VARARGS | METH_KEYWORDS, "Set up and start the PWM channel. channel can be in the form of 'XIO-P0', or 'U14_13'"}, + { "stop", (PyCFunction)py_stop_channel, METH_VARARGS | METH_KEYWORDS, "Stop the PWM channel. channel can be in the form of 'XIO-P0', or 'U14_13'"}, { "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"}, + { "cleanup", (PyCFunction)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"}, //{"setwarnings", py_setwarnings, METH_VARARGS, "Enable or disable warning messages"}, {NULL, NULL, 0, NULL} };