diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a513f86..57a6dde 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,10 @@ +0.3.5 +--- +* Merged in brettcvz's code to read a byte of data from the GPIO + - Cleaned the code up and expanded it (in the low level C code) to read up to 32 bits of data + - Presented 8 bit and 16 bits of data functions to the Python interface with brettcvz's read_byte() and my read_word() +* I think I finally fixed the GPIO.cleanup() code one and for all + 0.3.4.1 --- * Quick fix as I borked XIO setup as inputs with the latest change that enabled PUD diff --git a/README.rst b/README.rst index ab70ec9..b1abb7e 100644 --- a/README.rst +++ b/README.rst @@ -205,6 +205,15 @@ Polling inputs:: else: print("LOW") +Read lots of data:: + + # Get 8 bits of data in one shot + mybyte = GPIO.read_byte("LCD-D3") + # Get 16 bits of data in one shot + myword = GPIO.read_word("XIO-P4") + +This code was initially added by brettcvz and I cleaned it up and expanded it. + 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:: diff --git a/setup.py b/setup.py index 2f9dc4b..33b37a6 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.3.4.1', + version = '0.3.5', author = 'Robert Wolterman', author_email = 'robert.wolterman@gmail.com', description = 'A module to control CHIP IO channels', diff --git a/source/constants.c b/source/constants.c index da9a5e8..1f73a35 100644 --- a/source/constants.c +++ b/source/constants.c @@ -88,6 +88,6 @@ void define_constants(PyObject *module) module_debug = Py_BuildValue("i", DEBUG ? Py_True: Py_False); PyModule_AddObject(module, "DEBUG", module_debug); - version = Py_BuildValue("s", "0.3.4.1"); + version = Py_BuildValue("s", "0.3.5"); PyModule_AddObject(module, "VERSION", version); } diff --git a/source/event_gpio.c b/source/event_gpio.c index c54e481..7c07b6c 100644 --- a/source/event_gpio.c +++ b/source/event_gpio.c @@ -506,8 +506,7 @@ int gpio_get_value(int gpio, unsigned int *value) int fd = fd_lookup(gpio); char ch; - if (!fd) - { + if (!fd) { if ((fd = open_value_file(gpio)) == -1) { char err[256]; snprintf(err, sizeof(err), "gpio_get_value: could not open GPIO %d value file", gpio); @@ -547,6 +546,58 @@ int gpio_get_value(int gpio, unsigned int *value) return 0; } +int gpio_get_more(int gpio, int bits, unsigned int *value) +{ + int fd = fd_lookup(gpio); + char ch; + + if (!fd) { + if ((fd = open_value_file(gpio)) == -1) { + char err[256]; + snprintf(err, sizeof(err), "gpio_get_more: could not open GPIO %d value file", gpio); + add_error_msg(err); + return -1; + } + } + + // Loop for our number of bits + int i; + for (i = 0; i < bits; i++) { + + if (lseek(fd, 0, SEEK_SET) < 0) { + char err[256]; + snprintf(err, sizeof(err), "gpio_get_more: could not seek GPIO %d (%s)", gpio, strerror(errno)); + add_error_msg(err); + return -1; + } + ssize_t s = read(fd, &ch, sizeof(ch)); + if (s < 0) { + char err[256]; + snprintf(err, sizeof(err), "gpio_get_more: could not read GPIO %d (%s)", gpio, strerror(errno)); + add_error_msg(err); + return -1; + } + + if (ch == '1') { + *value |= (1 << i); + } else if (ch == '0') { + *value |= (0 << i); + } else { + char err[256]; + snprintf(err, sizeof(err), "gpio_get_more: unrecognized read GPIO %d (%c)", gpio, ch); + add_error_msg(err); + return -1; + } + if (DEBUG) { + printf(" ** gpio_get_more: %c **\n", ch); + printf(" ** gpio_get_more: current value: %u **\n", *value); + } + } + + return 0; + +} + int gpio_set_edge(int gpio, unsigned int edge) { int fd; diff --git a/source/event_gpio.h b/source/event_gpio.h index bfadb14..0c18fd8 100644 --- a/source/event_gpio.h +++ b/source/event_gpio.h @@ -69,6 +69,7 @@ int gpio_set_direction(int gpio, unsigned int in_flag); int gpio_get_direction(int gpio, unsigned int *value); int gpio_set_value(int gpio, unsigned int value); int gpio_get_value(int gpio, unsigned int *value); +int gpio_get_more(int gpio, int bits, unsigned int *value); int fd_lookup(int gpio); int open_value_file(int gpio); diff --git a/source/py_gpio.c b/source/py_gpio.c index 51df761..898e949 100644 --- a/source/py_gpio.c +++ b/source/py_gpio.c @@ -86,7 +86,6 @@ static int init_module(void) return 0; } - static void remember_gpio_direction(int gpio, int direction) { dyn_int_array_set(&gpio_direction, gpio, direction, -1); @@ -118,10 +117,7 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args, PyObject *kwargs) 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; + event_cleanup(); } gpio_unexport(gpio); } @@ -290,13 +286,12 @@ static PyObject *py_input_gpio(PyObject *self, PyObject *args) return py_value; } +//TODO: Come up with a way to merge py_read_byte_gpio and py_read_word_gpio // python function value = read_byte(channel) static PyObject *py_read_byte_gpio(PyObject *self, PyObject *args) { int gpio; char *channel; - int i; - unsigned int bit; unsigned int value = 0; PyObject *py_value; @@ -306,37 +301,63 @@ static PyObject *py_read_byte_gpio(PyObject *self, PyObject *args) return NULL; if (get_gpio_number(channel, &gpio)) { - } - - if (strcmp(channel, "XIO") == 0) { - int base_gpio = get_xio_base(); - for (i = 0; i < 8; i++) { - gpio = base_gpio + i; - if (gpio_get_value(gpio, &bit) < 0) { - char err[1024]; - snprintf(err, sizeof(err), "Could not get bit ('%s')", get_error_msg()); - PyErr_SetString(PyExc_RuntimeError, err); - return NULL; - } - value |= (bit << i); - } - } else if (strcmp(channel, "CSID") == 0) { - int base_gpio = 132; - for (i = 0; i < 8; i++) { - gpio = base_gpio + i; - if (gpio_get_value(gpio, &bit) < 0) { - char err[1024]; - snprintf(err, sizeof(err), "Could not get bit ('%s')", get_error_msg()); - PyErr_SetString(PyExc_RuntimeError, err); - return NULL; - } - value |= (bit << i); - } - } else { PyErr_SetString(PyExc_ValueError, "Invalid channel"); return NULL; } + // check channel is set up as an input or output + if (!module_setup || (dyn_int_array_get(&gpio_direction, gpio, -1) == -1)) + { + PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel first"); + return NULL; + } + + // We only want to get a 8 bits here + if (gpio_get_more(gpio, 8, &value) < 0) { + char err[1024]; + snprintf(err, sizeof(err), "Could not get 8 bits of data ('%s')", get_error_msg()); + PyErr_SetString(PyExc_RuntimeError, err); + return NULL; + } + + py_value = Py_BuildValue("i", value); + + return py_value; +} + +// python function value = read_word(channel) +static PyObject *py_read_word_gpio(PyObject *self, PyObject *args) +{ + int gpio; + char *channel; + unsigned int value = 0; + PyObject *py_value; + + clear_error_msg(); + + if (!PyArg_ParseTuple(args, "s", &channel)) + return NULL; + + if (get_gpio_number(channel, &gpio)) { + PyErr_SetString(PyExc_ValueError, "Invalid channel"); + return NULL; + } + + // check channel is set up as an input or output + if (!module_setup || (dyn_int_array_get(&gpio_direction, gpio, -1) == -1)) + { + PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel first"); + return NULL; + } + + // We only want to get a 8 bits here + if (gpio_get_more(gpio, 16, &value) < 0) { + char err[1024]; + snprintf(err, sizeof(err), "Could not get 16 bits of data ('%s')", get_error_msg()); + PyErr_SetString(PyExc_RuntimeError, err); + return NULL; + } + py_value = Py_BuildValue("i", value); return py_value; @@ -912,7 +933,8 @@ PyMethodDef gpio_methods[] = { {"cleanup", (PyCFunction)py_cleanup, METH_VARARGS | METH_KEYWORDS, "Clean up by resetting all GPIO channels that have been used by this program to INPUT with no pullup/pulldown and no event detection"}, {"output", py_output_gpio, METH_VARARGS, "Output to a GPIO channel\ngpio - gpio channel\nvalue - 0/1 or False/True or LOW/HIGH"}, {"input", py_input_gpio, METH_VARARGS, "Input from a GPIO channel. Returns HIGH=1=True or LOW=0=False\ngpio - gpio channel"}, - {"read_byte", py_read_byte_gpio, METH_VARARGS, "Read a byte from a set of GPIO channels. Returns 8-bit integer\ngpio - gpio channel. Valid channels: 'XIO', 'CSID'"}, + {"read_byte", py_read_byte_gpio, METH_VARARGS, "Read a byte (8 bits) from a set of GPIO channels. Returns 8-bits of integer data\ngpio - gpio channel."}, + {"read_word", py_read_word_gpio, METH_VARARGS, "Read a word (16 bits) from a set of GPIO channels. Returns 16-bits of integer data\ngpio - gpio channel."}, {"add_event_detect", (PyCFunction)py_add_event_detect, METH_VARARGS | METH_KEYWORDS, "Enable edge detection events for a particular GPIO channel.\nchannel - either board pin number or BCM number depending on which mode is set.\nedge - RISING, FALLING or BOTH\n[callback] - A callback function for the event (optional)\n[bouncetime] - Switch bounce timeout in ms for callback"}, {"remove_event_detect", py_remove_event_detect, METH_VARARGS, "Remove edge detection for a particular GPIO channel\ngpio - gpio channel"}, {"event_detected", py_event_detected, METH_VARARGS, "Returns True if an edge has occured on a given GPIO. You need to enable edge detection using add_event_detect() first.\ngpio - gpio channel"}, diff --git a/source/py_softpwm.c b/source/py_softpwm.c index 15566f7..d1bd265 100644 --- a/source/py_softpwm.c +++ b/source/py_softpwm.c @@ -62,8 +62,7 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args) return NULL; } else { if (!get_key(channel, key)) { - PyErr_SetString(PyExc_ValueError, "Invalid SOFTPWM key or name."); - return NULL; + softpwm_cleanup(); } softpwm_disable(key); }