From bec533d8bdd2527b6a50ffcc62258e9460d6cf12 Mon Sep 17 00:00:00 2001 From: Noel Eck Date: Fri, 9 Sep 2016 16:17:48 -0700 Subject: [PATCH] joystick12: Added 2 axis analog joystick12 C sensor Added the C source for the joystick12 with necessary changes to cmake, examples, and docs. Signed-off-by: Noel Eck --- examples/c/CMakeLists.txt | 1 + examples/c/joystick12.c | 86 +++++++++++++ src/joystick12/CMakeLists.txt | 13 +- src/joystick12/joystick12.c | 206 ++++++++++++++++++++++++++++++++ src/joystick12/joystick12.h | 151 +++++++++++++++++++++++ src/joystick12/joystick12_fti.c | 143 ++++++++++++++++++++++ 6 files changed, 595 insertions(+), 5 deletions(-) create mode 100644 examples/c/joystick12.c create mode 100644 src/joystick12/joystick12.c create mode 100644 src/joystick12/joystick12.h create mode 100644 src/joystick12/joystick12_fti.c diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index 534ba217..5e08cc8d 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -101,6 +101,7 @@ add_example (emg) add_example (gsr) add_example (light) add_example (ldt0028) +add_example (joystick12) # Custom examples add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) diff --git a/examples/c/joystick12.c b/examples/c/joystick12.c new file mode 100644 index 00000000..27aa0285 --- /dev/null +++ b/examples/c/joystick12.c @@ -0,0 +1,86 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "joystick12.h" + +bool shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + +int main() +{ + signal(SIGINT, sig_handler); + + //! [Interesting] + + // Instantiate a joystick12 sensor + // X = Analog pin A0 + // Y = Analog pin A1 + joystick12_context sensor = joystick12_init(0, 1); + + if (!sensor) + { + printf("joystick12_init() failed.\n"); + return -1; + } + + printf("Press any key to zero joystick...\n"); + getchar(); + + // Zero x and y axis + joystick12_zero(sensor); + + printf("Hold the X axis to the far neg or pos value, then press a key...\n"); + getchar(); + joystick12_calibrate_x(sensor); + printf("Hold the Y axis to the far neg or pos value, then press a key...\n"); + getchar(); + joystick12_calibrate_y(sensor); + + // Every half a second, sample the sensor output + float x, y; + while (shouldRun) + { + joystick12_get_value_x(sensor, &x); + joystick12_get_value_y(sensor, &y); + + printf("X: %5.02f Y: %5.02f\n", x, y); + usleep(500000); + } + + //! [Interesting] + + printf("Exiting\n"); + + joystick12_close(sensor); + + return 0; +} diff --git a/src/joystick12/CMakeLists.txt b/src/joystick12/CMakeLists.txt index 0d0afc25..a8086d85 100644 --- a/src/joystick12/CMakeLists.txt +++ b/src/joystick12/CMakeLists.txt @@ -1,5 +1,8 @@ -set (libname "joystick12") -set (libdescription "ElecFreaks Joystick 1.2") -set (module_src ${libname}.cxx) -set (module_hpp ${libname}.hpp) -upm_module_init() +upm_mixed_module_init (NAME joystick12 + DESCRIPTION "ElecFreaks Joystick 1.2" + C_HDR joystick12.h + C_SRC joystick12.c + CPP_HDR joystick12.hpp + CPP_SRC joystick12.cxx + FTI_SRC joystick12_fti.c + REQUIRES mraa) diff --git a/src/joystick12/joystick12.c b/src/joystick12/joystick12.c new file mode 100644 index 00000000..aee51c47 --- /dev/null +++ b/src/joystick12/joystick12.c @@ -0,0 +1,206 @@ +/* + * Author: + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "joystick12.h" + +joystick12_context joystick12_init(int16_t apin_x, int16_t apin_y) +{ + joystick12_context dev = + (joystick12_context) malloc(sizeof(struct _joystick12_context)); + + if(dev == NULL) return NULL; + + /* Init analog pins */ + dev->ai_x = mraa_aio_init(apin_x); + dev->ai_y = mraa_aio_init(apin_y); + + /* Set the ref, zero the offset */ + dev->m_count_offset_x = 0.0; + dev->m_count_scale_x = 2.0; + dev->m_count_offset_y = 0.0; + dev->m_count_scale_y = 2.0; + + if((dev->ai_x == NULL) || (dev->ai_y == NULL)) + { + free(dev); + return NULL; + } + + return dev; +} + +void joystick12_close(joystick12_context dev) +{ + mraa_aio_close(dev->ai_x); + mraa_aio_close(dev->ai_y); + free(dev); +} + +upm_result_t joystick12_read_data(const joystick12_context dev, int* values) +{ + /* Throw away first read */ + mraa_aio_read(dev->ai_x); + values[0] = mraa_aio_read(dev->ai_x); + /* Throw away first read */ + mraa_aio_read(dev->ai_y); + values[1] = mraa_aio_read(dev->ai_y); + + if (values[0] < 0 || values[1] < 0) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t joystick12_set_offset_x(const joystick12_context dev, float offset) +{ + dev->m_count_offset_x = offset; + return UPM_SUCCESS; +} + +upm_result_t joystick12_set_offset_y(const joystick12_context dev, float offset) +{ + dev->m_count_offset_y = offset; + return UPM_SUCCESS; +} + +upm_result_t joystick12_set_scale_x(const joystick12_context dev, float scale) +{ + dev->m_count_scale_x = scale; + return UPM_SUCCESS; +} + +upm_result_t joystick12_set_scale_y(const joystick12_context dev, float scale) +{ + dev->m_count_scale_y = scale; + return UPM_SUCCESS; +} + +upm_result_t joystick12_get_value_x(const joystick12_context dev, float *value) +{ + int counts[2] = {0,0}; + + /* Read counts from the generic read method */ + joystick12_read_data(dev, counts); + + /* Get max adc value range 1023, 2047, 4095, etc... */ + float max_adc = (1 << mraa_aio_get_bit(dev->ai_x)) - 1; + + /* Apply raw offset */ + *value = counts[0] + dev->m_count_offset_x; + + // Scale to +/- 1.0 + *value = -2.0 * (((max_adc/2.0 - *value))/max_adc * dev->m_count_scale_x); + + // Clip to +/- 1.0 + if (*value > 1.0) *value = 1.0; + else if (*value < -1.0) *value = -1.0; + + return UPM_SUCCESS; +} + +upm_result_t joystick12_get_value_y(const joystick12_context dev, float *value) +{ + int counts[2] = {0,0}; + + /* Read counts from the generic read method */ + joystick12_read_data(dev, counts); + + /* Get max adc value range 1023, 2047, 4095, etc... */ + float max_adc = (1 << mraa_aio_get_bit(dev->ai_y)) - 1; + + /* Apply raw offset */ + *value = counts[1] + dev->m_count_offset_y; + + // Scale to +/- 1.0 + *value = -2.0 * (((max_adc/2.0 - *value))/max_adc * dev->m_count_scale_y); + + // Clip to +/- 1.0 + if (*value > 1.0) *value = 1.0; + else if (*value < -1.0) *value = -1.0; + + return UPM_SUCCESS; +} + +upm_result_t joystick12_zero(const joystick12_context dev) +{ + int counts[2] = {0, 0}; + + /* Read counts from the generic read method */ + joystick12_read_data(dev, counts); + + /* Get max adc value range 1023, 2047, 4095, etc... */ + float max_adc = (1 << mraa_aio_get_bit(dev->ai_y)) - 1; + + dev->m_count_offset_x = max_adc/2.0 - counts[0]; + dev->m_count_offset_y = max_adc/2.0 - counts[1]; + + return UPM_SUCCESS; +} + +upm_result_t joystick12_calibrate_x(const joystick12_context dev) +{ + int counts[2] = {0, 0}; + + /* Read counts from the generic read method */ + joystick12_read_data(dev, counts); + + /* Get max adc value range 1023, 2047, 4095, etc... */ + float max_adc = (1 << mraa_aio_get_bit(dev->ai_y)) - 1; + + float fcounts = counts[0]; + + /* no need to scale if counts is a max or min value */ + if ((fcounts == 0) || (fcounts == max_adc)) return UPM_SUCCESS; + + dev->m_count_scale_x = + 1.0 / (1.0 - 2.0 * fcounts/max_adc); + dev->m_count_scale_x = fabs(dev->m_count_scale_x); + + return UPM_SUCCESS; +} + +upm_result_t joystick12_calibrate_y(const joystick12_context dev) +{ + int counts[2] = {0, 0}; + + /* Read counts from the generic read method */ + joystick12_read_data(dev, counts); + + /* Get max adc value range 1023, 2047, 4095, etc... */ + float max_adc = (1 << mraa_aio_get_bit(dev->ai_y)) - 1; + + float fcounts = counts[1]; + + /* no need to scale if counts is a max or min value */ + if ((fcounts == 0) || (fcounts == max_adc)) return UPM_SUCCESS; + + dev->m_count_scale_y = + 1.0 / (1.0 - 2.0 * fcounts/max_adc); + dev->m_count_scale_y = fabs(dev->m_count_scale_y); + + return UPM_SUCCESS; +} diff --git a/src/joystick12/joystick12.h b/src/joystick12/joystick12.h new file mode 100644 index 00000000..5f852769 --- /dev/null +++ b/src/joystick12/joystick12.h @@ -0,0 +1,151 @@ +/* + * Author: + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include "upm.h" +#include "mraa/aio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * device context + */ +typedef struct _joystick12_context { + /* mraa ai_x pin context */ + mraa_aio_context ai_x; + /* mraa ai_y pin context */ + mraa_aio_context ai_y; + /* Raw count offset - x axis */ + float m_count_offset_x; + /* Raw count offset - y axis */ + float m_count_offset_y; + /* Raw count scale - x axis */ + float m_count_scale_x; + /* Raw count scale - y axis */ + float m_count_scale_y; +} *joystick12_context; + +/** + * Initialize analog sensor + * @param pin is Analog pin + * @return sensor context as void pointer + */ +joystick12_context joystick12_init(int16_t apin_x, int16_t apin_y); + +/** + * Analog sensor destructor + * @param sensor context pointer deallocate memory + */ +void joystick12_close(joystick12_context dev); + +/** + * Generic read joystick data method + * @param dev sensor device context pointer + * @param value pointer to an int[2] in which data is returned + */ +upm_result_t joystick12_read_data(const joystick12_context dev, int* values); + +/** + * Set sensor offset. This offset is applied to the return value: + * counts = counts + offset + * @param dev sensor context pointer + * @param offset count offset value used + * @return Function result code + */ +upm_result_t joystick12_set_offset_x(const joystick12_context dev, + float offset); + +/** + * Set sensor offset. This offset is applied to the return value: + * counts = counts + offset + * @param dev sensor context pointer + * @param offset count offset value used + * @return Function result code + */ +upm_result_t joystick12_set_offset_y(const joystick12_context dev, + float offset); + +/** + * Set sensor scale. This scale is applied to the return value: + * counts = counts * scale + * @param dev sensor context pointer + * @param scale count scale value used + * @return Function result code + */ +upm_result_t joystick12_set_scale_x(const joystick12_context dev, float scale); + +/** + * Set sensor scale. This scale is applied to the return value: + * counts = counts * scale + * @param dev sensor context pointer + * @param scale count scale value used + * @return Function result code + */ +upm_result_t joystick12_set_scale_y(const joystick12_context dev, float scale); + +/** + * Read value from sensor + * @param dev sensor context pointer + * @param *value normalized value from sensor, units depend on unit enum + * @param unit Enum which specifies units returned in *value + * @return Function result code + */ +upm_result_t joystick12_get_value_x(const joystick12_context dev, float *value); + +/** + * Read value from sensor + * @param dev sensor context pointer + * @param *value normalized value from sensor, units depend on unit enum + * @param unit Enum which specifies units returned in *value + * @return Function result code + */ +upm_result_t joystick12_get_value_y(const joystick12_context dev, float *value); + +/** + * Zero out the sensor x and y axis + * @param dev sensor context pointer + * @return Function result code + */ +upm_result_t joystick12_zero(const joystick12_context dev); + +/** + * Set x scale. Move joystick to min or max x and call calibrate + * @param dev sensor context pointer + * @return Function result code + */ +upm_result_t joystick12_calibrate_x(const joystick12_context dev); + +/** + * Set y scale. Move joystick to min or max y and call calibrate + * @param dev sensor context pointer + * @return Function result code + */ +upm_result_t joystick12_calibrate_y(const joystick12_context dev); + +#ifdef __cplusplus +} +#endif diff --git a/src/joystick12/joystick12_fti.c b/src/joystick12/joystick12_fti.c new file mode 100644 index 00000000..c4424b09 --- /dev/null +++ b/src/joystick12/joystick12_fti.c @@ -0,0 +1,143 @@ +/* + * Author: + * Copyright (c) 2015 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "joystick12.h" +#include "upm_fti.h" +#include "fti/upm_sensor.h" +#include "fti/upm_joystick.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_joystick12_name[] = "JOYSTICK12"; +const char upm_joystick12_description[] = "Analog joystick sensor"; +const upm_protocol_t upm_joystick12_protocol[] = {UPM_ANALOG}; +const upm_sensor_t upm_joystick12_category[] = {UPM_JOYSTICK}; + +// forward declarations +const void* upm_joystick12_get_ft(upm_sensor_t sensor_type); +void* upm_joystick12_init_str(const char* protocol, const char* params); +void upm_joystick12_close(void* dev); +const upm_sensor_descriptor_t upm_joystick12_get_descriptor(); +upm_result_t upm_joystick12_set_offset_x(const void* dev, float offset); +upm_result_t upm_joystick12_set_offset_y(const void* dev, float offset); +upm_result_t upm_joystick12_set_scale_x(const void* dev, float scale); +upm_result_t upm_joystick12_set_scale_y(const void* dev, float scale); +upm_result_t upm_joystick12_get_value_x(const void* dev, float *value); +upm_result_t upm_joystick12_get_value_y(const void* dev, float *value); + + + +/* This sensor implementes 2 function tables */ +/* 1. Generic base function table */ +static const upm_sensor_ft ft_gen = +{ + .upm_sensor_init_name = &upm_joystick12_init_str, + .upm_sensor_close = &upm_joystick12_close, + .upm_sensor_get_descriptor = &upm_joystick12_get_descriptor +}; + +/* 2. JOYSTICK function table */ +static const upm_joystick_ft ft_joystick = +{ + .upm_joystick_set_offset_x = &upm_joystick12_set_offset_x, + .upm_joystick_set_offset_y = &upm_joystick12_set_offset_y, + .upm_joystick_set_scale_x = &upm_joystick12_set_scale_x, + .upm_joystick_set_scale_y = &upm_joystick12_set_scale_y, + .upm_joystick_get_value_x = &upm_joystick12_get_value_x, + .upm_joystick_get_value_y = &upm_joystick12_get_value_y +}; + +const void* upm_joystick12_get_ft(upm_sensor_t sensor_type) +{ + switch(sensor_type) + { + case UPM_SENSOR: + return &ft_gen; + case UPM_JOYSTICK: + return &ft_joystick; + default: + return NULL; + } +} + +void* upm_joystick12_init_str(const char* protocol, const char* params) +{ + fprintf(stderr, "String initialization - not implemented, using ain0 = x ain1 = y: %s\n", __FILENAME__); + return joystick12_init(0, 1); +} + +void upm_joystick12_close(void* dev) +{ + joystick12_close((joystick12_context)dev); +} + +const upm_sensor_descriptor_t upm_joystick12_get_descriptor() +{ + /* Fill in the descriptor */ + upm_sensor_descriptor_t usd; + usd.name = upm_joystick12_name; + usd.description = upm_joystick12_description; + usd.protocol_size = 1; + usd.protocol = upm_joystick12_protocol; + usd.category_size = 1; + usd.category = upm_joystick12_category; + + return usd; +} + +upm_result_t upm_joystick12_set_offset_x(const void* dev, float offset) +{ + return joystick12_set_offset_x((joystick12_context)dev, offset); +} + +upm_result_t upm_joystick12_set_offset_y(const void* dev, float offset) +{ + return joystick12_set_offset_y((joystick12_context)dev, offset); +} + +upm_result_t upm_joystick12_set_scale_x(const void* dev, float scale) +{ + return joystick12_set_scale_x((joystick12_context)dev, scale); +} + +upm_result_t upm_joystick12_set_scale_y(const void* dev, float scale) +{ + return joystick12_set_scale_y((joystick12_context)dev, scale); +} + +upm_result_t upm_joystick12_get_value_x(const void* dev, float *value) +{ + return joystick12_get_value_x((joystick12_context)dev, value); +} + +upm_result_t upm_joystick12_get_value_y(const void* dev, float *value) +{ + return joystick12_get_value_y((joystick12_context)dev, value); +} +