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

Reworked a lot of error handling.

This commit is contained in:
fordsfords
2016-07-02 18:57:03 -05:00
parent 093922567a
commit 71b6829804
11 changed files with 442 additions and 104 deletions

View File

@ -131,7 +131,7 @@ pins_t pins_info[] = {
{ "CSID7", "U14_38", 139, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_39", 0, BASE_METHOD_AS_IS, -1, -1},
{ "GND", "U14_40", 0, BASE_METHOD_AS_IS, -1, -1},
{ NULL, NULL, 0 }
{ NULL, NULL, 0, 0, -1, -1}
};
@ -178,10 +178,10 @@ int get_xio_base(void)
/* Found the expander, get the contents of base */
snprintf(base_file, sizeof(base_file), "%s/%s/base", GPIO_PATH, ent->d_name); BUF2SMALL(base_file);
base_fp = fopen(base_file, "r"); ASSRT(base_fp != NULL);
s = fgets(input_line, sizeof(input_line), base_fp);
ASSRT(s == input_line && strlen(input_line) < sizeof(input_line)-1);
s = fgets(input_line, sizeof(input_line), base_fp); BUF2SMALL(input_line); ASSRT(s);
fclose(base_fp);
xio_base_address = atoi(input_line); /* remember the result */
/* Remember the value in the static local. */
xio_base_address = atoi(input_line); ASSRT(xio_base_address > 0);
num_get_xio_base++; /* for self-test purposes */
}
} /* if label file is open */
@ -377,7 +377,7 @@ int build_path(const char *partial_path, const char *prefix, char *full_path, si
dp = opendir (partial_path);
if (dp != NULL) {
while ((ep = readdir (dp))) {
// Enforce that the prefix must be the first part of the file
// Enforce that the prefix must be the first part of the file name
char* found_string = strstr(ep->d_name, prefix);
if (found_string != NULL && (ep->d_name - found_string) == 0) {
@ -419,3 +419,75 @@ int get_spi_bus_path_number(unsigned int spi)
return -1;
}
}
struct dyn_int_array {
int num_elements;
int *array;
};
void *dyn_int_array_create(int initial_num_elements, int initial_val)
{
struct dyn_int_array *new_array = (struct dyn_int_array *)malloc(sizeof(struct dyn_int_array));
ASSRT(new_array != NULL);
new_array->num_elements = initial_num_elements;
new_array->array = (int *)malloc(initial_num_elements * sizeof(int));
ASSRT(new_array->array != NULL);
int i;
for (i = 0; i < initial_num_elements; i++)
new_array->array[i] = initial_val;
return (void *)new_array;
} /* dyn_int_array_create */
void dyn_int_array_set(void **in_array, int i, int val, int initial_val)
{
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
if (array == NULL)
array = dyn_int_array_create(i * 3 / 2, initial_val);
if (i >= array->num_elements) {
int new_num_elements = i * 3 / 2; /* half-again larger than current request */
array->array = realloc(array->array, new_num_elements * sizeof(int));
ASSRT(array->array != NULL);
// Zero out the newly allocated elements.
while (array->num_elements < new_num_elements) {
array->array[array->num_elements] = initial_val;
array->num_elements ++;
}
}
array->array[i] = val;
*in_array = (void *)array;
} /* dyn_int_array_set */
int dyn_int_array_get(void **in_array, int i, int initial_val)
{
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
if (array == NULL)
array = dyn_int_array_create(i * 3 / 2, initial_val);
if (i >= array->num_elements) {
int new_num_elements = i * 3 / 2; /* half-again larger than current request */
array->array = realloc(array->array, new_num_elements * sizeof(int));
ASSRT(array->array != NULL);
// Zero out the newly allocated elements.
while (array->num_elements < new_num_elements) {
array->array[array->num_elements] = initial_val;
array->num_elements ++;
}
}
return array->array[i];
*in_array = (void *)array;
} /* dyn_int_array_get */
void dyn_int_array_delete(void **in_array)
{
struct dyn_int_array *array = (struct dyn_int_array *)(*in_array);
free(array->array);
free(array);
} /* dyn_int_array_delete */

View File

@ -41,7 +41,7 @@ SOFTWARE.
// See http://blog.geeky-boy.com/2016/06/of-compiler-warnings-and-asserts-in.html
#define ASSRT(cond_expr) do { \
if (!(cond_expr)) { \
fprintf(stderr, "ASSRT failed at %s:%d (%s)", __FILE__, __LINE__, #cond_expr); \
fprintf(stderr, "ASSRT failed at %s:%d (%s)\n", __FILE__, __LINE__, #cond_expr); \
fflush(stderr); \
abort(); \
} } while (0)
@ -75,6 +75,7 @@ int setup_error;
int module_setup;
int get_xio_base(void);
int gpio_number(pins_t *pin);
int lookup_gpio_by_key(const char *key);
int lookup_gpio_by_name(const char *name);
int lookup_ain_by_key(const char *key);
@ -89,3 +90,6 @@ int get_pwm_key(const char *input, char *key);
int get_adc_ain(const char *key, unsigned int *ain);
int build_path(const char *partial_path, const char *prefix, char *full_path, size_t full_path_len);
int get_spi_bus_path_number(unsigned int spi);
void dyn_int_array_set(void **in_array, int i, int val, int initial_val);
int dyn_int_array_get(void **in_array, int i, int initial_val);
void dyn_int_array_delete(void **in_array);

View File

@ -77,7 +77,7 @@ struct gpio_exp
struct gpio_exp *exported_gpios = NULL;
pthread_t threads;
int event_occurred[430] = { 0 };
void *event_occurred = NULL;
int thread_running = 0;
int epfd = -1;
@ -92,8 +92,12 @@ int gpio_export(unsigned int gpio)
return -1;
}
len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); BUF2SMALL(str_gpio);
ssize_t s = write(fd, str_gpio, len); ASSRT(s == len);
ssize_t s = write(fd, str_gpio, len);
close(fd);
if (s != len)
{
return -1;
}
// add to list
new_gpio = malloc(sizeof(struct gpio_exp));
@ -183,8 +187,9 @@ int open_value_file(unsigned int gpio)
// create file descriptor of value file
snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d/value", gpio); BUF2SMALL(filename);
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0)
return -1;
if ((fd = open(filename, O_RDONLY | O_NONBLOCK)) < 0) {
return -1;
}
add_fd_list(gpio, fd);
return fd;
}
@ -240,7 +245,6 @@ int gpio_set_direction(unsigned int gpio, unsigned int in_flag)
} else {
strncpy(direction, "in", ARRAY_SIZE(direction) - 1);
}
ssize_t s = write(fd, direction, strlen(direction)); ASSRT(s == strlen(direction));
close(fd);
return 0;
@ -285,8 +289,11 @@ int gpio_set_value(unsigned int gpio, unsigned int value)
strncpy(vstr, "0", ARRAY_SIZE(vstr) - 1);
}
ssize_t s = write(fd, vstr, strlen(vstr)); ASSRT(s == strlen(vstr));
ssize_t s = write(fd, vstr, strlen(vstr));
close(fd);
if (s != strlen(vstr))
return -2;
return 0;
}
@ -454,11 +461,12 @@ void *poll_thread(void *threadarg)
thread_running = 0;
pthread_exit(NULL);
}
// The return value represents the ending level after the edge.
gpio = gpio_lookup(events.data.fd);
if (gpio_initial(gpio)) { // ignore first epoll trigger
set_initial_false(gpio);
} else {
event_occurred[gpio] = 1;
dyn_int_array_set(&event_occurred, gpio, 1, 0);
run_callbacks(gpio);
}
}
@ -512,6 +520,7 @@ int gpio_event_remove(unsigned int gpio)
return 0;
}
// add_edge_detect assumes the caller has ensured the GPIO is already exported.
int add_edge_detect(unsigned int gpio, unsigned int edge)
// return values:
// 0 - Success
@ -528,31 +537,34 @@ int add_edge_detect(unsigned int gpio, unsigned int edge)
return 1;
// export /sys/class/gpio interface
gpio_export(gpio);
gpio_set_direction(gpio, 0); // 0=input
gpio_set_edge(gpio, edge);
if (!fd)
{
if ((fd = open_value_file(gpio)) == -1)
if ((fd = open_value_file(gpio)) == -1) {
return 2;
}
}
// create epfd if not already open
if ((epfd == -1) && ((epfd = epoll_create(1)) == -1))
if ((epfd == -1) && ((epfd = epoll_create(1)) == -1)) {
return 2;
}
// add to epoll fd
ev.events = EPOLLIN | EPOLLET | EPOLLPRI;
ev.data.fd = fd;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1)
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
return 2;
}
// start poll thread if it is not already running
if (!thread_running)
{
if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0)
if (pthread_create(&threads, NULL, poll_thread, (void *)t) != 0) {
return 2;
}
}
return 0;
@ -576,13 +588,13 @@ void remove_edge_detect(unsigned int gpio)
gpio_event_remove(gpio);
// clear detected flag
event_occurred[gpio] = 0;
dyn_int_array_set(&event_occurred, gpio, 0, 0);
}
int event_detected(unsigned int gpio)
{
if (event_occurred[gpio]) {
event_occurred[gpio] = 0;
if (dyn_int_array_get(&event_occurred, gpio, 0)) {
dyn_int_array_set(&event_occurred, gpio, 0, 0);
return 1;
} else {
return 0;
@ -612,7 +624,7 @@ int blocking_wait_for_edge(unsigned int gpio, unsigned int edge)
return 2;
// export /sys/class/gpio interface
gpio_export(gpio);
gpio_export(gpio); // ignore errors
gpio_set_direction(gpio, 0); // 0=input
gpio_set_edge(gpio, edge);

View File

@ -45,7 +45,7 @@ SOFTWARE.
static int gpio_warnings = 1;
int max_gpio = -1;
int *gpio_direction = NULL;
void *gpio_direction = NULL;
struct py_callback
{
@ -60,26 +60,15 @@ static struct py_callback *py_callbacks = NULL;
static int init_module(void)
{
int i;
max_gpio = 1024;
gpio_direction = (int *)malloc(max_gpio * sizeof(int));
for (i=0; i<max_gpio; i++)
gpio_direction[i] = -1;
module_setup = 1;
return 0;
}
static void set_gpio_direction(int gpio, int direction)
static void remember_gpio_direction(int gpio, int direction)
{
if (gpio >= max_gpio) { /* Does gpio_direction need to be expanded? */
max_gpio = gpio + (gpio / 2);
gpio_direction = (int *)realloc(gpio_direction, max_gpio * sizeof(int));
}
gpio_direction[gpio] = direction;
dyn_int_array_set(&gpio_direction, gpio, direction, -1);
}
// python function cleanup()
@ -124,21 +113,23 @@ static PyObject *py_setup_channel(PyObject *self, PyObject *args, PyObject *kwar
return NULL;
}
if (get_gpio_number(channel, &gpio))
return NULL;
gpio_export(gpio);
gpio_set_direction(gpio, direction);
// For some reason, the following code doesn't work for XIOs. Skip.
if (!(gpio >= lookup_gpio_by_name("XIO-P0") && gpio <= lookup_gpio_by_name("XIO-P7"))) {
if (direction == OUTPUT) {
gpio_set_value(gpio, initial);
} else {
gpio_set_value(gpio, pud);
}
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_ValueError, "Invalid value for channel");
return NULL;
}
set_gpio_direction(gpio, direction);
int result = gpio_export(gpio);
if (result < 0) {
PyErr_SetString(PyExc_ValueError, "Channel in use (already exported)");
return NULL;
}
gpio_set_direction(gpio, direction);
// For some reason, the following code doesn't work for XIOs. Skip.
if (direction == OUTPUT) {
gpio_set_value(gpio, initial);
}
remember_gpio_direction(gpio, direction);
Py_RETURN_NONE;
}
@ -153,16 +144,22 @@ static PyObject *py_output_gpio(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "si", &channel, &value))
return NULL;
if (get_gpio_number(channel, &gpio))
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
return NULL;
}
if (!module_setup || gpio_direction[gpio] != OUTPUT)
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != OUTPUT)
{
PyErr_SetString(PyExc_RuntimeError, "The GPIO channel has not been setup() as an OUTPUT");
return NULL;
}
gpio_set_value(gpio, value);
int result = gpio_set_value(gpio, value);
if (result < 0) {
PyErr_SetString(PyExc_RuntimeError, "Could not write to channel");
return NULL;
}
Py_RETURN_NONE;
}
@ -178,11 +175,13 @@ static PyObject *py_input_gpio(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (get_gpio_number(channel, &gpio))
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
return NULL;
}
// check channel is set up as an input or output
if (!module_setup || (gpio_direction[gpio] != INPUT && gpio_direction[gpio] != 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;
@ -282,8 +281,10 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
return NULL;
}
if (get_gpio_number(channel, &gpio))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
return NULL;
}
// check to ensure gpio is one of the allowed pins
if (gpio != lookup_gpio_by_name("AP-EINT3")
@ -294,7 +295,7 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
}
// check channel is set up as an input
if (!module_setup || gpio_direction[gpio] != INPUT)
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
{
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
return NULL;
@ -305,7 +306,6 @@ static PyObject *py_add_event_callback(PyObject *self, PyObject *args, PyObject
PyErr_SetString(PyExc_RuntimeError, "Add event detection using add_event_detect first before adding a callback");
return NULL;
}
if (add_py_callback(channel, gpio, bouncetime, cb_func) != 0)
return NULL;
@ -331,8 +331,10 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
return NULL;
}
if (get_gpio_number(channel, &gpio))
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
return NULL;
}
// check to ensure gpio is one of the allowed pins
if (gpio != lookup_gpio_by_name("AP-EINT3")
@ -343,7 +345,7 @@ static PyObject *py_add_event_detect(PyObject *self, PyObject *args, PyObject *k
}
// check channel is set up as an input
if (!module_setup || gpio_direction[gpio] != INPUT)
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
{
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
return NULL;
@ -387,8 +389,10 @@ static PyObject *py_remove_event_detect(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (get_gpio_number(channel, &gpio))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
return NULL;
}
// check to ensure gpio is one of the allowed pins
if (gpio != lookup_gpio_by_name("AP-EINT3")
@ -431,8 +435,10 @@ static PyObject *py_event_detected(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (get_gpio_number(channel, &gpio))
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
return NULL;
}
if (event_detected(gpio))
Py_RETURN_TRUE;
@ -451,8 +457,10 @@ static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "si", &channel, &edge))
return NULL;
if (get_gpio_number(channel, &gpio))
return NULL;
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
return NULL;
}
// check to ensure gpio is one of the allowed pins
if (gpio != lookup_gpio_by_name("AP-EINT3")
@ -463,7 +471,7 @@ static PyObject *py_wait_for_edge(PyObject *self, PyObject *args)
}
// check channel is setup as an input
if (!module_setup || gpio_direction[gpio] != INPUT)
if (!module_setup || dyn_int_array_get(&gpio_direction, gpio, -1) != INPUT)
{
PyErr_SetString(PyExc_RuntimeError, "You must setup() the GPIO channel as an input first");
return NULL;
@ -507,8 +515,10 @@ static PyObject *py_gpio_function(PyObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (get_gpio_number(channel, &gpio))
if (get_gpio_number(channel, &gpio)) {
PyErr_SetString(PyExc_RuntimeError, "Invalid channel");
return NULL;
}
if (setup_error)
{
@ -538,17 +548,105 @@ static PyObject *py_setwarnings(PyObject *self, PyObject *args)
// Internal unit tests
extern int num_get_xio_base;
extern pins_t pins_info[];
static PyObject *py_selftest(PyObject *self, PyObject *args)
{
int input;
if (!PyArg_ParseTuple(args, "i", &input))
return NULL;
printf("Testing get_xio_base\n");
ASSRT(num_get_xio_base == 0);
int base = get_xio_base(); ASSRT(base > 0 && base < 1024);
ASSRT(num_get_xio_base == 1);
int second_base = get_xio_base(); ASSRT(second_base == base);
ASSRT(num_get_xio_base == 1); /* make sure it didn't do the full calc a second time. */
printf("base=%d\n", base);
printf("Testing lookup_gpio_by_key\n");
ASSRT(0 == lookup_gpio_by_key("U13_1"));
ASSRT(48 == lookup_gpio_by_key("U13_9"));
ASSRT(47 == lookup_gpio_by_key("U13_11"));
ASSRT(base == lookup_gpio_by_key("U14_13"));
ASSRT((base+1) == lookup_gpio_by_key("U14_14"));
ASSRT((base+6) == lookup_gpio_by_key("U14_19"));
ASSRT((base+7) == lookup_gpio_by_key("U14_20"));
ASSRT(193 == lookup_gpio_by_key("U14_23"));
ASSRT(139 == lookup_gpio_by_key("U14_38"));
ASSRT(0 == lookup_gpio_by_key("U14_40"));
ASSRT(0 == lookup_gpio_by_key("NOTFOUND"));
ASSRT(0 == lookup_gpio_by_key("U14_"));
ASSRT(0 == lookup_gpio_by_key("U14_4000"));
printf("Testing lookup_gpio_by_name\n");
ASSRT(0 == lookup_gpio_by_name("GND"));
ASSRT(48 == lookup_gpio_by_name("TWI1-SDA"));
ASSRT(47 == lookup_gpio_by_name("TWI1-SCK"));
ASSRT(base == lookup_gpio_by_name("XIO-P0"));
ASSRT((base+6) == lookup_gpio_by_name("XIO-P6"));
ASSRT((base+7) == lookup_gpio_by_name("XIO-P7"));
ASSRT(139 == lookup_gpio_by_name("CSID7"));
ASSRT(0 == lookup_gpio_by_name("NOTFOUND"));
ASSRT(0 == lookup_gpio_by_name("CSID"));
ASSRT(0 == lookup_gpio_by_name("CSID777"));
printf("Testing lookup_ain_by_key\n");
ASSRT(-1 == lookup_ain_by_key("U14_1"));
ASSRT(0 == lookup_ain_by_key("U14_11"));
ASSRT(-1 == lookup_ain_by_key("NOTFOUND"));
ASSRT(-1 == lookup_ain_by_key("U14_"));
ASSRT(-1 == lookup_ain_by_key("U14_1111"));
printf("Testing lookup_ain_by_name\n");
ASSRT(-1 == lookup_ain_by_name("GND"));
ASSRT(0 == lookup_ain_by_name("LRADC"));
ASSRT(-1 == lookup_ain_by_name("NOTFOUND"));
ASSRT(-1 == lookup_ain_by_name("LR"));
ASSRT(-1 == lookup_ain_by_name("LRADCCC"));
char k[9];
printf("Testing copy_key_by_key\n");
ASSRT(1 == copy_key_by_key("U13_1", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U13_1", k));
ASSRT(1 == copy_key_by_key("U14_40", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U14_40", k));
ASSRT(0 == copy_key_by_key("NOTFOUND", k));
ASSRT(0 == copy_key_by_key("U14_", k));
ASSRT(0 == copy_key_by_key("U14_4000", k));
printf("Testing copy_pwm_key_by_key\n");
ASSRT(1 == copy_pwm_key_by_key("U13_18", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U13_18", k));
ASSRT(0 == copy_pwm_key_by_key("U13_1", k));
ASSRT(0 == copy_pwm_key_by_key("U14_40", k));
ASSRT(0 == copy_pwm_key_by_key("NOTFOUND", k));
ASSRT(0 == copy_pwm_key_by_key("U13_", k));
ASSRT(0 == copy_pwm_key_by_key("U13_1888", k));
printf("Testing get_key_by_name\n");
ASSRT(1 == get_key_by_name("GND", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U13_1", k));
ASSRT(1 == get_key_by_name("CSID7", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U14_38", k));
ASSRT(0 == get_key_by_name("NOTFOUND", k));
ASSRT(0 == get_key_by_name("CSID", k));
ASSRT(0 == get_key_by_name("CSID777", k));
printf("Testing get_pwm_key_by_name\n");
ASSRT(1 == get_pwm_key_by_name("PWM0", k)); BUF2SMALL(k); ASSRT(0 == strcmp("U13_18", k));
ASSRT(0 == get_pwm_key_by_name("NOTFOUND", k));
ASSRT(0 == get_pwm_key_by_name("PWM", k));
ASSRT(0 == get_pwm_key_by_name("PWM000", k));
char fp[80];
printf("Testing build_path\n");
ASSRT(1 == build_path("/home", "ch", fp, sizeof(fp))); ASSRT(0 == strcmp("/home/chip", fp));
ASSRT(1 == build_path("/home", "chip", fp, sizeof(fp))); ASSRT(0 == strcmp("/home/chip", fp));
ASSRT(0 == build_path("/home", "NOTFOUND", fp, sizeof(fp)));
ASSRT(0 == build_path("/home", "chipp", fp, sizeof(fp)));
ASSRT(0 == build_path("/home", "ip", fp, sizeof(fp)));
ASSRT(0 == build_path("/NOTFOUND", "ch", fp, sizeof(fp)));
printf("Testing get_spi_bus_path_number\n");
ASSRT(2 == get_spi_bus_path_number(0)); /* doesn't really work on CHIP */
ASSRT(2 == get_spi_bus_path_number(1)); /* doesn't really work on CHIP */
int value = input;

View File

@ -32,13 +32,13 @@ SOFTWARE.
#include "Python.h"
#include "constants.h"
#include "common.h"
#include "c_softpwm.h"
#include "c_softpwm.h"
// python function cleanup()
static PyObject *py_cleanup(PyObject *self, PyObject *args)
{
// unexport the PWM
softpwm_cleanup();
softpwm_cleanup();
Py_RETURN_NONE;
}
@ -47,7 +47,7 @@ static PyObject *py_cleanup(PyObject *self, PyObject *args)
static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwargs)
{
char key[8];
char *channel;
char *channel = NULL;
float frequency = 2000.0;
float duty_cycle = 0.0;
int polarity = 0;
@ -56,6 +56,7 @@ static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwar
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ffi", kwlist, &channel, &duty_cycle, &frequency, &polarity)) {
return NULL;
}
ASSRT(channel != NULL);
if (!get_key(channel, key)) {
PyErr_SetString(PyExc_ValueError, "Invalid SOFTPWM key or name.");
@ -79,7 +80,7 @@ static PyObject *py_start_channel(PyObject *self, PyObject *args, PyObject *kwar
return NULL;
}
if (!softpwm_start(key, duty_cycle, frequency, polarity))
if (!softpwm_start(key, duty_cycle, frequency, polarity))
return NULL;
Py_RETURN_NONE;
@ -94,12 +95,12 @@ static PyObject *py_stop_channel(PyObject *self, PyObject *args, PyObject *kwarg
if (!PyArg_ParseTuple(args, "s", &channel))
return NULL;
if (!get_key(channel, key)) {
if (!get_key(channel, key)) {
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
return NULL;
}
softpwm_disable(key);
softpwm_disable(key);
Py_RETURN_NONE;
}
@ -121,12 +122,12 @@ static PyObject *py_set_duty_cycle(PyObject *self, PyObject *args, PyObject *kwa
return NULL;
}
if (!get_key(channel, key)) {
if (!get_key(channel, key)) {
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
return NULL;
}
if (softpwm_set_duty_cycle(key, duty_cycle) == -1) {
if (softpwm_set_duty_cycle(key, duty_cycle) == -1) {
PyErr_SetString(PyExc_RuntimeError, "You must start() the PWM channel first");
return NULL;
}
@ -145,13 +146,13 @@ static PyObject *py_set_frequency(PyObject *self, PyObject *args, PyObject *kwar
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|f", kwlist, &channel, &frequency))
return NULL;
if ((frequency <= 0.0) || (frequency > 10000.0))
if ((frequency <= 0.0) || (frequency > 10000.0))
{
PyErr_SetString(PyExc_ValueError, "frequency must be greater than 0.0 and less than 10000.0");
PyErr_SetString(PyExc_ValueError, "frequency must be greater than 0.0 and less than 10000.0");
return NULL;
}
if (!get_key(channel, key)) {
if (!get_key(channel, key)) {
PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name.");
return NULL;
}