aio: add initial analog input support
authorNandkishor Sonar <nandkishor.sonar@intel.com>
Thu, 1 May 2014 15:36:11 +0000 (16:36 +0100)
committerBrendan Le Foll <brendan.le.foll@intel.com>
Thu, 1 May 2014 15:38:17 +0000 (16:38 +0100)
Signed-off-by: Nandkishor Sonar <nandkishor.sonar@intel.com>
Reviewed-by: Brendan Le Foll <brendan.le.foll@intel.com>
api/aio.h [new file with mode: 0644]
examples/CMakeLists.txt
examples/analogin_a0.c [new file with mode: 0644]
src/CMakeLists.txt
src/aio/aio.c [new file with mode: 0644]

diff --git a/api/aio.h b/api/aio.h
new file mode 100644 (file)
index 0000000..619b831
--- /dev/null
+++ b/api/aio.h
@@ -0,0 +1,82 @@
+/*
+ * Author: Nandkishor Sonar
+ * Copyright (c) 2014 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 <stdio.h>
+#include <fcntl.h>
+
+#include "maa.h"
+#include "gpio.h"
+
+#define TOTAL_ANALOG_INPUTS_ON_BOARD    (6)
+
+static const unsigned int A0 = 0;
+static const unsigned int A1 = 1;
+static const unsigned int A2 = 2;
+static const unsigned int A3 = 3;
+static const unsigned int A4 = 4;
+static const unsigned int A5 = 5;
+
+#define ADC_RAW_RESOLUTION_BITS         (12)
+#define ADC_SUPPORTED_RESOLUTION_BITS   (10)
+#define ADC_COMMON_GATE_A4_A5           (29)
+
+static const unsigned int
+adc_gate_pins[TOTAL_ANALOG_INPUTS_ON_BOARD] = {37, 36, 23, 22, 21, 20};
+
+typedef struct {
+    unsigned int channel;
+    FILE *adc_in_fp;
+} maa_aio_context;
+
+/** Initialise an Analog input device, connected to the specified pin
+ *
+ * @param aio_channel channel number to read ADC inputs
+ *
+ * @returns pointer to maa_aio_context structure after initialisation of Analog
+ * input pin successfully, else returns null.
+ */
+maa_aio_context* maa_aio_init(unsigned int aio_channel);
+
+/** Read the input voltage, represented as an unsigned short in the range [0x0,
+ * 0xFFFF]
+ *
+ * @param dev -  pointer to maa_aio_context structure  initialised by
+ * maa_aio_init()
+ *
+ * @returns 16-bit unsigned integer representing the current input voltage,
+ * normalised to a 16-bit value
+ */
+unsigned int maa_aio_read_u16(maa_aio_context* dev);
+
+/** Close the analog input context
+ * - Will free the memory for the context.
+ *
+ * @param dev -  pointer to maa_aio_context structure  initialised by
+ * maa_aio_init()
+ *
+ * @return maa_result_t - result type.
+ */
+maa_result_t maa_aio_close(maa_aio_context* dev);
index 9da7162..49de0b3 100644 (file)
@@ -2,6 +2,7 @@ add_executable (i2c_HMC5883L i2c_HMC5883L.c)
 add_executable (hellomaa hellomaa.c)
 add_executable (cycle-pwm3 cycle-pwm3.c)
 add_executable (blink-io8 blink-io8.c)
+add_executable (analogin_a0 analogin_a0.c)
 
 include_directories(${PROJECT_SOURCE_DIR}/api ${PROJECT_SOURCE_DIR}/include)
 
@@ -9,3 +10,4 @@ target_link_libraries (hellomaa maa)
 target_link_libraries (i2c_HMC5883L maa m)
 target_link_libraries (cycle-pwm3 maa)
 target_link_libraries (blink-io8 maa)
