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

GPIO able to be controlled by pin sysfs number like RPi.GPIO, close #65

This commit is contained in:
Robert Wolterman
2017-09-13 10:35:32 -05:00
parent e3a077bf82
commit e7db735a2f
9 changed files with 231 additions and 40 deletions

View File

@ -1,3 +1,7 @@
0.7.0
---
* Added ability to specify GPIO only as a number, this doesn't work for PWM/SPWM/LRADC/SERVO
0.6.2 0.6.2
--- ---
* Implementation for #77 - ability to push up binary pypi * Implementation for #77 - ability to push up binary pypi

View File

@ -4,8 +4,13 @@ package: clean
python setup.py sdist bdist_wheel python setup.py sdist bdist_wheel
python3 setup.py bdist_wheel python3 setup.py bdist_wheel
# PyPi Packaging
package3: package
@echo " ** PACKAGING FOR PYPI **"
python3 setup.py bdist_wheel
# PyPi Publishing # PyPi Publishing
publish: package publish: package package3
@echo " ** UPLOADING TO PYPI **" @echo " ** UPLOADING TO PYPI **"
twine upload dist/* twine upload dist/*

10
debian/changelog vendored
View File

@ -1,7 +1,13 @@
chip-io (0.7.0-1) unstable; urgency=low
* Added ability to specify GPIO only as a number, this doesn't work for PWM/SPWM/LRADC/SERVO
-- Robert Wolterman <robert.wolterman@gmail.com> Wed, 13 Sep 2017 09:51:00 -0600
chip-io (0.6.2-1) unstable; urgency=low chip-io (0.6.2-1) unstable; urgency=low
* Implementation for #77 - ability to push up binary pypi * Implementation for number 77 ability to push up binary pypi
* Implementation for #75 - wait_for_edge timeout * Implementation for number 75 wait for edge timeout
-- Robert Wolterman <robert.wolterman@gmail.com> Sun, 03 Sep 2017 21:34:00 -0600 -- Robert Wolterman <robert.wolterman@gmail.com> Sun, 03 Sep 2017 21:34:00 -0600

4
debian/files vendored
View File

@ -1,2 +1,2 @@
python-chip-io_0.6.1-1_armhf.deb python optional python-chip-io_0.7.0-1_armhf.deb python optional
python3-chip-io_0.6.1-1_armhf.deb python optional python3-chip-io_0.7.0-1_armhf.deb python optional

View File

@ -13,7 +13,7 @@ classifiers = ['Development Status :: 3 - Alpha',
'Topic :: System :: Hardware'] 'Topic :: System :: Hardware']
setup(name = 'CHIP_IO', setup(name = 'CHIP_IO',
version = '0.6.2', version = '0.7.0',
author = 'Robert Wolterman', author = 'Robert Wolterman',
author_email = 'robert.wolterman@gmail.com', author_email = 'robert.wolterman@gmail.com',
description = 'A module to control CHIP IO channels', description = 'A module to control CHIP IO channels',

View File

@ -371,6 +371,28 @@ int gpio_pud_capable(pins_t *pin)
return capable; return capable;
} }
int lookup_gpio_by_number(const char *num) {
// Convert the char to an int
char *ptr;
long ret;
int gpnum;
ret = strtol(num, &ptr, 10);
if (ret == 0) {
return -1;
}
// If we make it here, lets look for the data
pins_t *p;
for (p = pins_info; p->key != NULL; ++p) {
gpnum = gpio_number(p);
// If the number of the gpio pin matches the input
// we are
if (gpnum == (int)ret) {
return gpnum;
}
}
return -1;
}
int lookup_gpio_by_key(const char *key) int lookup_gpio_by_key(const char *key)
{ {
pins_t *p; pins_t *p;
@ -541,10 +563,13 @@ int get_gpio_number(const char *key, int *gpio)
if (*gpio <= 0) { if (*gpio <= 0) {
*gpio = lookup_gpio_by_name(key); *gpio = lookup_gpio_by_name(key);
if (*gpio <= 0) { if (*gpio <= 0) {
*gpio = lookup_gpio_by_altname(key); *gpio = lookup_gpio_by_altname(key);
if (*gpio <=0) { if (*gpio <=0) {
status = -1; /* error */ *gpio = lookup_gpio_by_number(key);
} if (*gpio <= 0) {
status = -1; /* error */
}
}
} }
} }
return status; return status;

View File

