mirror of
https://github.com/xtacocorex/CHIP_IO
synced 2025-07-19 20:33:21 +00:00
pull up/down feature addition to close #48. fixed gpio cleanup() function again, 3rd time is a charm. version bump to 0.3.4
This commit is contained in:
@ -1,3 +1,8 @@
|
||||
0.3.4
|
||||
---
|
||||
* Pull Up/Pull Down resistor setting now available for the R8 GPIO.
|
||||
* Some general cleanup
|
||||
|
||||
0.3.3
|
||||
----
|
||||
* Added Debug printing for all the capabilities with the toggle_debug() function
|
||||
|
@ -191,6 +191,15 @@ Inputs work similarly to outputs.::
|
||||
import CHIP_IO.GPIO as GPIO
|
||||
GPIO.setup("CSID0", GPIO.IN)
|
||||
|
||||
Other options when setting up pins::
|
||||
|
||||
# Specify pull up/pull down settings on a pin
|
||||
GPIO.setup("CSID0", GPIO.IN, pull_up_down=GPIO.PUD_UP)
|
||||
# Specify initial value for an output
|
||||
GPIO.setup("CSID0", GPIO.OUT, initial=1)
|
||||
|
||||
Pull Up/Down values are only for pins that are provided by the R8, the XIO are not capable of this. The allowable values are: PUD_OFF, PUD_UP, and PUD_DOWN.
|
||||
|
||||
Polling inputs::
|
||||
|
||||
if GPIO.input("CSID0"):
|
||||
|
2
setup.py
2
setup.py
@ -20,7 +20,7 @@ classifiers = ['Development Status :: 3 - Alpha',
|
||||
'Topic :: System :: Hardware']
|
||||
|
||||
setup(name = 'CHIP_IO',
|
||||
version = '0.3.3',
|
||||
version = '0.3.4',
|
||||
author = 'Robert Wolterman',
|
||||
author_email = 'robert.wolterman@gmail.com',
|
||||
description = 'A module to control CHIP IO channels',
|
||||
|
@ -249,6 +249,22 @@ int gpio_number(pins_t *pin)
|
||||
return gpio_num;
|
||||
} /* gpio_number */
|
||||
|
||||
int gpio_pud_capable(pins_t *pin)
|
||||
{
|
||||
int capable = -1;
|
||||
|
||||
switch (pin->base_method) {
|
||||
case BASE_METHOD_AS_IS:
|
||||
capable = 1;
|
||||
break;
|
||||
|
||||
case BASE_METHOD_XIO:
|
||||
capable = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return capable;
|
||||
}
|
||||
|
||||
int lookup_gpio_by_key(const char *key)
|
||||
{
|
||||
@ -283,6 +299,39 @@ int lookup_gpio_by_altname(const char *altname)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lookup_pud_capable_by_key(const char *key)
|
||||
{
|
||||
pins_t *p;
|
||||
for (p = pins_info; p->key != NULL; ++p) {
|
||||
if (strcmp(p->key, key) == 0) {
|
||||
return gpio_pud_capable(p);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lookup_pud_capable_by_name(const char *name)
|
||||
{
|
||||
pins_t *p;
|
||||
for (p = pins_info; p->name != NULL; ++p) {
|
||||
if (strcmp(p->name, name) == 0) {
|
||||
return gpio_pud_capable(p);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lookup_pud_capable_by_altname(const char *altname)
|
||||
{
|
||||
pins_t *p;
|
||||
for (p = pins_info; p->altname != NULL; ++p) {
|
||||
if (strcmp(p->altname, altname) == 0) {
|
||||
return gpio_pud_capable(p);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int lookup_ain_by_key(const char *key)
|
||||
{
|
||||
pins_t *p;
|
||||
@ -396,17 +445,29 @@ int get_gpio_number(const char *key, int *gpio)
|
||||
return status;
|
||||
}
|
||||
|
||||
int compute_port_pin(const char *key, int *port, int *pin)
|
||||
int compute_port_pin(const char *key, int gpio, int *port, int *pin)
|
||||
{
|
||||
int gpio;
|
||||
int rtn;
|
||||
|
||||
rtn = get_gpio_number(key, &gpio);
|
||||
|
||||
// Method from:
|
||||
//https://bbs.nextthing.co/t/chippy-gonzales-fast-gpio/14056/6?u=xtacocorex
|
||||
*port = gpio / 32;
|
||||
*pin = gpio % 32;
|
||||
int capable = 0;
|
||||
int rtn = -1;
|
||||
|
||||
capable = lookup_pud_capable_by_key(key);
|
||||
if (capable < 0) {
|
||||
capable = lookup_pud_capable_by_name(key);
|
||||
if (capable < 0) {
|
||||
capable = lookup_gpio_by_altname(key);
|
||||
if (capable < 0) {
|
||||
capable = 0; // default to false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (capable) {
|
||||
// Method from:
|
||||
// https://bbs.nextthing.co/t/chippy-gonzales-fast-gpio/14056/6?u=xtacocorex
|
||||
*port = gpio / 32;
|
||||
*pin = gpio % 32;
|
||||
rtn = 0;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
@ -92,9 +92,13 @@ int DEBUG;
|
||||
|
||||
int get_xio_base(void);
|
||||
int gpio_number(pins_t *pin);
|
||||
int gpio_pud_capable(pins_t *pin);
|
||||
int lookup_gpio_by_key(const char *key);
|
||||
int lookup_gpio_by_name(const char *name);
|
||||
int lookup_gpio_by_altname(const char *altname);
|
||||
int lookup_pud_capable_by_key(const char *key);
|
||||
int lookup_pud_capable_by_name(const char *name);
|
||||
int lookup_pud_capable_by_altname(const char *altname);
|
||||
int lookup_ain_by_key(const char *key);
|
||||
int lookup_ain_by_name(const char *name);
|
||||
int copy_key_by_key(const char *input_key, char *key);
|
||||
@ -113,4 +117,4 @@ void clear_error_msg(void);
|
||||
char *get_error_msg(void);
|
||||
void add_error_msg(char *msg);
|
||||
void toggle_debug(void);
|
||||
int compute_port_pin(const char *key, int *port, int *pin);
|
||||
int compute_port_pin(const char *key, int gpio, int *port, int *pin);
|
||||
|
@ -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.3");
|
||||
version = Py_BuildValue("s", "0.3.4");
|
||||
PyModule_AddObject(module, "VERSION", version);
|
||||
}
|
||||
|
@ -38,17 +38,23 @@ SOFTWARE.
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include "event_gpio.h"
|
||||
#include "common.h"
|
||||
|
||||
const char *stredge[4] = {"none", "rising", "falling", "both"};
|
||||
|
||||
// Memory Map for PUD
|
||||
uint8_t *memmap;
|
||||
|
||||
// file descriptors
|
||||
struct fdx
|
||||
{
|
||||
@ -85,6 +91,63 @@ dyn_int_array_t *event_occurred = NULL;
|
||||
int thread_running = 0;
|
||||
int epfd = -1;
|
||||
|
||||
// Thanks to WereCatf and Chippy-Gonzales for the Memory Mapping code/help
|
||||
int map_pio_memory()
|
||||
{
|
||||
if (DEBUG)
|
||||
printf(" ** map_pio_memory: opening /dev/mem **\n");
|
||||
int fd = open("/dev/mem", O_RDWR|O_SYNC);
|
||||
if(fd < 0) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "map_pio_memory: could not open /dev/mem (%s)", strerror(errno));
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
}
|
||||
// uint32_t addr = 0x01c20800 & ~(getpagesize() - 1);
|
||||
//Requires memmap to be on pagesize-boundary
|
||||
if (DEBUG)
|
||||
printf(" ** map_pio_memory: mapping memory **\n");
|
||||
memmap = (uint8_t *)mmap(NULL, getpagesize()*2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x01C20000);
|
||||
if(memmap == NULL) {
|
||||
char err[256];
|
||||
snprintf(err, sizeof(err), "map_pio_memory: mmap failed (%s)", strerror(errno));
|
||||
add_error_msg(err);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
//Set memmap to point to PIO-registers
|
||||
if (DEBUG)
|
||||
printf(" ** map_pio_memory: moving to pio registers **\n");
|
||||
memmap=memmap+0x800;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_get_pud(int port, int pin)
|
||||
{
|
||||
if (DEBUG)
|
||||
printf(" ** gpio_get_pud: port %d, pin %d **\n", port, pin);
|
||||
volatile uint32_t *pioMem32, *configRegister;
|
||||
pioMem32=(uint32_t *)(memmap+port*0x24+0x1c); //0x1c == pull-register
|
||||
configRegister=pioMem32+(pin >> 4);
|
||||
return *configRegister >> ((pin & 15) * 2) & 3;
|
||||
}
|
||||
|
||||
int gpio_set_pud(int port, int pin, uint8_t value)
|
||||
{
|
||||
if (DEBUG)
|
||||
printf(" ** gpio_set_pud: port %d, pin %d, value %d **\n", port, pin, value);
|
||||
value &= 3;
|
||||
volatile uint32_t *pioMem32, *configRegister;
|
||||
uint32_t mask;
|
||||
pioMem32=(uint32_t *)(memmap+port*0x24+0x1c); //0x1c == pull-register
|
||||
configRegister=pioMem32+(pin >> 4);
|
||||
mask = ~(3 << ((pin & 15) * 2));
|
||||
*configRegister &= mask;
|
||||
*configRegister |= value << ((pin & 15) * 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int gpio_export(int gpio)
|
||||
{
|
||||
@ -119,7 +182,7 @@ int gpio_export(int gpio)
|
||||
|
||||
// add to list
|
||||
if (DEBUG)
|
||||
printf(" ** gpio_export: creating data struct **\n");
|
||||
printf(" ** gpio_export: creating data struct **\n");
|
||||
new_gpio = malloc(sizeof(struct gpio_exp)); ASSRT(new_gpio != NULL);
|
||||
|
||||
new_gpio->gpio = gpio;
|
||||
|
@ -36,6 +36,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define NO_EDGE 0
|
||||
#define RISING_EDGE 1
|
||||
#define FALLING_EDGE 2
|
||||
@ -54,6 +56,12 @@ SOFTWARE.
|
||||
#define PUD_DOWN 1
|
||||
#define PUD_UP 2
|
||||
|
||||
extern uint8_t *memmap;
|
||||
|
||||
int map_pio_memory(void);
|
||||
int gpio_get_pud(int port, int pin);
|
||||
int gpio_set_pud(int port, int pin, uint8_t value);
|
||||
|
||||
int gpio_export(int gpio);
|
||||
int gpio_unexport(int gpio);
|
||||
void exports_cleanup(void);
|
||||
|
163
source/py_gpio.c
163
source/py_gpio.c
@ -58,8 +58,29 @@ struct py_callback
|
||||
};
|
||||
static struct py_callback *py_callbacks = NULL;
|
||||
|
||||
// python function toggle_debug()
|
||||
static PyObject *py_toggle_debug(PyObject *self, PyObject *args)
|
||||
{
|
||||
// toggle debug printing
|
||||
toggle_debug();
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static int init_module(void)
|
||||
{
|
||||
clear_error_msg();
|
||||
|
||||
if (map_pio_memory() < 0) {
|
||||
char err[2000];
|
||||
snprintf(err, sizeof(err), "init_module error (%s)", get_error_msg());
|
||||
PyErr_SetString(PyExc_RuntimeError, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If we make it here, we're good to go
|
||||
if (DEBUG)
|
||||
printf(" ** init_module: setup complete **\n");
|
||||
module_setup = 1;
|
||||
|
||||
return 0;
|
||||
@ -93,7 +114,7 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
}
|
||||
|
||||
// The !channel fixes issues #50
|
||||
if (!channel || strcmp(channel, "") == 0) {
|
||||
if (channel == NULL || strcmp(channel, "\0") == 0) {
|
||||
event_cleanup();
|
||||
} else {
|
||||
if (get_gpio_number(channel, &gpio) < 0) {
|
||||
@ -111,68 +132,91 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
// python function setup(channel, direction, pull_up_down=PUD_OFF, initial=None)
|
||||
static PyObject *py_setup_channel(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
int gpio;
|
||||
char *channel;
|
||||
int direction;
|
||||
int pud = PUD_OFF;
|
||||
int initial = 0;
|
||||
static char *kwlist[] = {"channel", "direction", "pull_up_down", "initial", NULL};
|
||||
|
||||
clear_error_msg();
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|ii", kwlist, &channel, &direction, &pud, &initial))
|
||||
return NULL;
|
||||
|
||||
if (!module_setup) {
|
||||
init_module();
|
||||
}
|
||||
|
||||
if (direction != INPUT && direction != OUTPUT)
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "An invalid direction was passed to setup()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (direction == OUTPUT)
|
||||
pud = PUD_OFF;
|
||||
|
||||
if (pud != PUD_OFF && pud != PUD_DOWN && pud != PUD_UP)
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid value for pull_up_down - should be either PUD_OFF, PUD_UP or PUD_DOWN");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 (gpio_export(gpio) < 0) {
|
||||
char err[2000];
|
||||
snprintf(err, sizeof(err), "Error setting up channel %s, maybe already exported? (%s)", channel, get_error_msg());
|
||||
PyErr_SetString(PyExc_RuntimeError, err);
|
||||
return NULL;
|
||||
}
|
||||
if (gpio_set_direction(gpio, direction) < 0) {
|
||||
char err[2000];
|
||||
snprintf(err, sizeof(err), "Error setting direction %d on channel %s. (%s)", direction, channel, get_error_msg());
|
||||
PyErr_SetString(PyExc_RuntimeError, err);
|
||||
return NULL;
|
||||
}
|
||||
if (direction == OUTPUT) {
|
||||
if (gpio_set_value(gpio, initial) < 0) {
|
||||
int gpio;
|
||||
char *channel;
|
||||
int direction;
|
||||
int pud = PUD_OFF;
|
||||
int initial = 0;
|
||||
static char *kwlist[] = {"channel", "direction", "pull_up_down", "initial", NULL};
|
||||
|
||||
clear_error_msg();
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "si|ii", kwlist, &channel, &direction, &pud, &initial))
|
||||
return NULL;
|
||||
|
||||
if (!module_setup) {
|
||||
init_module();
|
||||
}
|
||||
|
||||
if (direction != INPUT && direction != OUTPUT)
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "An invalid direction was passed to setup()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Force pud to be off if we're configured for output
|
||||
if (direction == OUTPUT) {
|
||||
pud = PUD_OFF;
|
||||
}
|
||||
|
||||
if (pud != PUD_OFF && pud != PUD_DOWN && pud != PUD_UP)
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid value for pull_up_down - should be either PUD_OFF, PUD_UP or PUD_DOWN");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 (gpio_export(gpio) < 0) {
|
||||
char err[2000];
|
||||
snprintf(err, sizeof(err), "Error setting up channel %s, maybe already exported? (%s)", channel, get_error_msg());
|
||||
PyErr_SetString(PyExc_RuntimeError, err);
|
||||
return NULL;
|
||||
}
|
||||
if (gpio_set_direction(gpio, direction) < 0) {
|
||||
char err[2000];
|
||||
snprintf(err, sizeof(err), "Error setting direction %d on channel %s. (%s)", direction, channel, get_error_msg());
|
||||
PyErr_SetString(PyExc_RuntimeError, err);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Pull Up/Down
|
||||
int port, pin;
|
||||
if (compute_port_pin(channel, gpio, &port, &pin) < 0) {
|
||||
char err[2000];
|
||||
snprintf(err, sizeof(err), "Pull Up/Down setting not capable for %s. (%s)", channel, get_error_msg());
|
||||
PyErr_SetString(PyExc_ValueError, err);
|
||||
return NULL;
|
||||
} else {
|
||||
// Set the PUD
|
||||
gpio_set_pud(port, pin, pud);
|
||||
// Check it was set properly
|
||||
int pudr = gpio_get_pud(port, pin);
|
||||
if (pudr != pud) {
|
||||
char err[2000];
|
||||
snprintf(err, sizeof(err), "Error setting pull up down %d on channel %s", pud, channel);
|
||||
PyErr_SetString(PyExc_RuntimeError, err);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (direction == OUTPUT) {
|
||||
if (gpio_set_value(gpio, initial) < 0) {
|
||||
char err[2000];
|
||||
snprintf(err, sizeof(err), "Error setting initial value %d on channel %s. (%s)", initial, channel, get_error_msg());
|
||||
PyErr_SetString(PyExc_RuntimeError, err);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
remember_gpio_direction(gpio, direction);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
remember_gpio_direction(gpio, direction);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
} /* py_setup_channel */
|
||||
|
||||
|
||||
@ -831,6 +875,7 @@ PyMethodDef gpio_methods[] = {
|
||||
{"selftest", py_selftest, METH_VARARGS, "Internal unit tests"},
|
||||
{"direction", (PyCFunction)py_set_direction, METH_VARARGS | METH_KEYWORDS, "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" },
|
||||
{"toggle_debug", py_toggle_debug, METH_VARARGS, "Toggles the enabling/disabling of Debug print output"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
@ -34,6 +34,15 @@ SOFTWARE.
|
||||
#include "common.h"
|
||||
#include "c_softpwm.h"
|
||||
|
||||
// python function toggle_debug()
|
||||
static PyObject *py_toggle_debug(PyObject *self, PyObject *args)
|
||||
{
|
||||
// toggle debug printing
|
||||
toggle_debug();
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
// python function cleanup(channel=None)
|
||||
static PyObject *py_cleanup(PyObject *self, PyObject *args)
|
||||
{
|
||||
@ -48,8 +57,9 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args)
|
||||
return NULL;
|
||||
|
||||
// The !channel fixes issue #50
|
||||
if (!channel || strcmp(channel, "") == 0) {
|
||||
if (channel == NULL || strcmp(channel, "\0") == 0) {
|
||||
softpwm_cleanup();
|
||||
return NULL;
|
||||
} else {
|
||||
if (!get_key(channel, key)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Invalid SOFTPWM key or name.");
|
||||
@ -195,11 +205,12 @@ static PyObject *py_set_frequency(PyObject *self, PyObject *args, PyObject *kwar
|
||||
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'"},
|
||||
{ "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", (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"},
|
||||
{"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", (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"},
|
||||
{"toggle_debug", py_toggle_debug, METH_VARARGS, "Toggles the enabling/disabling of Debug print output"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user