+target_link_libraries (analogin_a0 maa)
diff --git a/examples/analogin_a0.c b/examples/analogin_a0.c
new file mode 100644 (file)
index 0000000..e73285c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Author: Nandkishor Sonar
+ * Copyright (c) 2014 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 <unistd.h>
+
+#include "aio.h"
+
+int main ()
+{
+    maa_aio_context* adc_a0;
+    unsigned int adc_value = 0;
+    int i = 0;
+
+    adc_a0 = maa_aio_init(A0);
+    if (adc_a0 == NULL) {
+        return 1;
+    }
+
+    for(i = 0; i < 10; i++) {
+        adc_value = maa_aio_read_u16(adc_a0);
+        fprintf(stdout, "ADC A0 read %X\n", adc_value);
+    }
+
+    maa_aio_close(adc_a0);
+
+    return MAA_SUCCESS;
+}
index ee8c0b5..2498009 100644 (file)
@@ -9,6 +9,7 @@ set (maa_LIB_HEADERS
   ${PROJECT_SOURCE_DIR}/api/i2c.h
   ${PROJECT_SOURCE_DIR}/api/pwm.h
   ${PROJECT_SOURCE_DIR}/api/spi.h
+  ${PROJECT_SOURCE_DIR}/api/aio.h
   ${PROJECT_SOURCE_DIR}/include/smbus.h
   ${PROJECT_SOURCE_DIR}/include/version.h
 )
@@ -27,6 +28,7 @@ set (maa_LIB_SRCS
   ${PROJECT_SOURCE_DIR}/src/i2c/smbus.c
   ${PROJECT_SOURCE_DIR}/src/pwm/pwm.c
   ${PROJECT_SOURCE_DIR}/src/spi/spi.c
+  ${PROJECT_SOURCE_DIR}/src/aio/aio.c
 # autogenerated version file
   ${CMAKE_CURRENT_BINARY_DIR}/version.c
 )