@ -94,6 +94,7 @@ int get_xio_base(void);
int is_this_chippro(void); int is_this_chippro(void);
int gpio_number(pins_t *pin); int gpio_number(pins_t *pin);
int gpio_pud_capable(pins_t *pin); int gpio_pud_capable(pins_t *pin);
int lookup_gpio_by_number(const char *num);
int lookup_gpio_by_key(const char *key); int lookup_gpio_by_key(const char *key);
int lookup_gpio_by_name(const char *name); int lookup_gpio_by_name(const char *name);
int lookup_gpio_by_altname(const char *altname); int lookup_gpio_by_altname(const char *altname);

View File

@ -85,6 +85,6 @@ void define_constants(PyObject *module)
bcm = Py_BuildValue("i", BCM); bcm = Py_BuildValue("i", BCM);
PyModule_AddObject(module, "BCM", bcm); PyModule_AddObject(module, "BCM", bcm);
version = Py_BuildValue("s", "0.6.2"); version = Py_BuildValue("s", "0.7");
PyModule_AddObject(module, "VERSION", version); PyModule_AddObject(module, "VERSION", version);
} }

View File

@ -36,6 +36,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <stdio.h>
#include "stdlib.h" #include "stdlib.h"
#include "Python.h" #include "Python.h"
#include "constants.h" #include "constants.h"
@ -129,13 +130,23 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args, PyObject *kwargs)
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
static char *kwlist[] = {"channel", NULL}; static char *kwlist[] = {"channel", NULL};
clear_error_msg(); clear_error_msg();
// Channel is optional // Channel is optional
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &channel)) { // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "|s", kwlist, &channel);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &inchan);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
} }
// The !channel fixes issues #50 // The !channel fixes issues #50
@ -157,6 +168,7 @@ static PyObject *py_setup_channel(PyObject *self, PyObject *args, PyObject *kwar
int gpio; int gpio;
int allowed = -1; int allowed = -1;
char *channel; char *channel;
int inchan;
int direction; int direction;
int pud = PUD_OFF; int pud = PUD_OFF;
int initial = 0; int initial = 0;
@ -164,13 +176,30 @@ static PyObject *py_setup_channel(PyObject *self, PyObject *args, PyObject *kwar
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|ii", kwlist, &channel, &direction, &pud, &initial)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "si|ii", kwlist, &channel, &direction, &pud, &initial);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "ii|ii", kwlist, &inchan, &direction, &pud, &initial);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (!module_setup) { if (!module_setup) {
init_module(); init_module();
} }
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;
}
if (direction != INPUT && direction != OUTPUT) if (direction != INPUT && direction != OUTPUT)
{ {
PyErr_SetString(PyExc_ValueError, "An invalid direction was passed to setup()"); PyErr_SetString(PyExc_ValueError, "An invalid direction was passed to setup()");
@ -259,23 +288,33 @@ static PyObject *py_setup_channel(PyObject *self, PyObject *args, PyObject *kwar
} }
remember_gpio_direction(gpio, direction); remember_gpio_direction(gpio, direction);
Py_RETURN_NONE; Py_RETURN_NONE;
} /* py_setup_channel */ } /* py_setup_channel */
// python function output(channel, value) // python function output(channel, value)
static PyObject *py_output_gpio(PyObject *self, PyObject *args) static PyObject *py_output_gpio(PyObject *self, PyObject *args)
{ {
int gpio; int gpio;
int value; int value;
char *channel; char *channel;
int inchan;
int allowed = -1; int allowed = -1;
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTuple(args, "si", &channel, &value)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTuple(args, "si", &channel, &value);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTuple(args, "ii", &inchan, &value);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (get_gpio_number(channel, &gpio)) { if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid channel"); PyErr_SetString(PyExc_ValueError, "Invalid channel");
@ -322,14 +361,25 @@ static PyObject *py_input_gpio(PyObject *self, PyObject *args)
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
unsigned int value; unsigned int value;
PyObject *py_value; PyObject *py_value;
int allowed = -1; int allowed = -1;
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTuple(args, "s", &channel);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTuple(args, "i", &inchan);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (get_gpio_number(channel, &gpio)) { if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid channel"); PyErr_SetString(PyExc_ValueError, "Invalid channel");
@ -376,14 +426,25 @@ static PyObject *py_read_byte_gpio(PyObject *self, PyObject *args)
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
unsigned int value = 0; unsigned int value = 0;
PyObject *py_value; PyObject *py_value;
int allowed = -1; int allowed = -1;
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTuple(args, "s", &channel);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTuple(args, "i", &inchan);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (get_gpio_number(channel, &gpio)) { if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid channel"); PyErr_SetString(PyExc_ValueError, "Invalid channel");
@ -430,14 +491,25 @@ static PyObject *py_read_word_gpio(PyObject *self, PyObject *args)
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
unsigned int value = 0; unsigned int value = 0;
PyObject *py_value; PyObject *py_value;
int allowed = -1; int allowed = -1;
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTuple(args, "s", &channel);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTuple(args, "i", &inchan);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (get_gpio_number(channel, &gpio)) { if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid channel"); PyErr_SetString(PyExc_ValueError, "Invalid channel");
@ -557,6 +629,7 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
int allowed = -1; int allowed = -1;
unsigned int bouncetime = 0; unsigned int bouncetime = 0;
PyObject *cb_func; PyObject *cb_func;
@ -564,8 +637,18 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|i", kwlist, &channel, &cb_func, &bouncetime)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "sO|i", kwlist, &channel, &cb_func, &bouncetime);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "iO|i", kwlist, &inchan, &cb_func, &bouncetime);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (!PyCallable_Check(cb_func)) if (!PyCallable_Check(cb_func))
{ {
@ -628,6 +711,7 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
int edge, result; int edge, result;
unsigned int bouncetime = 0; unsigned int bouncetime = 0;
int allowed = -1; int allowed = -1;
@ -636,8 +720,18 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|Oi", kwlist, &channel, &edge, &cb_func, &bouncetime)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "si|Oi", kwlist, &channel, &edge, &cb_func, &bouncetime);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "ii|Oi", kwlist, &inchan, &edge, &cb_func, &bouncetime);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (cb_func != NULL && !PyCallable_Check(cb_func)) if (cb_func != NULL && !PyCallable_Check(cb_func))
{ {
@ -714,6 +808,7 @@ static PyObject *py_remove_event_detect(PyObject *self, PyObject *args)
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
struct py_callback *cb = py_callbacks; struct py_callback *cb = py_callbacks;
struct py_callback *temp; struct py_callback *temp;
struct py_callback *prev = NULL; struct py_callback *prev = NULL;
@ -721,8 +816,18 @@ static PyObject *py_remove_event_detect(PyObject *self, PyObject *args)
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTuple(args, "s", &channel);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTuple(args, "i", &inchan);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (get_gpio_number(channel, &gpio)) { if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid channel"); PyErr_SetString(PyExc_ValueError, "Invalid channel");
@ -784,12 +889,23 @@ static PyObject *py_event_detected(PyObject *self, PyObject *args)
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
int allowed = -1; int allowed = -1;
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTuple(args, "s", &channel);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTuple(args, "i", &inchan);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (get_gpio_number(channel, &gpio)) { if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid channel"); PyErr_SetString(PyExc_ValueError, "Invalid channel");
@ -823,14 +939,26 @@ static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
int gpio; int gpio;
int edge, result, timeout; int edge, result, timeout;
char *channel; char *channel;
int inchan;
char error[81]; char error[81];
int allowed = -1; int allowed = -1;
clear_error_msg(); clear_error_msg();
timeout = -1; timeout = -1;
if (!PyArg_ParseTuple(args, "si|i", &channel, &edge, &timeout))
return NULL; // Try to parse the string
int rtn;
rtn = PyArg_ParseTuple(args, "si|i", &channel, &edge, &timeout);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTuple(args, "ii|i", &inchan, &edge, &timeout);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (get_gpio_number(channel, &gpio)) { if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid channel"); PyErr_SetString(PyExc_ValueError, "Invalid channel");
@ -903,12 +1031,23 @@ static PyObject *py_gpio_function(PyObject *self, PyObject *args)
unsigned int value; unsigned int value;
PyObject *func; PyObject *func;
char *channel; char *channel;
int inchan;
int allowed = -1; int allowed = -1;
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTuple(args, "s", &channel)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTuple(args, "s", &channel);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTuple(args, "i", &inchan);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (get_gpio_number(channel, &gpio)) { if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid channel"); PyErr_SetString(PyExc_ValueError, "Invalid channel");
@ -1116,14 +1255,25 @@ static PyObject *py_set_direction(PyObject *self, PyObject *args, PyObject *kwar
{ {
int gpio; int gpio;
char *channel; char *channel;
int inchan;
int direction; int direction;
int allowed = -1; int allowed = -1;
static char *kwlist[] = { "channel", "direction", NULL }; static char *kwlist[] = { "channel", "direction", NULL };
clear_error_msg(); clear_error_msg();
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si", kwlist, &channel, &direction)) // Try to parse the string
return NULL; int rtn;
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "si", kwlist, &channel, &direction);
if (!rtn) {
// Fall into here are try to parse an int
rtn = PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &inchan, &direction);
if (!rtn) {
return NULL;
}
// We make it here, we can convert inchan to a string for us to ensure it's valid
asprintf(&channel, "%i", inchan);
}
if (!module_setup) { if (!module_setup) {
init_module(); init_module();