From 5ee8b13dc75d2a0527c1c3d8315e174fac29d2c5 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Sun, 17 Jun 2012 17:14:21 +0200 Subject: move sources back to top-level src directory --- src/Makefile | 16 ++ src/c/Makefile | 16 -- src/c/k8055.c | 462 --------------------------------------------------------- src/c/k8055.h | 147 ------------------ src/k8055.c | 462 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/k8055.h | 147 ++++++++++++++++++ 6 files changed, 625 insertions(+), 625 deletions(-) create mode 100644 src/Makefile delete mode 100644 src/c/Makefile delete mode 100644 src/c/k8055.c delete mode 100644 src/c/k8055.h create mode 100644 src/k8055.c create mode 100644 src/k8055.h diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..0e1d62b --- /dev/null +++ b/src/Makefile @@ -0,0 +1,16 @@ +C = gcc +# libusb.h location +INCDIR = /usr/include/libusb-1.0 +CFLAGS = -std=c99 -O2 -Wall + +all: libk8055.so + +libk8055.so: k8055.o + $(C) -shared -o libk8055.so k8055.o -lusb-1.0 + +k8055.o: k8055.c + $(C) $(CFLAGS) -fPIC -I $(INCDIR) -c k8055.c -o k8055.o + +clean: + rm -rf *.o + rm -rf *.so diff --git a/src/c/Makefile b/src/c/Makefile deleted file mode 100644 index 0e1d62b..0000000 --- a/src/c/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -C = gcc -# libusb.h location -INCDIR = /usr/include/libusb-1.0 -CFLAGS = -std=c99 -O2 -Wall - -all: libk8055.so - -libk8055.so: k8055.o - $(C) -shared -o libk8055.so k8055.o -lusb-1.0 - -k8055.o: k8055.c - $(C) $(CFLAGS) -fPIC -I $(INCDIR) -c k8055.c -o k8055.o - -clean: - rm -rf *.o - rm -rf *.so diff --git a/src/c/k8055.c b/src/c/k8055.c deleted file mode 100644 index 5b8f806..0000000 --- a/src/c/k8055.c +++ /dev/null @@ -1,462 +0,0 @@ -/* k8055 driver for libusb-1.0 - - Copyright (c) 2012 by Jakob Odersky - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - Thanks to the following people who wrote the original version of `libk8055' - (http://libk8055.sourceforge.net/): - - 2005 by Sven Lindberg - - 2007 by Pjetur G. Hjaltason - Commenting, general rearrangement of code, bugfixes, - python interface with swig and simple k8055 python class - - The comments explaining the data packets and debounce time conversion are from them. - - Input packet format - - +---+---+---+---+---+---+---+---+ - |DIn|Sta|A1 |A2 | C1 | C2 | - +---+---+---+---+---+---+---+---+ - DIn = Digital input in high nibble, except for input 3 in 0x01 - Sta = Status, Board number + 1 - A1 = Analog input 1, 0-255 - A2 = Analog input 2, 0-255 - C1 = Counter 1, 16 bits (lsb) - C2 = Counter 2, 16 bits (lsb) - - Output packet format - - - +---+---+---+---+---+---+---+---+ - |CMD|DIG|An1|An2|Rs1|Rs2|Dbv|Dbv| - +---+---+---+---+---+---+---+---+ - CMD = Command - DIG = Digital output bitmask - An1 = Analog output 1 value, 0-255 - An2 = Analog output 2 value, 0-255 - Rs1 = Reset counter 1, command 3 - Rs2 = Reset counter 3, command 4 - Dbv = Debounce value for counter 1 and 2, command 1 and 2 - - Or split by commands - - Cmd 0, Reset ?? - Cmd 1, Set debounce Counter 1 - +---+---+---+---+---+---+---+---+ - |CMD| | | | | |Dbv| | - +---+---+---+---+---+---+---+---+ - Cmd 2, Set debounce Counter 2 - +---+---+---+---+---+---+---+---+ - |CMD| | | | | | |Dbv| - +---+---+---+---+---+---+---+---+ - Cmd 3, Reset counter 1 - +---+---+---+---+---+---+---+---+ - | 3 | | | | 00| | | | - +---+---+---+---+---+---+---+---+ - Cmd 4, Reset counter 2 - +---+---+---+---+---+---+---+---+ - | 4 | | | | | 00| | | - +---+---+---+---+---+---+---+---+ - cmd 5, Set analog/digital - +---+---+---+---+---+---+---+---+ - | 5 |DIG|An1|An2| | | | | - +---+---+---+---+---+---+---+---+ - - */ - -#define PACKET_LENGTH 8 -#define K8055_PRODUCT_ID 0x5500 -#define VELLEMAN_VENDOR_ID 0x10cf -#define K8055_MAX_DEVICES 4 - -#define USB_OUT_EP 0x01 /** USB output endpoint */ -#define USB_IN_EP 0x81 /* USB Input endpoint */ -#define USB_TIMEOUT 20 /* [ms] */ - -#define WRITE_TRIES 3 /* maximum number of write tries */ -#define READ_TRIES 3/* maximum number of read tries */ - -#define IN_DIGITAL_OFFSET 0 -#define IN_ANALOG_0_OFFSET 2 -#define IN_ANALOG_1_OFFSET 3 -#define IN_COUNTER_0_OFFSET 4 -#define IN_COUNTER_1_OFFSET 6 - -#define OUT_CMD_OFFEST 0 -#define OUT_DIGITAL_OFFSET 1 -#define OUT_ANALOG_0_OFFSET 2 -#define OUT_ANALOG_1_OFFSET 3 -#define OUT_COUNTER_0_OFFSET 4 -#define OUT_COUNTER_1_OFFSET 5 -#define OUT_COUNTER_0_DEBOUNCE_OFFSET 6 -#define OUT_COUNTER_1_DEBOUNCE_OFFSET 7 - -#define CMD_RESET 0 -#define CMD_SET_DEBOUNCE_1 1 -#define CMD_SET_DEBOUNCE_2 2 -#define CMD_RESET_COUNTER_0 3 -#define CMD_RESET_COUNTER_1 4 -#define CMD_SET_ANALOG_DIGITAL 5 - -#include -#include -#include -#include -#include -#include "k8055.h" - -/** Represents a Vellemean K8055 USB board. */ -struct k8055_device { - - /** Data last read from device, used by k8055_read_data(). */ - unsigned char data_in[PACKET_LENGTH]; - - /** Data to be sent to the device, used by k8055_write_data(). */ - unsigned char data_out[PACKET_LENGTH]; - - unsigned char current_out[PACKET_LENGTH]; - - /** Underlying libusb handle to device. NULL if the device is not open. */ - libusb_device_handle *device_handle; -}; - -/** Libusb context. */ -static libusb_context* context = NULL; -static int k8055_open_devices = 0; -static int DEBUG = 0; - -/** Prints the given message to standard output if debugging is enabled. */ -static void print_error(const char * str) { - if (DEBUG) { - printf("%s", str); - } -} - -int k8055_open_device(int port, k8055_device** device) { - if (port < 0 || K8055_MAX_DEVICES <= port) { - print_error("invalid port number, port p should be 0<=p<=3"); - return K8055_ERROR_INDEX; - } - - if (k8055_open_devices == 0) { /* no devices are open */ - int r = libusb_init(&context); /* initialize a new context */ - if (r < 0) { - print_error("could not initialize libusb"); - return K8055_ERROR_INIT_LIBUSB; /* return error code in case of error */ - } - } - - libusb_device **connected_devices = NULL; - - ssize_t size = libusb_get_device_list(context, &connected_devices); /* get all devices on system */ - if (size <= 0) { - print_error("no usb devices found on system"); - return K8055_ERROR_NO_DEVICES; - } - - libusb_device *k8055 = NULL; /* device on port */ - - for (size_t i = 0; i < size; ++i) { /* look for the device at given port */ - struct libusb_device_descriptor descriptor; - libusb_get_device_descriptor(connected_devices[i], &descriptor); - if (descriptor.idVendor == VELLEMAN_VENDOR_ID - && descriptor.idProduct == (K8055_PRODUCT_ID + port)) - k8055 = connected_devices[i]; - } - if (k8055 == NULL) { - print_error("velleman k8055 not found at port"); - return K8055_ERROR_NO_K8055; - } - - libusb_device_handle *handle = NULL; /* handle to device on port */ - - int r = libusb_open(k8055, &handle); /* open device */ - libusb_free_device_list(connected_devices, 1); /* we got the handle, free references to other devices */ - - if (r == LIBUSB_ERROR_ACCESS) { - print_error( - "could not open device, you don't have the required permissions"); - return K8055_ERROR_ACCESS; - } else if (r != 0) { - print_error("could not open device"); - return K8055_ERROR_OPEN; - } - - if (libusb_kernel_driver_active(handle, 0) == 1) { /* find out if kernel driver is attached */ - if (libusb_detach_kernel_driver(handle, 0) != 0) { /* detach it */ - print_error("could not detach kernel driver"); - return K8055_ERROR_OPEN; - } - } - - r = libusb_claim_interface(handle, 0); /* claim interface 0 (the first) of device */ - if (r != 0) { - print_error("could not claim interface"); - return K8055_ERROR_OPEN; - } - - k8055_device* _device = NULL; - _device = malloc(sizeof(k8055_device)); - if (_device == NULL) { - print_error("could not allocate memory for device"); - return K8055_ERROR_MEM; - } - - _device->device_handle = handle; /* add usb handle */ - - for (int i = 0; i < PACKET_LENGTH; ++i) { /* initialize command data */ - _device->data_out[i]=0; - _device->current_out[i]=0; - } - - k8055_set_all_digital(_device, 0); - k8055_set_all_analog(_device, 0, 0); - k8055_set_debounce_time(_device, 0, 2); - k8055_set_debounce_time(_device, 1, 2); - k8055_reset_counter(_device, 1); - k8055_reset_counter(_device, 1); - - *device = _device; - k8055_open_devices += 1; - - return 0; -} - -void k8055_close_device(k8055_device* device) { - libusb_release_interface(device->device_handle, 0); - libusb_close(device->device_handle); - device->device_handle = NULL; - free(device); - device = NULL; - - k8055_open_devices -= 1; - - if (k8055_open_devices <= 0) - libusb_exit(context); -} - -/** Writes the actual data contained in the device's data_out field to the usb endpoint. - * @return K8055_ERROR_CLOSED if the board is not open - * @return K8055_ERROR_WRITE if another error occurred during the write process */ -static int k8055_write_data(k8055_device* device) { - int write_status = 0; - - if (device->device_handle == NULL) { - print_error("unable to write data, device not open"); - return K8055_ERROR_CLOSED; - } - - int transferred = 0; - for (int i = 0; i < WRITE_TRIES; ++i) { /* number of tries on failure */ - write_status = libusb_interrupt_transfer(device->device_handle, - USB_OUT_EP, (unsigned char *) device->data_out, PACKET_LENGTH, - &transferred, USB_TIMEOUT); - if (write_status == 0 && transferred == PACKET_LENGTH) - break; - } - if (write_status != 0 || transferred != PACKET_LENGTH) { - print_error("could not write packet"); - return K8055_ERROR_WRITE; - } - - /* if there was no error up to this point, assume that data_out now reflects the devices output status */ - for (int i = 0; i < PACKET_LENGTH; ++i) { - device->current_out[i]=device->data_out[i]; - } - - return 0; -} - -/** Reads data from the usb endpoint into the device's data_in field. - * @return K8055_ERROR_CLOSED if the board is not open - * @return K8055_ERROR_READ if another error occurred during the read process */ -static int k8055_read_data(k8055_device* device, int cycles) { - int read_status = 0; - - if (device->device_handle == NULL) { - print_error("unable to read data, device not open"); - return K8055_ERROR_CLOSED; - } - - int transferred = 0; - for (int i = 0; i < READ_TRIES; ++i) { /* number of tries on failure */ - for (int j = 0; j < cycles; ++j) { /* read at least twice to get fresh data, (i.e. circumvent some kind of buffer) */ - read_status = libusb_interrupt_transfer(device->device_handle, - USB_IN_EP, (unsigned char *) device->data_in, PACKET_LENGTH, - &transferred, USB_TIMEOUT); - } - if (read_status == 0 && transferred == PACKET_LENGTH) - break; - } - if (read_status != 0 || transferred != PACKET_LENGTH) { - print_error("could not read packet"); - return K8055_ERROR_READ; - } - return 0; -} - -static unsigned char k8055_ms_to_char(int t) { - /* the velleman k8055 use a exponetial formula to split up the - DebounceTime 0-7450 over value 1-255. I've tested every value and - found that the formula dbt=0,338*value^1,8017 is closest to - vellemans dll. By testing and measuring times on the other hand I - found the formula dbt=0,115*x^2 quite near the actual values, a - little below at really low values and a little above at really - high values. But the time set with this formula is within +-4% */ - - int c = t; - - if (c > 7450) - c = 7450; - c = sqrt(c / 0.115); - if (c > ((int) c + 0.49999999)) /* simple round() function) */ - c += 1; - return (unsigned char) c; -} -static int k8055_char_to_ms(unsigned char c) { - double t = 0.115 * c * c; - if (t > ((int) t + 0.49999999)) /* simple round() function) */ - t += 1; - return t; -} - -int k8055_set_all_digital(k8055_device* device, int bitmask) { - device->data_out[OUT_DIGITAL_OFFSET] = bitmask; - device->data_out[OUT_CMD_OFFEST] = CMD_SET_ANALOG_DIGITAL; - return k8055_write_data(device); -} - -int k8055_set_digital(k8055_device* device, int channel, bool value) { - - unsigned char data = device->data_out[OUT_DIGITAL_OFFSET]; - if (value == false) /* off */ - data = data & ~(1 << channel); - else - /* on */ - data = data | (1 << channel); - - device->data_out[OUT_DIGITAL_OFFSET] = data; - device->data_out[OUT_CMD_OFFEST] = CMD_SET_ANALOG_DIGITAL; - return k8055_write_data(device); -} - -int k8055_set_all_analog(k8055_device* device, int analog0, int analog1) { - device->data_out[OUT_ANALOG_0_OFFSET] = analog0; - device->data_out[OUT_ANALOG_1_OFFSET] = analog1; - device->data_out[OUT_CMD_OFFEST] = CMD_SET_ANALOG_DIGITAL; - return k8055_write_data(device); -} - -int k8055_set_analog(k8055_device* device, int channel, int value) { - - if (channel == 0) { - device->data_out[OUT_ANALOG_0_OFFSET] = value; - } else if (channel == 1) { - device->data_out[OUT_ANALOG_1_OFFSET] = value; - } else { - print_error("can't write to unknown analog port"); - return K8055_ERROR_INDEX; - } - - device->data_out[OUT_CMD_OFFEST] = CMD_SET_ANALOG_DIGITAL; - return k8055_write_data(device); -} - -int k8055_reset_counter(k8055_device* device, int counter) { - - if (counter == 0) { - device->data_out[OUT_COUNTER_0_OFFSET] = 0; - device->data_out[OUT_CMD_OFFEST] = CMD_RESET_COUNTER_0; - } else if (counter == 1) { - device->data_out[OUT_COUNTER_1_OFFSET] = 0; - device->data_out[OUT_CMD_OFFEST] = CMD_RESET_COUNTER_1; - } else { - print_error("can't reset unknown counter"); - return K8055_ERROR_INDEX; - } - - return k8055_write_data(device); -} - -int k8055_set_debounce_time(k8055_device* device, int counter, int debounce) { - - if (counter == 0) { - device->data_out[OUT_COUNTER_0_DEBOUNCE_OFFSET] = k8055_ms_to_char( - debounce); - device->data_out[OUT_CMD_OFFEST] = CMD_SET_DEBOUNCE_1; - } else if (counter == 1) { - device->data_out[OUT_COUNTER_1_DEBOUNCE_OFFSET] = k8055_ms_to_char( - debounce); - device->data_out[OUT_CMD_OFFEST] = CMD_SET_DEBOUNCE_2; - } else { - print_error("can't set debounce time for unknown counter"); - return K8055_ERROR_INDEX; - } - - return k8055_write_data(device); -} - -int k8055_get_all_input(k8055_device* device, int *bitmask, int *analog0, - int *analog1, int *counter0, int *counter1, bool quick) { - int cycles = 2; - if (quick) - cycles = 1; - int r = k8055_read_data(device, cycles); - if (r != 0) - return r; - - if (bitmask != NULL) - *bitmask = (((device->data_in[IN_DIGITAL_OFFSET] >> 4) & 0x03) | /* Input 1 and 2 */ - ((device->data_in[IN_DIGITAL_OFFSET] << 2) & 0x04) | /* Input 3 */ - ((device->data_in[IN_DIGITAL_OFFSET] >> 3) & 0x18)); /* Input 4 and 5 */ - if (analog0 != NULL) - *analog0 = device->data_in[IN_ANALOG_0_OFFSET]; - if (analog1 != NULL) - *analog1 = device->data_in[IN_ANALOG_1_OFFSET]; - if (counter0 != NULL) - *counter0 = (int) device->data_in[IN_COUNTER_0_OFFSET + 1] << 8 - | device->data_in[IN_COUNTER_0_OFFSET]; - if (counter1 != NULL) - *counter1 = (int) device->data_in[IN_COUNTER_1_OFFSET + 1] << 8 - | device->data_in[IN_COUNTER_1_OFFSET]; - return 0; -} - -void k8055_get_all_output(k8055_device* device, int* bitmask, int *analog0, - int *analog1, int *debounce0, int *debounce1) { - - if (bitmask != NULL) - *bitmask = device->current_out[OUT_DIGITAL_OFFSET]; - if (analog0 != NULL) - *analog0 = device->current_out[OUT_ANALOG_0_OFFSET]; - if (analog1 != NULL) - *analog1 = device->current_out[OUT_ANALOG_1_OFFSET]; - if (debounce0 != NULL) - *debounce0 = k8055_char_to_ms(device->current_out[OUT_COUNTER_0_DEBOUNCE_OFFSET]); - if (debounce1 != NULL) - *debounce1 = k8055_char_to_ms(device->current_out[OUT_COUNTER_1_DEBOUNCE_OFFSET]); -} diff --git a/src/c/k8055.h b/src/c/k8055.h deleted file mode 100644 index 3b42a1c..0000000 --- a/src/c/k8055.h +++ /dev/null @@ -1,147 +0,0 @@ -/* k8055 driver for libusb-1.0 - - Copyright (c) 2012 by Jakob Odersky - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef K8055_H_ -#define K8055_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct k8055_device k8055_device; - -enum k8055_error_code { - K8055_SUCCESS = 0, K8055_ERROR = -1, K8055_ERROR_INIT_LIBUSB = -2, /* error during libusb initialization */ - K8055_ERROR_NO_DEVICES = -3, /* no usb devices found on host machine */ - K8055_ERROR_NO_K8055 = -4, /* Velleman k8055 cannot be found (on given port) */ - K8055_ERROR_ACCESS = -6, /* access denied (insufficient permissions) */ - K8055_ERROR_OPEN = -7, /* error opening device handle (also applies for claiming and detaching kernel driver) */ - K8055_ERROR_CLOSED = -8, /* device is already closed */ - K8055_ERROR_WRITE = -9, /* write error */ - K8055_ERROR_READ = -10, /* read error */ - K8055_ERROR_INDEX = -11, /* invalid argument (i.e. trying to access analog channel >= 2) */ - K8055_ERROR_MEM = -12 /* memory allocation error */ -}; - -/**Opens a K8055 device on the given port (i.e. address). - * @return 0 on success - * @return K8055_ERROR_INDEX if port is an invalid index - * @return K8055_ERROR_INIT_LIBUSB on libusb initialization error - * @return K8055_ERROR_NO_DEVICES if no usb devices are found on host system - * @return K8055_ERROR_NO_K8055 if no K8055 board is found at the given port - * @return K8055_ERROR_ACCESS if permission is denied to access a usb port - * @return K8055_ERROR_OPEN if another error occured preventing the board to be opened */ -int k8055_open_device(int port, k8055_device** device); - -/** Closes the given device. */ -void k8055_close_device(k8055_device* device); - -/**Sets all digital ouputs according to the given bitmask. - * @param device k8055 board - * @param bitmask '1' for 'on', '0' for 'off' - * @return K8055_ERROR_CLOSED if the given device is not open - * @return K8055_ERROR_WRITE if another error occurred during the write process */ -int k8055_set_all_digital(k8055_device* device, int bitmask); - -/**Sets a digital output at given channel. - * @param device k8055 board - * @param channel channel of port - * @param value output status: 'true' for on, 'false' for off - * @return K8055_ERROR_CLOSED if the given device is not open - * @return K8055_ERROR_WRITE if another error occurred during the write process */ -int k8055_set_digital(k8055_device* device, int channel, bool value); - -/**Sets the values of both analog outputs. - * @param device k8055 board - * @param analog0 value of first analog output - * @param analog1 value of second analog output - * @return K8055_ERROR_CLOSED if the given device is not open - * @return K8055_ERROR_WRITE if another error occurred during the write process */ -int k8055_set_all_analog(k8055_device* device, int analog0, int analog1); - -/**Sets the value for an analog output at a given channel. - * @param device k8055 board - * @param channel channel of analog output (zero indexed) - * @param value value of analog output [0-255] - * @return K8055_ERROR_INDEX if channel is an invalid index - * @return K8055_ERROR_CLOSED if the given device is not open - * @return K8055_ERROR_WRITE if another error occurred during the write process */ -int k8055_set_analog(k8055_device* device, int channel, int value); - -/**Resets a hardware integrated counter of the Velleman K8055 board. - * @param device k8055 board - * @param counter index of counter (zero indexed) - * @return K8055_ERROR_INDEX if counter is an invalid index - * @return K8055_ERROR_CLOSED if the given device is not open - * @return K8055_ERROR_WRITE if another error occurred during the write process */ -int k8055_reset_counter(k8055_device* device, int counter); - -/**Sets the debounce time of a hardware integrated counter of the Velleman K8055 board. - * @param device k8055 board - * @param counter index of counter (zero indexed) - * @param debounce debounce value - * @return K8055_ERROR_INDEX if counter is an invalid index - * @return K8055_ERROR_CLOSED if the given device is not open - * @return K8055_ERROR_WRITE if another error occurred during the write process*/ -int k8055_set_debounce_time(k8055_device* device, int counter, int debounce); - -/**Reads all current data of a given board into the passed parameters. NULL is a valid parameter. - * Unless quick is set, data is read twice from the board to circumvent some kind of buffer and get current data. - * @param device k8055 board - * @param digitalBitmask bitmask value of digital inputs (there are 5 digital inputs) - * @param analog0 value of first analog input - * @param analog1 value of second analog input - * @param counter0 value of first counter - * @param counter1 value of second counter - * @param quick if set, read data only once - * @return 0 on success - * @return K8055_ERROR_CLOSED if the given device is not open - * @return K8055_ERROR_READ if another error occurred during the read process */ -int k8055_get_all_input(k8055_device* device, int *digitalBitmask, int *analog0, - int *analog1, int *counter0, int *counter1, bool quick); - -/**Gets a given board's current output status. NULL is a valid parameter. - * Note: as the K8055's firmware does not provide any method for querying the board's output status, - * this library only tracks the board's status by recording any successfull data writes. - * Hence no guarantee can be given on the validity of the output status. - * @param device k8055 board - * @param digitalBitmask bitmask value of digital outputs (there are 8 digital outputs) - * @param analog0 value of first analog output - * @param analog1 value of second analog output - * @param debounce0 value of first counter's debounce time [ms] - * @param debounce1 value of second counter's debounce time [ms] */ -void k8055_get_all_output(k8055_device* device, int* digitalBitmask, int *analog0, - int *analog1, int *debounce0, int *debounce1); - -#ifdef __cplusplus -} -#endif - -#endif /* K8055_H_ */ diff --git a/src/k8055.c b/src/k8055.c new file mode 100644 index 0000000..5b8f806 --- /dev/null +++ b/src/k8055.c @@ -0,0 +1,462 @@ +/* k8055 driver for libusb-1.0 + + Copyright (c) 2012 by Jakob Odersky + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Thanks to the following people who wrote the original version of `libk8055' + (http://libk8055.sourceforge.net/): + + 2005 by Sven Lindberg + + 2007 by Pjetur G. Hjaltason + Commenting, general rearrangement of code, bugfixes, + python interface with swig and simple k8055 python class + + The comments explaining the data packets and debounce time conversion are from them. + + Input packet format + + +---+---+---+---+---+---+---+---+ + |DIn|Sta|A1 |A2 | C1 | C2 | + +---+---+---+---+---+---+---+---+ + DIn = Digital input in high nibble, except for input 3 in 0x01 + Sta = Status, Board number + 1 + A1 = Analog input 1, 0-255 + A2 = Analog input 2, 0-255 + C1 = Counter 1, 16 bits (lsb) + C2 = Counter 2, 16 bits (lsb) + + Output packet format + + + +---+---+---+---+---+---+---+---+ + |CMD|DIG|An1|An2|Rs1|Rs2|Dbv|Dbv| + +---+---+---+---+---+---+---+---+ + CMD = Command + DIG = Digital output bitmask + An1 = Analog output 1 value, 0-255 + An2 = Analog output 2 value, 0-255 + Rs1 = Reset counter 1, command 3 + Rs2 = Reset counter 3, command 4 + Dbv = Debounce value for counter 1 and 2, command 1 and 2 + + Or split by commands + + Cmd 0, Reset ?? + Cmd 1, Set debounce Counter 1 + +---+---+---+---+---+---+---+---+ + |CMD| | | | | |Dbv| | + +---+---+---+---+---+---+---+---+ + Cmd 2, Set debounce Counter 2 + +---+---+---+---+---+---+---+---+ + |CMD| | | | | | |Dbv| + +---+---+---+---+---+---+---+---+ + Cmd 3, Reset counter 1 + +---+---+---+---+---+---+---+---+ + | 3 | | | | 00| | | | + +---+---+---+---+---+---+---+---+ + Cmd 4, Reset counter 2 + +---+---+---+---+---+---+---+---+ + | 4 | | | | | 00| | | + +---+---+---+---+---+---+---+---+ + cmd 5, Set analog/digital + +---+---+---+---+---+---+---+---+ + | 5 |DIG|An1|An2| | | | | + +---+---+---+---+---+---+---+---+ + + */ + +#define PACKET_LENGTH 8 +#define K8055_PRODUCT_ID 0x5500 +#define VELLEMAN_VENDOR_ID 0x10cf +#define K8055_MAX_DEVICES 4 + +#define USB_OUT_EP 0x01 /** USB output endpoint */ +#define USB_IN_EP 0x81 /* USB Input endpoint */ +#define USB_TIMEOUT 20 /* [ms] */ + +#define WRITE_TRIES 3 /* maximum number of write tries */ +#define READ_TRIES 3/* maximum number of read tries */ + +#define IN_DIGITAL_OFFSET 0 +#define IN_ANALOG_0_OFFSET 2 +#define IN_ANALOG_1_OFFSET 3 +#define IN_COUNTER_0_OFFSET 4 +#define IN_COUNTER_1_OFFSET 6 + +#define OUT_CMD_OFFEST 0 +#define OUT_DIGITAL_OFFSET 1 +#define OUT_ANALOG_0_OFFSET 2 +#define OUT_ANALOG_1_OFFSET 3 +#define OUT_COUNTER_0_OFFSET 4 +#define OUT_COUNTER_1_OFFSET 5 +#define OUT_COUNTER_0_DEBOUNCE_OFFSET 6 +#define OUT_COUNTER_1_DEBOUNCE_OFFSET 7 + +#define CMD_RESET 0 +#define CMD_SET_DEBOUNCE_1 1 +#define CMD_SET_DEBOUNCE_2 2 +#define CMD_RESET_COUNTER_0 3 +#define CMD_RESET_COUNTER_1 4 +#define CMD_SET_ANALOG_DIGITAL 5 + +#include +#include +#include +#include +#include +#include "k8055.h" + +/** Represents a Vellemean K8055 USB board. */ +struct k8055_device { + + /** Data last read from device, used by k8055_read_data(). */ + unsigned char data_in[PACKET_LENGTH]; + + /** Data to be sent to the device, used by k8055_write_data(). */ + unsigned char data_out[PACKET_LENGTH]; + + unsigned char current_out[PACKET_LENGTH]; + + /** Underlying libusb handle to device. NULL if the device is not open. */ + libusb_device_handle *device_handle; +}; + +/** Libusb context. */ +static libusb_context* context = NULL; +static int k8055_open_devices = 0; +static int DEBUG = 0; + +/** Prints the given message to standard output if debugging is enabled. */ +static void print_error(const char * str) { + if (DEBUG) { + printf("%s", str); + } +} + +int k8055_open_device(int port, k8055_device** device) { + if (port < 0 || K8055_MAX_DEVICES <= port) { + print_error("invalid port number, port p should be 0<=p<=3"); + return K8055_ERROR_INDEX; + } + + if (k8055_open_devices == 0) { /* no devices are open */ + int r = libusb_init(&context); /* initialize a new context */ + if (r < 0) { + print_error("could not initialize libusb"); + return K8055_ERROR_INIT_LIBUSB; /* return error code in case of error */ + } + } + + libusb_device **connected_devices = NULL; + + ssize_t size = libusb_get_device_list(context, &connected_devices); /* get all devices on system */ + if (size <= 0) { + print_error("no usb devices found on system"); + return K8055_ERROR_NO_DEVICES; + } + + libusb_device *k8055 = NULL; /* device on port */ + + for (size_t i = 0; i < size; ++i) { /* look for the device at given port */ + struct libusb_device_descriptor descriptor; + libusb_get_device_descriptor(connected_devices[i], &descriptor); + if (descriptor.idVendor == VELLEMAN_VENDOR_ID + && descriptor.idProduct == (K8055_PRODUCT_ID + port)) + k8055 = connected_devices[i]; + } + if (k8055 == NULL) { + print_error("velleman k8055 not found at port"); + return K8055_ERROR_NO_K8055; + } + + libusb_device_handle *handle = NULL; /* handle to device on port */ + + int r = libusb_open(k8055, &handle); /* open device */ + libusb_free_device_list(connected_devices, 1); /* we got the handle, free references to other devices */ + + if (r == LIBUSB_ERROR_ACCESS) { + print_error( + "could not open device, you don't have the required permissions"); + return K8055_ERROR_ACCESS; + } else if (r != 0) { + print_error("could not open device"); + return K8055_ERROR_OPEN; + } + + if (libusb_kernel_driver_active(handle, 0) == 1) { /* find out if kernel driver is attached */ + if (libusb_detach_kernel_driver(handle, 0) != 0) { /* detach it */ + print_error("could not detach kernel driver"); + return K8055_ERROR_OPEN; + } + } + + r = libusb_claim_interface(handle, 0); /* claim interface 0 (the first) of device */ + if (r != 0) { + print_error("could not claim interface"); + return K8055_ERROR_OPEN; + } + + k8055_device* _device = NULL; + _device = malloc(sizeof(k8055_device)); + if (_device == NULL) { + print_error("could not allocate memory for device"); + return K8055_ERROR_MEM; + } + + _device->device_handle = handle; /* add usb handle */ + + for (int i = 0; i < PACKET_LENGTH; ++i) { /* initialize command data */ + _device->data_out[i]=0; + _device->current_out[i]=0; + } + + k8055_set_all_digital(_device, 0); + k8055_set_all_analog(_device, 0, 0); + k8055_set_debounce_time(_device, 0, 2); + k8055_set_debounce_time(_device, 1, 2); + k8055_reset_counter(_device, 1); + k8055_reset_counter(_device, 1); + + *device = _device; + k8055_open_devices += 1; + + return 0; +} + +void k8055_close_device(k8055_device* device) { + libusb_release_interface(device->device_handle, 0); + libusb_close(device->device_handle); + device->device_handle = NULL; + free(device); + device = NULL; + + k8055_open_devices -= 1; + + if (k8055_open_devices <= 0) + libusb_exit(context); +} + +/** Writes the actual data contained in the device's data_out field to the usb endpoint. + * @return K8055_ERROR_CLOSED if the board is not open + * @return K8055_ERROR_WRITE if another error occurred during the write process */ +static int k8055_write_data(k8055_device* device) { + int write_status = 0; + + if (device->device_handle == NULL) { + print_error("unable to write data, device not open"); + return K8055_ERROR_CLOSED; + } + + int transferred = 0; + for (int i = 0; i < WRITE_TRIES; ++i) { /* number of tries on failure */ + write_status = libusb_interrupt_transfer(device->device_handle, + USB_OUT_EP, (unsigned char *) device->data_out, PACKET_LENGTH, + &transferred, USB_TIMEOUT); + if (write_status == 0 && transferred == PACKET_LENGTH) + break; + } + if (write_status != 0 || transferred != PACKET_LENGTH) { + print_error("could not write packet"); + return K8055_ERROR_WRITE; + } + + /* if there was no error up to this point, assume that data_out now reflects the devices output status */ + for (int i = 0; i < PACKET_LENGTH; ++i) { + device->current_out[i]=device->data_out[i]; + } + + return 0; +} + +/** Reads data from the usb endpoint into the device's data_in field. + * @return K8055_ERROR_CLOSED if the board is not open + * @return K8055_ERROR_READ if another error occurred during the read process */ +static int k8055_read_data(k8055_device* device, int cycles) { + int read_status = 0; + + if (device->device_handle == NULL) { + print_error("unable to read data, device not open"); + return K8055_ERROR_CLOSED; + } + + int transferred = 0; + for (int i = 0; i < READ_TRIES; ++i) { /* number of tries on failure */ + for (int j = 0; j < cycles; ++j) { /* read at least twice to get fresh data, (i.e. circumvent some kind of buffer) */ + read_status = libusb_interrupt_transfer(device->device_handle, + USB_IN_EP, (unsigned char *) device->data_in, PACKET_LENGTH, + &transferred, USB_TIMEOUT); + } + if (read_status == 0 && transferred == PACKET_LENGTH) + break; + } + if (read_status != 0 || transferred != PACKET_LENGTH) { + print_error("could not read packet"); + return K8055_ERROR_READ; + } + return 0; +} + +static unsigned char k8055_ms_to_char(int t) { + /* the velleman k8055 use a exponetial formula to split up the + DebounceTime 0-7450 over value 1-255. I've tested every value and + found that the formula dbt=0,338*value^1,8017 is closest to + vellemans dll. By testing and measuring times on the other hand I + found the formula dbt=0,115*x^2 quite near the actual values, a + little below at really low values and a little above at really + high values. But the time set with this formula is within +-4% */ + + int c = t; + + if (c > 7450) + c = 7450; + c = sqrt(c / 0.115); + if (c > ((int) c + 0.49999999)) /* simple round() function) */ + c += 1; + return (unsigned char) c; +} +static int k8055_char_to_ms(unsigned char c) { + double t = 0.115 * c * c; + if (t > ((int) t + 0.49999999)) /* simple round() function) */ + t += 1; + return t; +} + +int k8055_set_all_digital(k8055_device* device, int bitmask) { + device->data_out[OUT_DIGITAL_OFFSET] = bitmask; + device->data_out[OUT_CMD_OFFEST] = CMD_SET_ANALOG_DIGITAL; + return k8055_write_data(device); +} + +int k8055_set_digital(k8055_device* device, int channel, bool value) { + + unsigned char data = device->data_out[OUT_DIGITAL_OFFSET]; + if (value == false) /* off */ + data = data & ~(1 << channel); + else + /* on */ + data = data | (1 << channel); + + device->data_out[OUT_DIGITAL_OFFSET] = data; + device->data_out[OUT_CMD_OFFEST] = CMD_SET_ANALOG_DIGITAL; + return k8055_write_data(device); +} + +int k8055_set_all_analog(k8055_device* device, int analog0, int analog1) { + device->data_out[OUT_ANALOG_0_OFFSET] = analog0; + device->data_out[OUT_ANALOG_1_OFFSET] = analog1; + device->data_out[OUT_CMD_OFFEST] = CMD_SET_ANALOG_DIGITAL; + return k8055_write_data(device); +} + +int k8055_set_analog(k8055_device* device, int channel, int value) { + + if (channel == 0) { + device->data_out[OUT_ANALOG_0_OFFSET] = value; + } else if (channel == 1) { + device->data_out[OUT_ANALOG_1_OFFSET] = value; + } else { + print_error("can't write to unknown analog port"); + return K8055_ERROR_INDEX; + } + + device->data_out[OUT_CMD_OFFEST] = CMD_SET_ANALOG_DIGITAL; + return k8055_write_data(device); +} + +int k8055_reset_counter(k8055_device* device, int counter) { + + if (counter == 0) { + device->data_out[OUT_COUNTER_0_OFFSET] = 0; + device->data_out[OUT_CMD_OFFEST] = CMD_RESET_COUNTER_0; + } else if (counter == 1) { + device->data_out[OUT_COUNTER_1_OFFSET] = 0; + device->data_out[OUT_CMD_OFFEST] = CMD_RESET_COUNTER_1; + } else { + print_error("can't reset unknown counter"); + return K8055_ERROR_INDEX; + } + + return k8055_write_data(device); +} + +int k8055_set_debounce_time(k8055_device* device, int counter, int debounce) { + + if (counter == 0) { + device->data_out[OUT_COUNTER_0_DEBOUNCE_OFFSET] = k8055_ms_to_char( + debounce); + device->data_out[OUT_CMD_OFFEST] = CMD_SET_DEBOUNCE_1; + } else if (counter == 1) { + device->data_out[OUT_COUNTER_1_DEBOUNCE_OFFSET] = k8055_ms_to_char( + debounce); + device->data_out[OUT_CMD_OFFEST] = CMD_SET_DEBOUNCE_2; + } else { + print_error("can't set debounce time for unknown counter"); + return K8055_ERROR_INDEX; + } + + return k8055_write_data(device); +} + +int k8055_get_all_input(k8055_device* device, int *bitmask, int *analog0, + int *analog1, int *counter0, int *counter1, bool quick) { + int cycles = 2; + if (quick) + cycles = 1; + int r = k8055_read_data(device, cycles); + if (r != 0) + return r; + + if (bitmask != NULL) + *bitmask = (((device->data_in[IN_DIGITAL_OFFSET] >> 4) & 0x03) | /* Input 1 and 2 */ + ((device->data_in[IN_DIGITAL_OFFSET] << 2) & 0x04) | /* Input 3 */ + ((device->data_in[IN_DIGITAL_OFFSET] >> 3) & 0x18)); /* Input 4 and 5 */ + if (analog0 != NULL) + *analog0 = device->data_in[IN_ANALOG_0_OFFSET]; + if (analog1 != NULL) + *analog1 = device->data_in[IN_ANALOG_1_OFFSET]; + if (counter0 != NULL) + *counter0 = (int) device->data_in[IN_COUNTER_0_OFFSET + 1] << 8 + | device->data_in[IN_COUNTER_0_OFFSET]; + if (counter1 != NULL) + *counter1 = (int) device->data_in[IN_COUNTER_1_OFFSET + 1] << 8 + | device->data_in[IN_COUNTER_1_OFFSET]; + return 0; +} + +void k8055_get_all_output(k8055_device* device, int* bitmask, int *analog0, + int *analog1, int *debounce0, int *debounce1) { + + if (bitmask != NULL) + *bitmask = device->current_out[OUT_DIGITAL_OFFSET]; + if (analog0 != NULL) + *analog0 = device->current_out[OUT_ANALOG_0_OFFSET]; + if (analog1 != NULL) + *analog1 = device->current_out[OUT_ANALOG_1_OFFSET]; + if (debounce0 != NULL) + *debounce0 = k8055_char_to_ms(device->current_out[OUT_COUNTER_0_DEBOUNCE_OFFSET]); + if (debounce1 != NULL) + *debounce1 = k8055_char_to_ms(device->current_out[OUT_COUNTER_1_DEBOUNCE_OFFSET]); +} diff --git a/src/k8055.h b/src/k8055.h new file mode 100644 index 0000000..3b42a1c --- /dev/null +++ b/src/k8055.h @@ -0,0 +1,147 @@ +/* k8055 driver for libusb-1.0 + + Copyright (c) 2012 by Jakob Odersky + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef K8055_H_ +#define K8055_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct k8055_device k8055_device; + +enum k8055_error_code { + K8055_SUCCESS = 0, K8055_ERROR = -1, K8055_ERROR_INIT_LIBUSB = -2, /* error during libusb initialization */ + K8055_ERROR_NO_DEVICES = -3, /* no usb devices found on host machine */ + K8055_ERROR_NO_K8055 = -4, /* Velleman k8055 cannot be found (on given port) */ + K8055_ERROR_ACCESS = -6, /* access denied (insufficient permissions) */ + K8055_ERROR_OPEN = -7, /* error opening device handle (also applies for claiming and detaching kernel driver) */ + K8055_ERROR_CLOSED = -8, /* device is already closed */ + K8055_ERROR_WRITE = -9, /* write error */ + K8055_ERROR_READ = -10, /* read error */ + K8055_ERROR_INDEX = -11, /* invalid argument (i.e. trying to access analog channel >= 2) */ + K8055_ERROR_MEM = -12 /* memory allocation error */ +}; + +/**Opens a K8055 device on the given port (i.e. address). + * @return 0 on success + * @return K8055_ERROR_INDEX if port is an invalid index + * @return K8055_ERROR_INIT_LIBUSB on libusb initialization error + * @return K8055_ERROR_NO_DEVICES if no usb devices are found on host system + * @return K8055_ERROR_NO_K8055 if no K8055 board is found at the given port + * @return K8055_ERROR_ACCESS if permission is denied to access a usb port + * @return K8055_ERROR_OPEN if another error occured preventing the board to be opened */ +int k8055_open_device(int port, k8055_device** device); + +/** Closes the given device. */ +void k8055_close_device(k8055_device* device); + +/**Sets all digital ouputs according to the given bitmask. + * @param device k8055 board + * @param bitmask '1' for 'on', '0' for 'off' + * @return K8055_ERROR_CLOSED if the given device is not open + * @return K8055_ERROR_WRITE if another error occurred during the write process */ +int k8055_set_all_digital(k8055_device* device, int bitmask); + +/**Sets a digital output at given channel. + * @param device k8055 board + * @param channel channel of port + * @param value output status: 'true' for on, 'false' for off + * @return K8055_ERROR_CLOSED if the given device is not open + * @return K8055_ERROR_WRITE if another error occurred during the write process */ +int k8055_set_digital(k8055_device* device, int channel, bool value); + +/**Sets the values of both analog outputs. + * @param device k8055 board + * @param analog0 value of first analog output + * @param analog1 value of second analog output + * @return K8055_ERROR_CLOSED if the given device is not open + * @return K8055_ERROR_WRITE if another error occurred during the write process */ +int k8055_set_all_analog(k8055_device* device, int analog0, int analog1); + +/**Sets the value for an analog output at a given channel. + * @param device k8055 board + * @param channel channel of analog output (zero indexed) + * @param value value of analog output [0-255] + * @return K8055_ERROR_INDEX if channel is an invalid index + * @return K8055_ERROR_CLOSED if the given device is not open + * @return K8055_ERROR_WRITE if another error occurred during the write process */ +int k8055_set_analog(k8055_device* device, int channel, int value); + +/**Resets a hardware integrated counter of the Velleman K8055 board. + * @param device k8055 board + * @param counter index of counter (zero indexed) + * @return K8055_ERROR_INDEX if counter is an invalid index + * @return K8055_ERROR_CLOSED if the given device is not open + * @return K8055_ERROR_WRITE if another error occurred during the write process */ +int k8055_reset_counter(k8055_device* device, int counter); + +/**Sets the debounce time of a hardware integrated counter of the Velleman K8055 board. + * @param device k8055 board + * @param counter index of counter (zero indexed) + * @param debounce debounce value + * @return K8055_ERROR_INDEX if counter is an invalid index + * @return K8055_ERROR_CLOSED if the given device is not open + * @return K8055_ERROR_WRITE if another error occurred during the write process*/ +int k8055_set_debounce_time(k8055_device* device, int counter, int debounce); + +/**Reads all current data of a given board into the passed parameters. NULL is a valid parameter. + * Unless quick is set, data is read twice from the board to circumvent some kind of buffer and get current data. + * @param device k8055 board + * @param digitalBitmask bitmask value of digital inputs (there are 5 digital inputs) + * @param analog0 value of first analog input + * @param analog1 value of second analog input + * @param counter0 value of first counter + * @param counter1 value of second counter + * @param quick if set, read data only once + * @return 0 on success + * @return K8055_ERROR_CLOSED if the given device is not open + * @return K8055_ERROR_READ if another error occurred during the read process */ +int k8055_get_all_input(k8055_device* device, int *digitalBitmask, int *analog0, + int *analog1, int *counter0, int *counter1, bool quick); + +/**Gets a given board's current output status. NULL is a valid parameter. + * Note: as the K8055's firmware does not provide any method for querying the board's output status, + * this library only tracks the board's status by recording any successfull data writes. + * Hence no guarantee can be given on the validity of the output status. + * @param device k8055 board + * @param digitalBitmask bitmask value of digital outputs (there are 8 digital outputs) + * @param analog0 value of first analog output + * @param analog1 value of second analog output + * @param debounce0 value of first counter's debounce time [ms] + * @param debounce1 value of second counter's debounce time [ms] */ +void k8055_get_all_output(k8055_device* device, int* digitalBitmask, int *analog0, + int *analog1, int *debounce0, int *debounce1); + +#ifdef __cplusplus +} +#endif + +#endif /* K8055_H_ */ -- cgit v1.2.3