diff --git a/src/aio/aio.c b/src/aio/aio.c
new file mode 100644 (file)
index 0000000..35734f3
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Author: Nandkishor Sonar
+ * Copyright (c) 2014 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 <stdlib.h>
+
+#include "aio.h"
+
+static maa_result_t aio_get_valid_fp(maa_aio_context* dev)
+{
+    char file_path[64]= "";
+
+    //Open file Analog device input channel raw voltage file for reading.
+    snprintf(file_path, 64, "/sys/bus/iio/devices/iio:device0/in_voltage%d_raw",
+        dev->channel );
+
+    if (NULL == (dev->adc_in_fp = fopen(file_path, "r"))) {
+       fprintf(stderr, "Failed to open Analog input raw file %s for "
+           "reading!\n", file_path); return( MAA_ERROR_INVALID_RESOURCE);
+    }
+
+    return MAA_SUCCESS;
+}
+
+/** Configure multiplexer for Analog Input
+ *
+ * @param aio_channel = Analog input channel to read
+ *
+ * @return maa_result_t - result type.
+ *
+ */
+static maa_result_t maa_aio_set_mux(unsigned int aio_channel)
+{
+    maa_result_t result;
+    maa_gpio_context* aio_gate;
+
+    //Initialise VINx multiplexer gate pins
+    aio_gate = maa_gpio_init(adc_gate_pins[aio_channel]);
+
+    if (NULL == aio_gate) {
+        fprintf(stderr, "Failed to initialise first gate pin %d for  ADC "
+            "channel %d !\n", adc_gate_pins[aio_channel], aio_channel);
+        return MAA_ERROR_INVALID_RESOURCE;
+    }
+
+    //Set direction to output for the ADC input gate
+    result = maa_gpio_dir(aio_gate, MAA_GPIO_OUT);
+
+    if (MAA_SUCCESS == result) {
+        // Write gate configuration output value
+        result = maa_gpio_write(aio_gate, 0);
+
+        if (MAA_SUCCESS == result) {
+            //For A4 and A5 Analog common gate pin should be high for the
+            // Galileo board revision D
+            if (A4 == aio_channel || A5 == aio_channel) {
+                aio_gate = maa_gpio_init(ADC_COMMON_GATE_A4_A5);
+
+                //Set direction to output for the gate
+                if (NULL == aio_gate) {
+                    fprintf(stderr, "Failed to initialise second gate pin %d "
+                    "for  ADC channel %d !\n", ADC_COMMON_GATE_A4_A5,
+                    aio_channel);
+                    return(MAA_ERROR_INVALID_RESOURCE);
+                }
+
+                result = maa_gpio_dir(aio_gate, MAA_GPIO_OUT);
+                if (MAA_SUCCESS == result)
+                // Write gate configuration output value
+                result = maa_gpio_write(aio_gate, 1);
+            }
+        }
+    }
+
+    if (NULL != aio_gate)
+        free(aio_gate);
+
+    return (result);
+}
+
+/** Initialise an Analog input, connected to the specified channel
+ *
+ * @param aio_channel Analog input channel to read
+ *
+ * @returns pointer to maa_aio_context structure  after initialisation of
+ * Analog input pin connected to the device successfully, else returns NULL.
+ */
+maa_aio_context* maa_aio_init(unsigned int aio_channel)
+{
+    maa_aio_context* dev;
+
+    // Validate input pins 0-5
+    if (aio_channel > TOTAL_ANALOG_INPUTS_ON_BOARD) {
+           fprintf(stderr, "Invalid Analog  input channel %d specified!\n",
+           aio_channel);
+        return NULL;
+    }
+
+    //Set-up multiplexer for the Analog input channel
+    if (MAA_SUCCESS != maa_aio_set_mux(aio_channel)) {
+       fprintf(stderr, "Failed to set-up  Analog  input channel %d "
+           "multiplexer!\n", aio_channel); return NULL;
+    }
+
+    //Create ADC device connected to specified channel
+    dev = (maa_aio_context*) malloc(sizeof(maa_aio_context));
+    if (NULL == dev) {
+       fprintf(stderr, "Insufficient memory for specified Analog input channel "
+           "%d !\n", aio_channel);
+        return NULL;
+    }
+    dev->channel = aio_channel;
+
+    //Open valid  analog input file and get the pointer.
+    if (MAA_SUCCESS != aio_get_valid_fp(dev)) {
+        free(dev);
+        return NULL;
+    }
+
+    return dev;
+}
+
+/** Read the input voltage, represented as an unsigned short in the range [0x0,
+ * 0xFFFF]
+ *
+ * @param pointer to maa_aio_context structure  initialised by
+ * maa_aio_init()
+ *
+ * @returns
+ *   16-bit unsigned int representing the current input voltage, normalised to
+ *   a 16-bit value
+ */
+unsigned int maa_aio_read_u16(maa_aio_context* dev)
+{
+    char buffer[16] = "";
+    unsigned int raw_value=0;
+    unsigned int analog_value=0;
+    unsigned int shifter_value=0;
+
+    if (NULL == dev->adc_in_fp) {
+        aio_get_valid_fp(dev);
+    }
+
+    fseek(dev->adc_in_fp, SEEK_SET, 0);
+    fread(buffer, sizeof(buffer), 1, dev->adc_in_fp);
+    fseek(dev->adc_in_fp, SEEK_SET, 0);
+
+    raw_value = atoi(buffer);
+
+    /* Adjust the raw analog input reading to supported resolution value*/
+    if (ADC_RAW_RESOLUTION_BITS == ADC_SUPPORTED_RESOLUTION_BITS) {
+        analog_value = raw_value;
+    }
+    else {
+        if (ADC_RAW_RESOLUTION_BITS > ADC_SUPPORTED_RESOLUTION_BITS) {
+            shifter_value = ADC_RAW_RESOLUTION_BITS - ADC_SUPPORTED_RESOLUTION_BITS;
+            analog_value =  raw_value >> shifter_value;
+        } else {
+            shifter_value = ADC_SUPPORTED_RESOLUTION_BITS - ADC_RAW_RESOLUTION_BITS;
+            analog_value = raw_value << shifter_value;
+        }
+    }
+
+    return analog_value;
+}
+
+/** Close the analog input and free context memory
+ *
+ * @param dev - the analog input context
+ *
+ * @return maa result type.
+ */
+maa_result_t maa_aio_close(maa_aio_context* dev)
+{
+    if (NULL != dev)
+        free(dev);
+
+    return(MAA_SUCCESS);
+}