From 15708601c84dc12c6cf5409a7b03d2d87806d1a2 Mon Sep 17 00:00:00 2001 From: Jakob Odersky Date: Sun, 17 Jun 2012 15:10:52 +0200 Subject: add ability to get currentr output status --- src/k8055.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- src/k8055.h | 46 +++++++++++++++++++++++++++--------------- 2 files changed, 86 insertions(+), 27 deletions(-) diff --git a/src/k8055.c b/src/k8055.c index 3a3daa8..92ff291 100644 --- a/src/k8055.c +++ b/src/k8055.c @@ -132,12 +132,14 @@ /** Represents a Vellemean K8055 USB board. */ struct k8055_device { - /** Data last read from device, used by read_data(). */ + /** 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; }; @@ -223,8 +225,21 @@ int k8055_open_device(int port, k8055_device** device) { print_error("could not allocate memory for device"); return K8055_ERROR_MEM; } - - (*_device).device_handle = handle; + + _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; @@ -267,13 +282,19 @@ static int k8055_write_data(k8055_device* device) { 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 read_data(k8055_device* device, int cycles) { +static int k8055_read_data(k8055_device* device, int cycles) { int read_status = 0; if (device->device_handle == NULL) { @@ -298,7 +319,7 @@ static int read_data(k8055_device* device, int cycles) { return 0; } -static int k8055_int_to_debounce(int t) { +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 @@ -306,9 +327,18 @@ static int k8055_int_to_debounce(int t) { 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% */ - if (t > 7450) - t = 7450; - t = sqrt(t / 0.115); + + 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; @@ -375,11 +405,11 @@ int k8055_reset_counter(k8055_device* device, int counter) { int k8055_set_debounce_time(k8055_device* device, int counter, int debounce) { if (counter == 0) { - device->data_out[OUT_COUNTER_0_DEBOUNCE_OFFSET] = k8055_int_to_debounce( + 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_int_to_debounce( + device->data_out[OUT_COUNTER_1_DEBOUNCE_OFFSET] = k8055_ms_to_char( debounce); device->data_out[OUT_CMD_OFFEST] = CMD_SET_DEBOUNCE_2; } else { @@ -395,7 +425,7 @@ int k8055_get_all_input(k8055_device* device, int *bitmask, int *analog0, int cycles = 2; if (quick) cycles = 1; - int r = read_data(device, cycles); + int r = k8055_read_data(device, cycles); if (r != 0) return r; @@ -415,3 +445,18 @@ int k8055_get_all_input(k8055_device* device, int *bitmask, int *analog0, | 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 index 75f379c..5154214 100644 --- a/src/k8055.h +++ b/src/k8055.h @@ -61,70 +61,84 @@ enum k8055_error_code { int k8055_open_device(int port, k8055_device** device); /** Closes the given device. */ -void k8055_close_device(k8055_device* port); +void k8055_close_device(k8055_device* device); /**Sets all digital ouputs according to the given bitmask. - * @param port address of board + * @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*, int bitmask); +int k8055_set_all_digital(k8055_device* device, int bitmask); /**Sets a digital output at given channel. - * @param port address of board + * @param device k8055 board * @param channel channel of port * @param value output status: '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_digital(k8055_device*, int channel, int value); +int k8055_set_digital(k8055_device* device, int channel, int value); /**Sets the values of both analog outputs. - * @param port address of board + * @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*, int analog0, int analog1); +int k8055_set_all_analog(k8055_device* device, int analog0, int analog1); /**Sets the value for an analog output at a given channel. - * @param port address of board + * @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*, int channel, int value); +int k8055_set_analog(k8055_device* device, int channel, int value); /**Resets a hardware integrated counter of the Velleman K8055 board. - * @param port address of 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*, int counter); +int k8055_reset_counter(k8055_device* device, int counter); /**Sets the debounce time of a hardware integrated counter of the Velleman K8055 board. - * @param port address of 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*, int counter, int debounce); +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 port address of board - * @param digitalBitmask bitmask value of digital inputs + * @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*, int *digitalBitmask, int *analog0, +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 } -- cgit v1.2.3