Example Program for EVAL-AD7606

Dependencies:   platform_drivers

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers iio_ad7606.c Source File

iio_ad7606.c

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  *   @file    iio_ad7606.c
00003  *   @brief   Implementation of AD7606 IIO application interfaces
00004  *   @details This module acts as an interface for AD7606 IIO application
00005 ********************************************************************************
00006  * Copyright (c) 2020-2021 Analog Devices, Inc.
00007  *
00008  * This software is proprietary to Analog Devices, Inc. and its licensors.
00009  * By using this software you agree to the terms of the associated
00010  * Analog Devices Software License Agreement.
00011 *******************************************************************************/
00012 
00013 /******************************************************************************/
00014 /***************************** Include Files **********************************/
00015 /******************************************************************************/
00016 
00017 #include <inttypes.h>
00018 #include <string.h>
00019 #include <errno.h>
00020 #include <math.h>
00021 
00022 #include "app_config.h"
00023 #include "iio_ad7606.h"
00024 #include "platform_support.h"
00025 #include "spi_extra.h"
00026 #include "gpio_extra.h"
00027 #include "uart_extra.h"
00028 #include "irq_extra.h"
00029 #include "error.h"
00030 
00031 #include "ad7606.h"
00032 #include "adc_data_capture.h"
00033 #include "ad7606_support.h"
00034 #include "ad7606_user_config.h"
00035 
00036 /******************************************************************************/
00037 /************************ Macros/Constants ************************************/
00038 /******************************************************************************/
00039 
00040 /* ADC data to Voltage conversion scale factor for IIO client */
00041 #define DEFAULT_SCALE       ((DEFAULT_CHN_RANGE / ADC_MAX_COUNT_BIPOLAR) * 1000)
00042 
00043 /* LSB Threshold to entry into open circuit detection as per datasheet */
00044 #define MANUAL_OPEN_DETECT_ENTRY_TRHLD          350
00045 
00046 /* Manual open circuit detect LSB threshold @50K Rpd as per datasheet */
00047 #define MANUAL_OPEN_DETECT_THRESHOLD_RPD50K     20
00048 
00049 /* Number of consecutive conversions (N) in manual open circuit detection */
00050 #define MANUAL_OPEN_DETECT_CONV_CNTS            10
00051 
00052 /* LSB Threshold b/w consecutive N conversions */
00053 #define MANUAL_OPEN_DETECT_CONV_TRSHLD          10
00054 
00055 /* Number of common mode conversions in manual open circuit detect */
00056 #define MANUAL_OPEN_DETECT_CM_CNV_CNT           3
00057 
00058 /* Max number of queue counts for auto mode open circuit detection */
00059 #define AUTO_OPEN_DETECT_QUEUE_MAX_CNT          128
00060 #define AUTO_OPEN_DETECT_QUEUE_EXTRA_CONV_CNT   15
00061 
00062 /* Maximum ADC calibration gain value */
00063 #define ADC_CALIBRATION_GAIN_MAX        64.0
00064 
00065 #if defined(DEV_AD7606C_18)
00066 #define OFFSET_REG_RESOLUTION       4
00067 #else
00068 #define OFFSET_REG_RESOLUTION       1
00069 #endif
00070 
00071 /* Bytes per sample. This count should divide the total 256 bytes into 'n' equivalent
00072  * ADC samples as IIO library requests only 256bytes of data at a time in a given
00073  * data read query.
00074  * For 1 to 8-bit ADC, bytes per sample = 1 (2^0)
00075  * For 9 to 16-bit ADC, bytes per sample = 2 (2^1)
00076  * For 17 to 32-bit ADC, bytes per sample = 4 (2^2)
00077  **/
00078 #if (AD7606X_ADC_RESOLUTION == 18)
00079 #define BYTES_PER_SAMPLE    sizeof(uint32_t)    // For ADC resolution of 18-bits
00080 #else
00081 #define BYTES_PER_SAMPLE    sizeof(uint16_t)    // For ADC resolution of 16-bits
00082 #endif
00083 
00084 /* Number of data storage bits (needed for IIO client to plot ADC data) */
00085 #define CHN_STORAGE_BITS    (BYTES_PER_SAMPLE * 8)
00086 
00087 /******************************************************************************/
00088 /*************************** Types Declarations *******************************/
00089 /******************************************************************************/
00090 
00091 /* IIO interface descriptor */
00092 static struct iio_desc *p_ad7606_iio_desc;
00093 
00094 /**
00095  * Device name.
00096  */
00097 static const char dev_name[] = ACTIVE_DEVICE_NAME;
00098 
00099 /**
00100  * Pointer to the struct representing the AD7606 IIO device
00101  */
00102 struct ad7606_dev *p_ad7606_dev_inst = NULL;
00103 
00104 
00105 /* Device attributes with default values */
00106 
00107 /* Power down mode values string representation (possible values specified in datasheet) */
00108 static char *operating_mode_str[] = {
00109     "0  (Normal Mode)",
00110     "1  (Standby Mode)",
00111     "2  (Auto Standby Mode)",
00112     "3  (Shutdown Mode)"
00113 };
00114 
00115 /* Bandwidth values string */
00116 static char *bandwidth_str[] = {
00117     "0  (Low)",
00118     "1  (High)"
00119 };
00120 
00121 /* Channel range values string representation (possible values specified in datasheet) */
00122 static char *chn_range_str[] = {
00123 #if defined(DEV_AD7606B)
00124     "0  (+/-2.5V SE)", "1  (+/-5.0V SE)", "2  (+/-10.0V SE)", "3  (+/-10.0V SE)",
00125     "4  (+/-10.0V SE)", "5  (+/-10.0V SE)", "6  (+/-10.0V SE)", "7  (+/-10.0V SE)",
00126     "8  (+/-10.0V SE)", "9  (+/-10.0V SE)", "10  (+/-10.0V SE)", "11  (+/-10.0V SE)",
00127 #elif defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16)
00128     "0  (+/-2.5V SE)", "1  (+/-5.0V SE)", "2  (+/-6.25V SE)", "3  (+/-10.0V SE)",
00129     "4  (+/-12.5V SE)", "5  (0 to 5V SE)", "6  (0 to 10V SE)", "7  (0 to 12.5V SE)",
00130     "8  (+/-5.0V Diff)", "9  (+/-10.0V Diff)", "10  (+/-12.5V Diff)", "11  (+/-20.0V Diff)"
00131 #elif defined(DEV_AD7609)
00132     "0  (+/-10.0V SE)", "1  (+/-20.0V SE)"
00133 #else
00134     "0  (+/-5.0V SE)", "1  (+/-10.0V SE)"
00135 #endif
00136 };
00137 
00138 /* Oversampling values string representation (possible values specified in datasheet) */
00139 static char *oversampling_val_str[] = {
00140     "0 (no oversampling)", "1 (oversampling by 2)", "2 (oversampling by 4)",
00141     "3 (oversampling by 8)", "4 (oversampling by 16)", "5 (oversampling by 32)",
00142     "6 (oversampling by 64)", "7 (oversampling by 128)", "8 (oversampling by 256)"
00143 };
00144 
00145 
00146 /* Channel range values string representation (possible values specified in datasheet) */
00147 static float chn_range_val[] = {
00148 #if defined(DEV_AD7606B)
00149     2.5, 5.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0
00150 #elif defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16)
00151     2.5, 5.0, 6.25, 10.0, 12.5, 5.0, 10.0, 12.5, 5.0, 10.0, 12.5, 20.0
00152 #elif defined(DEV_AD7609)
00153     10.0, 20.0
00154 #else
00155     5.0, 10.0
00156 #endif
00157 };
00158 
00159 /* Range value per channel */
00160 static float attr_chn_range[AD7606X_ADC_CHANNELS] = {
00161     DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE,
00162     DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE
00163 };
00164 
00165 /* Scale value per channel */
00166 static float attr_scale_val[AD7606X_ADC_CHANNELS] = {
00167     DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE,
00168     DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE
00169 };
00170 
00171 /* Scale value per channel */
00172 static polarity_e attr_polarity_val[AD7606X_ADC_CHANNELS] = {
00173     BIPOLAR, BIPOLAR, BIPOLAR, BIPOLAR,
00174     BIPOLAR, BIPOLAR, BIPOLAR, BIPOLAR
00175 };
00176 
00177 /* Channel range */
00178 typedef enum {
00179     LOW,
00180     HIGH
00181 } range_e;
00182 
00183 /* Open detect auto mode QUEUE register count */
00184 static uint8_t open_detect_queue_cnts[AD7606X_ADC_CHANNELS] = {
00185     0
00186 };
00187 
00188 /* ADC gain calibration Rfilter value (in Kohms) */
00189 static uint8_t gain_calibration_reg_val[AD7606X_ADC_CHANNELS] = {
00190     0
00191 };
00192 
00193 /* Flag to trigger new background conversion and capture when READBUFF command is issued */
00194 static bool adc_data_capture_started = false;
00195 
00196 /* Gain calibration status */
00197 static bool gain_calibration_done = false;
00198 
00199 /* Open circuit mode detection flags */
00200 static bool open_circuit_detection_done = false;
00201 static bool open_circuit_detection_error = false;
00202 static bool open_circuit_detect_read_done = false;
00203 
00204 /******************************************************************************/
00205 /************************ Functions Prototypes ********************************/
00206 /******************************************************************************/
00207 
00208 static float get_vltg_conv_scale_factor(float chn_range, polarity_e polarity);
00209 static void save_local_attributes(void);
00210 
00211 /******************************************************************************/
00212 /************************ Functions Definitions *******************************/
00213 /******************************************************************************/
00214 
00215 /*!
00216  * @brief   Getter/Setter for the scale attribute value
00217  * @param   device- pointer to IIO device structure
00218  * @param   buf- pointer to buffer holding attribute value
00219  * @param   len- length of buffer string data
00220  * @param   channel- pointer to IIO channel structure
00221  * @return  Number of characters read/written
00222  */
00223 static ssize_t get_chn_scale(void *device,
00224                  char *buf,
00225                  size_t len,
00226                  const struct iio_ch_info *channel,
00227                  intptr_t id)
00228 {
00229     return (ssize_t) sprintf(buf, "%f", attr_scale_val[channel->ch_num]);
00230 }
00231 
00232 static ssize_t set_chn_scale(void *device,
00233                  char *buf,
00234                  size_t len,
00235                  const struct iio_ch_info *channel,
00236                  intptr_t id)
00237 {
00238     float scale;
00239 
00240     (void)sscanf(buf, "%f", &scale);
00241 
00242     if (scale > 0.0) {
00243         attr_scale_val[channel->ch_num] = scale;
00244         return len;
00245     }
00246 
00247     return -EINVAL;
00248 }
00249 
00250 
00251 /*!
00252  * @brief   Getter/Setter for the sampling frequency attribute value
00253  * @param   device- pointer to IIO device structure
00254  * @param   buf- pointer to buffer holding attribute value
00255  * @param   len- length of buffer string data
00256  * @param   channel- pointer to IIO channel structure
00257  * @return  Number of characters read/written
00258  * @Note    This attribute is used to define the timeout period in IIO
00259  *          client during data capture.
00260  *          Timeout = (number of requested samples * (1/sampling frequency)) + 1sec
00261  *          e.g. if sampling frequency = 1KSPS and requested samples = 400
00262  *          Timeout = (400 * 0.001) + 1 = 1.4sec
00263  */
00264 static ssize_t get_sampling_frequency(void *device,
00265                       char *buf,
00266                       size_t len,
00267                       const struct iio_ch_info *channel,
00268                       intptr_t id)
00269 {
00270     return (ssize_t) sprintf(buf, "%d", SAMPLING_RATE);
00271 }
00272 
00273 static ssize_t set_sampling_frequency(void *device,
00274                       char *buf,
00275                       size_t len,
00276                       const struct iio_ch_info *channel,
00277                       intptr_t id)
00278 {
00279     /* NA- Can't set sampling frequency value */
00280     return len;
00281 }
00282 
00283 
00284 /*!
00285  * @brief   Getter/Setter for the raw attribute value
00286  * @param   device- pointer to IIO device structure
00287  * @param   buf- pointer to buffer holding attribute value
00288  * @param   len- length of buffer string data
00289  * @param   channel- pointer to IIO channel structure
00290  * @return  Number of characters read/written
00291  */
00292 static ssize_t get_chn_raw(void *device,
00293                char *buf,
00294                size_t len,
00295                const struct iio_ch_info *channel,
00296                intptr_t id)
00297 {
00298     int32_t adc_data_raw;
00299 
00300     /* Capture the raw adc data */
00301     if (read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw) != SUCCESS) {
00302         return -EINVAL;
00303     }
00304 
00305     return (ssize_t) sprintf(buf, "%d", adc_data_raw);
00306 }
00307 
00308 static ssize_t set_chn_raw(void *device,
00309                char *buf,
00310                size_t len,
00311                const struct iio_ch_info *channel,
00312                intptr_t id)
00313 {
00314     /* NA- Can't set raw value */
00315     return len;
00316 }
00317 
00318 
00319 /*!
00320  * @brief   Getter/Setter for the operating mode attribute value
00321  * @param   device- pointer to IIO device structure
00322  * @param   buf- pointer to buffer holding attribute value
00323  * @param   len- length of buffer string data
00324  * @param   channel- pointer to IIO channel structure
00325  * @return  Number of characters read/written
00326  * @note    Available only for AD7606B and AD7606C
00327  */
00328 static ssize_t get_operating_mode(void *device,
00329                   char *buf,
00330                   size_t len,
00331                   const struct iio_ch_info *channel,
00332                   intptr_t id)
00333 {
00334     uint8_t read_val;
00335     uint8_t operating_mode_value;
00336 
00337     if (ad7606_spi_reg_read(device, AD7606_REG_CONFIG, &read_val) == SUCCESS) {
00338         operating_mode_value = (read_val & AD7606_CONFIG_OPERATION_MODE_MSK);
00339 
00340         if (operating_mode_value < sizeof(operating_mode_str) / sizeof(
00341                 operating_mode_str[0])) {
00342             return (ssize_t)sprintf(buf, "%s", operating_mode_str[operating_mode_value]);
00343         }
00344     }
00345 
00346     return -EINVAL;
00347 }
00348 
00349 static ssize_t set_operating_mode(void *device,
00350                   char *buf,
00351                   size_t len,
00352                   const struct iio_ch_info *channel,
00353                   intptr_t id)
00354 {
00355     uint8_t operating_mode_value;
00356 
00357     (void)sscanf(buf, "%d", &operating_mode_value);
00358 
00359     if (operating_mode_value < sizeof(operating_mode_str) / sizeof(
00360             operating_mode_str[0])) {
00361         if (ad7606_spi_write_mask(device,
00362                       AD7606_REG_CONFIG,
00363                       AD7606_CONFIG_OPERATION_MODE_MSK,
00364                       operating_mode_value) == SUCCESS) {
00365             return len;
00366         }
00367     }
00368 
00369     return -EINVAL;
00370 }
00371 
00372 
00373 /*!
00374  * @brief   Getter/Setter for the power down mode attribute value
00375  * @param   device- pointer to IIO device structure
00376  * @param   buf- pointer to buffer holding attribute value
00377  * @param   len- length of buffer string data
00378  * @param   channel- pointer to IIO channel structure
00379  * @return  Number of characters read/written
00380  * @note    Available for all devices except AD7606B and AD7606C
00381  */
00382 static ssize_t get_power_down_mode(void *device,
00383                    char *buf,
00384                    size_t len,
00385                    const struct iio_ch_info *channel,
00386                    intptr_t id)
00387 {
00388     uint8_t gpio_stby_val;
00389     uint8_t gpio_range_val;
00390 
00391     if (gpio_get_value(((struct ad7606_dev *)device)->gpio_stby_n,
00392                &gpio_stby_val) == SUCCESS) {
00393         if (gpio_get_value(((struct ad7606_dev *)device)->gpio_range,
00394                    &gpio_range_val) == SUCCESS) {
00395 
00396             if (gpio_stby_val) {
00397                 return sprintf(buf, "%s", operating_mode_str[AD7606_NORMAL]);
00398             } else {
00399                 if (gpio_range_val) {
00400                     return sprintf(buf, "%s", operating_mode_str[AD7606_STANDBY]);
00401                 } else {
00402                     return sprintf(buf, "%s", operating_mode_str[AD7606_SHUTDOWN]);
00403                 }
00404             }
00405         }
00406     }
00407 
00408     return -EINVAL;
00409 }
00410 
00411 static ssize_t set_power_down_mode(void *device,
00412                    char *buf,
00413                    size_t len,
00414                    const struct iio_ch_info *channel,
00415                    intptr_t id)
00416 {
00417     uint8_t power_down_mode_value;
00418     static enum ad7606_op_mode prev_power_down_mode = AD7606_NORMAL;
00419     struct ad7606_config dev_config;
00420 
00421     sscanf(buf, "%d", &power_down_mode_value);
00422 
00423     if (power_down_mode_value < (sizeof(operating_mode_str) / sizeof(
00424                          operating_mode_str[0]))) {
00425 
00426         dev_config.op_mode = power_down_mode_value;
00427 
00428         switch (power_down_mode_value) {
00429         case AD7606_NORMAL:
00430             if (ad7606_set_config(device, dev_config) == SUCCESS) {
00431                 /* Reset the device if previous power down mode was either standby
00432                  * or shutdown */
00433                 if (prev_power_down_mode != AD7606_NORMAL) {
00434 
00435                     /* Power-up wait time */
00436                     mdelay(1);
00437 
00438                     /* Toggle reset pin */
00439                     if (gpio_set_value(((struct ad7606_dev *)device)->gpio_reset,
00440                                GPIO_HIGH) == SUCCESS) {
00441                         mdelay(1);
00442 
00443                         if (gpio_set_value(((struct ad7606_dev *)device)->gpio_reset,
00444                                    GPIO_LOW) == SUCCESS) {
00445                             prev_power_down_mode = AD7606_NORMAL;
00446                             return len;
00447                         }
00448                     }
00449                 }
00450             }
00451             break;
00452 
00453         case AD7606_STANDBY:
00454             if (ad7606_set_config(device, dev_config) == SUCCESS) {
00455                 prev_power_down_mode = AD7606_STANDBY;
00456                 return len;
00457             }
00458             break;
00459 
00460         case AD7606_SHUTDOWN:
00461             if (ad7606_set_config(device, dev_config) == SUCCESS) {
00462                 prev_power_down_mode = AD7606_SHUTDOWN;
00463                 return len;
00464             }
00465             break;
00466 
00467         default:
00468             break;
00469         }
00470     }
00471 
00472     return -EINVAL;
00473 }
00474 
00475 
00476 /*!
00477  * @brief   Getter/Setter for the range attribute value
00478  * @param   device- pointer to IIO device structure
00479  * @param   buf- pointer to buffer holding attribute value
00480  * @param   len- length of buffer string data
00481  * @param   channel- pointer to IIO channel structure
00482  * @return  Number of characters read/written
00483  * @note    Available for all devices except AD7606B and AD7606C
00484  */
00485 static ssize_t get_range(void *device,
00486              char *buf,
00487              size_t len,
00488              const struct iio_ch_info *channel,
00489              intptr_t id)
00490 {
00491     uint8_t gpio_range_val;
00492     struct ad7606_dev *dev = device;
00493 
00494     if (gpio_get_value(dev->gpio_range, &gpio_range_val) == SUCCESS) {
00495         if (gpio_range_val) {
00496             return sprintf(buf, "%s", chn_range_str[HIGH]);
00497         } else {
00498             return sprintf(buf, "%s", chn_range_str[LOW]);
00499         }
00500     }
00501 
00502     return -EINVAL;
00503 }
00504 
00505 static ssize_t set_range(void *device,
00506              char *buf,
00507              size_t len,
00508              const struct iio_ch_info *channel,
00509              intptr_t id)
00510 {
00511     uint8_t range_value;
00512     struct ad7606_dev *dev = device;
00513 
00514     (void)sscanf(buf, "%d", &range_value);
00515 
00516     if (range_value < (sizeof(chn_range_str) / sizeof(chn_range_str[0]))) {
00517         if (range_value == LOW) {
00518             if (gpio_set_value(dev->gpio_range, GPIO_LOW) == SUCCESS) {
00519                 return len;
00520             }
00521         } else {
00522             if (gpio_set_value(dev->gpio_range, GPIO_HIGH) == SUCCESS) {
00523                 return len;
00524             }
00525         }
00526     }
00527 
00528     return -EINVAL;
00529 }
00530 
00531 
00532 /*!
00533  * @brief   Getter/Setter for the oversampling attribute value
00534  * @param   device- pointer to IIO device structure
00535  * @param   buf- pointer to buffer holding attribute value
00536  * @param   len- length of buffer string data
00537  * @param   channel- pointer to IIO channel structure
00538  * @return  Number of characters read/written
00539  * @note    Available for all devices except AD7606B and AD7606C
00540  */
00541 static ssize_t get_oversampling(void *device,
00542                 char *buf,
00543                 size_t len,
00544                 const struct iio_ch_info *channel,
00545                 intptr_t id)
00546 {
00547     uint8_t oversampling_value;
00548     uint8_t read_val;
00549     uint8_t gpio_osr0_val;
00550     uint8_t gpio_osr1_val;
00551     uint8_t gpio_osr2_val;
00552     struct ad7606_dev *dev = device;
00553 
00554 #if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16)
00555     if (ad7606_spi_reg_read(device,
00556                 AD7606_REG_OVERSAMPLING,
00557                 &read_val) == SUCCESS) {
00558         oversampling_value = (read_val & AD7606_OVERSAMPLING_MSK);
00559 
00560         if (oversampling_value < sizeof(oversampling_val_str) / sizeof(
00561                 oversampling_val_str[0])) {
00562             return (ssize_t)sprintf(buf, "%s", oversampling_val_str[oversampling_value]);
00563         }
00564     }
00565 #else
00566     if (gpio_get_value(dev->gpio_os0, &gpio_osr0_val) == SUCCESS) {
00567         if (gpio_get_value(dev->gpio_os1, &gpio_osr1_val) == SUCCESS) {
00568             if (gpio_get_value(dev->gpio_os2, &gpio_osr2_val) == SUCCESS) {
00569                 oversampling_value = (gpio_osr2_val << 2) | (gpio_osr1_val << 1) |
00570                              gpio_osr0_val;
00571 
00572                 if (oversampling_value < (sizeof(oversampling_val_str) / sizeof(
00573                                   oversampling_val_str[0]))) {
00574                     return sprintf(buf, "%s", oversampling_val_str[oversampling_value]);
00575                 }
00576             }
00577         }
00578     }
00579 #endif
00580 
00581     return -EINVAL;
00582 }
00583 
00584 static ssize_t set_oversampling(void *device,
00585                 char *buf,
00586                 size_t len,
00587                 const struct iio_ch_info *channel,
00588                 intptr_t id)
00589 {
00590     uint8_t oversampling_value;
00591     struct ad7606_oversampling oversampling_cfg;
00592 
00593     (void)sscanf(buf, "%d", &oversampling_value);
00594 
00595     if (oversampling_value < (sizeof(oversampling_val_str) / sizeof(
00596                       oversampling_val_str[0]))) {
00597 
00598         oversampling_cfg.os_pad = 0;
00599         oversampling_cfg.os_ratio = oversampling_value;
00600 
00601         ad7606_set_oversampling(device, oversampling_cfg);
00602 
00603         return len;
00604     }
00605 
00606     return -EINVAL;
00607 }
00608 
00609 
00610 /*!
00611  * @brief   Getter/Setter for the bandwidth attribute value
00612  * @param   device- pointer to IIO device structure
00613  * @param   buf- pointer to buffer holding attribute value
00614  * @param   len- length of buffer string data
00615  * @param   channel- pointer to IIO channel structure
00616  * @return  Number of characters read/written
00617  * @note    Available for only AD7606C
00618  */
00619 static ssize_t get_bandwidth(void *device,
00620                  char *buf,
00621                  size_t len,
00622                  const struct iio_ch_info *channel,
00623                  intptr_t id)
00624 {
00625     uint8_t bw_value;
00626     uint8_t read_val;
00627 
00628     if (ad7606_spi_reg_read(device,
00629                 AD7606_REG_BANDWIDTH,
00630                 &read_val) == SUCCESS) {
00631         bw_value = (read_val >> (channel->ch_num)) & 0x1;
00632 
00633         if (bw_value < sizeof(bandwidth_str) / sizeof(
00634                 bandwidth_str[0])) {
00635             return (ssize_t)sprintf(buf, "%s", bandwidth_str[bw_value]);
00636         }
00637     }
00638 
00639     return -EINVAL;
00640 }
00641 
00642 static ssize_t set_bandwidth(void *device,
00643                  char *buf,
00644                  size_t len,
00645                  const struct iio_ch_info *channel,
00646                  intptr_t id)
00647 {
00648     uint8_t bw_value;
00649     uint8_t read_val;
00650 
00651     (void)sscanf(buf, "%d", &bw_value);
00652 
00653     if (bw_value < sizeof(bandwidth_str) / sizeof(
00654             bandwidth_str[0])) {
00655         if (ad7606_spi_reg_read(device,
00656                     AD7606_REG_BANDWIDTH,
00657                     &read_val) == SUCCESS) {
00658             if (bw_value) {
00659                 read_val |= (1 << (channel->ch_num));
00660             } else {
00661                 read_val &= (~(1 << (channel->ch_num)));
00662             }
00663 
00664             if (ad7606_spi_reg_write(device,
00665                          AD7606_REG_BANDWIDTH,
00666                          read_val) == SUCCESS) {
00667                 return len;
00668             }
00669         }
00670     }
00671 
00672     return -EINVAL;
00673 }
00674 
00675 
00676 /*!
00677  * @brief   Getter/Setter for the channel range attribute value
00678  * @param   device- pointer to IIO device structure
00679  * @param   buf- pointer to buffer holding attribute value
00680  * @param   len- length of buffer string data
00681  * @param   channel- pointer to IIO channel structure
00682  * @return  Number of characters read/written
00683  * @note    Available only for AD7606B and AD7606C
00684  */
00685 static ssize_t get_chn_range(void *device,
00686                  char *buf,
00687                  size_t len,
00688                  const struct iio_ch_info *channel,
00689                  intptr_t id)
00690 {
00691     uint8_t read_val;
00692     uint8_t chn_range;
00693 
00694     if (ad7606_spi_reg_read(device, AD7606_REG_RANGE_CH_ADDR(channel->ch_num),
00695                 &read_val) == SUCCESS) {
00696         if (((channel->ch_num) % 2) != 0) {
00697             read_val >>= CHANNEL_RANGE_MSK_OFFSET;
00698             chn_range = read_val;
00699         } else {
00700             chn_range = (read_val & AD7606_RANGE_CH_MSK(channel->ch_num));
00701         }
00702 
00703         if (chn_range < sizeof(chn_range_str) / sizeof(chn_range_str[0])) {
00704             attr_chn_range[channel->ch_num] = chn_range_val[chn_range];
00705             attr_polarity_val[channel->ch_num] = ad7606_get_input_polarity(chn_range);
00706 
00707             return (ssize_t)sprintf(buf, "%s", chn_range_str[chn_range]);
00708         }
00709     }
00710 
00711     return -EINVAL;
00712 }
00713 
00714 static ssize_t set_chn_range(void *device,
00715                  char *buf,
00716                  size_t len,
00717                  const struct iio_ch_info *channel,
00718                  intptr_t id)
00719 {
00720     uint8_t chn_range;
00721 
00722     (void)sscanf(buf, "%d", &chn_range);
00723 
00724     if (chn_range < sizeof(chn_range_val) / sizeof(chn_range_val[0])) {
00725 
00726         /* Get the polarity of channel */
00727         attr_polarity_val[channel->ch_num] = ad7606_get_input_polarity(chn_range);
00728 
00729         attr_chn_range[channel->ch_num] = chn_range_val[chn_range];
00730         attr_scale_val[channel->ch_num] = get_vltg_conv_scale_factor(
00731                 chn_range_val[chn_range],
00732                 attr_polarity_val[channel->ch_num]);
00733 
00734         if (((channel->ch_num) % 2) != 0) {
00735             chn_range <<= CHANNEL_RANGE_MSK_OFFSET;
00736         }
00737 
00738         if (ad7606_spi_write_mask(device,
00739                       AD7606_REG_RANGE_CH_ADDR(channel->ch_num),
00740                       AD7606_RANGE_CH_MSK(channel->ch_num),
00741                       chn_range) == SUCCESS) {
00742             return len;
00743         }
00744     }
00745 
00746     return -EINVAL;
00747 }
00748 
00749 
00750 /*!
00751  * @brief   Getter/Setter for the channel offset attribute value
00752  * @param   device- pointer to IIO device structure
00753  * @param   buf- pointer to buffer holding attribute value
00754  * @param   len- length of buffer string data
00755  * @param   channel- pointer to IIO channel structure
00756  * @return  Number of characters read/written
00757  * @note    Available only for AD7606B and AD7606C
00758  */
00759 static ssize_t get_chn_offset(void *device,
00760                   char *buf,
00761                   size_t len,
00762                   const struct iio_ch_info *channel,
00763                   intptr_t id)
00764 {
00765     uint8_t chn_offset_value;
00766 
00767     if (ad7606_spi_reg_read(device, AD7606_REG_OFFSET_CH(channel->ch_num),
00768                 &chn_offset_value) == SUCCESS) {
00769         return (ssize_t)sprintf(buf, "%d", chn_offset_value);
00770     }
00771 
00772     return -EINVAL;
00773 }
00774 
00775 static ssize_t set_chn_offset(void *device,
00776                   char *buf,
00777                   size_t len,
00778                   const struct iio_ch_info *channel,
00779                   intptr_t id)
00780 {
00781     uint8_t chn_offset_value = 0;
00782 
00783     (void)sscanf(buf, "%d", &chn_offset_value);
00784 
00785     if (ad7606_set_ch_offset(device, channel->ch_num,
00786                  chn_offset_value) == SUCCESS) {
00787         return len;
00788     }
00789 
00790     return -EINVAL;
00791 }
00792 
00793 
00794 /*!
00795  * @brief   Getter/Setter for the channel pahse offset attribute value
00796  * @param   device- pointer to IIO device structure
00797  * @param   buf- pointer to buffer holding attribute value
00798  * @param   len- length of buffer string data
00799  * @param   channel- pointer to IIO channel structure
00800  * @return  Number of characters read/written
00801  * @note    Available only for AD7606B and AD7606C
00802  */
00803 static ssize_t get_chn_phase_offset(void *device,
00804                     char *buf,
00805                     size_t len,
00806                     const struct iio_ch_info *channel,
00807                     intptr_t id)
00808 {
00809     uint8_t chn_phase_offset_value;
00810 
00811     if (ad7606_spi_reg_read(device,
00812                 AD7606_REG_PHASE_CH(channel->ch_num),
00813                 &chn_phase_offset_value) == SUCCESS) {
00814         return (ssize_t)sprintf(buf, "%d", chn_phase_offset_value);
00815     }
00816 
00817     return -EINVAL;
00818 }
00819 
00820 static ssize_t set_chn_phase_offset(void *device,
00821                     char *buf,
00822                     size_t len,
00823                     const struct iio_ch_info *channel,
00824                     intptr_t id)
00825 {
00826     uint8_t chn_phase_offset_value = 0;
00827 
00828     (void)sscanf(buf, "%d", &chn_phase_offset_value);
00829 
00830     if (ad7606_set_ch_phase(device, channel->ch_num,
00831                 chn_phase_offset_value) == SUCCESS) {
00832         return len;
00833     }
00834 
00835     return -EINVAL;
00836 }
00837 
00838 
00839 /*!
00840  * @brief   Getter/Setter for the channel temperature attribute value
00841  * @param   device- pointer to IIO device structure
00842  * @param   buf- pointer to buffer holding attribute value
00843  * @param   len- length of buffer string data
00844  * @param   channel- pointer to IIO channel structure
00845  * @return  Number of characters read/written
00846  * @note    Available only for AD7606B and AD7606C
00847  */
00848 static ssize_t get_chn_temperature(void *device,
00849                    char *buf,
00850                    size_t len,
00851                    const struct iio_ch_info *channel,
00852                    intptr_t id)
00853 {
00854     int32_t adc_data_raw = 0;
00855     float temperature;
00856     float voltage;
00857 
00858     /* Configure the channel multiplexer to select temperature read */
00859     if (ad7606_spi_write_mask(device,
00860                   AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
00861                   AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
00862                   AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
00863                           TEMPERATURE_MUX)) == SUCCESS) {
00864 
00865         /* Allow to settle Mux channel */
00866         udelay(100);
00867 
00868         /* Sample the channel and read conversion result */
00869         read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
00870 
00871         /* Convert ADC data into equivalent voltage */
00872         voltage = convert_adc_raw_to_voltage(adc_data_raw,
00873                              attr_scale_val[channel->ch_num]);
00874 
00875         /* Obtain the temperature using equation specified in device datasheet */
00876         temperature = ((voltage - 0.69068) / 0.019328) + 25.0;
00877 
00878         /* Change channel mux back to analog input */
00879         (void)ad7606_spi_write_mask(device,
00880                         AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
00881                         AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
00882                         AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
00883                                 ANALOG_INPUT_MUX));
00884 
00885         return (ssize_t)sprintf(buf, "%f", temperature);
00886     }
00887 
00888     return -EINVAL;
00889 }
00890 
00891 static ssize_t set_chn_temperature(void *device,
00892                    char *buf,
00893                    size_t len,
00894                    const struct iio_ch_info *channel,
00895                    intptr_t id)
00896 {
00897     // NA- Can't set temperature
00898     return -EINVAL;
00899 }
00900 
00901 
00902 /*!
00903  * @brief   Getter/Setter for the channel Vref attribute value
00904  * @param   device- pointer to IIO device structure
00905  * @param   buf- pointer to buffer holding attribute value
00906  * @param   len- length of buffer string data
00907  * @param   channel- pointer to IIO channel structure
00908  * @return  Number of characters read/written
00909  * @note    Available only for AD7606B and AD7606C
00910  */
00911 static ssize_t get_chn_vref(void *device,
00912                 char *buf,
00913                 size_t len,
00914                 const struct iio_ch_info *channel,
00915                 intptr_t id)
00916 {
00917     float vref_voltge;
00918     int32_t adc_data_raw;
00919 
00920     /* Configure the channel multiplexer to select Vref read */
00921     if (ad7606_spi_write_mask(device,
00922                   AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
00923                   AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
00924                   AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
00925                           VREF_MUX)) == SUCCESS) {
00926 
00927         /* Allow to settle Mux channel */
00928         udelay(100);
00929 
00930         /* Sample the channel and read conversion result */
00931         read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
00932 
00933         /* Convert ADC data into equivalent voltage */
00934         vref_voltge = convert_adc_raw_to_voltage(adc_data_raw,
00935                 attr_scale_val[channel->ch_num]);
00936 
00937         /* Divide by 4 since Vref Mux has 4x multiplier on it */
00938         vref_voltge /= VREF_MUX_MULTIPLIER;
00939 
00940         /* Change channel mux back to analog input */
00941         (void)ad7606_spi_write_mask(device,
00942                         AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
00943                         AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
00944                         AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
00945                                 ANALOG_INPUT_MUX));
00946 
00947         return (ssize_t)sprintf(buf, "%f", vref_voltge);
00948     }
00949 
00950     return -EINVAL;
00951 }
00952 
00953 static ssize_t set_chn_vref(void *device,
00954                 char *buf,
00955                 size_t len,
00956                 const struct iio_ch_info *channel,
00957                 intptr_t id)
00958 {
00959     // NA- Can't set Vref
00960     return - EINVAL;
00961 }
00962 
00963 
00964 /*!
00965  * @brief   Getter/Setter for the channel Vdrive attribute value
00966  * @param   device- pointer to IIO device structure
00967  * @param   buf- pointer to buffer holding attribute value
00968  * @param   len- length of buffer string data
00969  * @param   channel- pointer to IIO channel structure
00970  * @return  Number of characters read/written
00971  * @note    Available only for AD7606B and AD7606C
00972  */
00973 static ssize_t get_chn_vdrive(void *device,
00974                   char *buf,
00975                   size_t len,
00976                   const struct iio_ch_info *channel,
00977                   intptr_t id)
00978 {
00979     float vdrive_voltge;
00980     int32_t adc_data_raw;
00981 
00982     /* Configure the channel multiplexer to select Vdrive read */
00983     if (ad7606_spi_write_mask(device,
00984                   AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
00985                   AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
00986                   AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
00987                           VDRIVE_MUX)) == SUCCESS) {
00988 
00989         /* Allow to settle Mux channel */
00990         udelay(100);
00991 
00992         /* Sample the channel and read conversion result */
00993         read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
00994 
00995         /* Convert ADC data into equivalent voltage */
00996         vdrive_voltge = convert_adc_raw_to_voltage(adc_data_raw,
00997                 attr_scale_val[channel->ch_num]);
00998 
00999         /* Change channel mux back to analog input */
01000         (void)ad7606_spi_write_mask(device,
01001                         AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
01002                         AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
01003                         AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
01004                                 ANALOG_INPUT_MUX));
01005 
01006         return (ssize_t)sprintf(buf, "%f", vdrive_voltge);
01007     }
01008 
01009     return -EINVAL;
01010 }
01011 
01012 static ssize_t set_chn_vdrive(void *device,
01013                   char *buf,
01014                   size_t len,
01015                   const struct iio_ch_info *channel,
01016                   intptr_t id)
01017 {
01018     // NA- Can't set Vdrive
01019     return - EINVAL;
01020 }
01021 
01022 
01023 /*!
01024  * @brief   Getter/Setter for the channel ALDO attribute value
01025  * @param   device- pointer to IIO device structure
01026  * @param   buf- pointer to buffer holding attribute value
01027  * @param   len- length of buffer string data
01028  * @param   channel- pointer to IIO channel structure
01029  * @return  Number of characters read/written
01030  * @note    Available only for AD7606B and AD7606C
01031  */
01032 static ssize_t get_chn_aldo(void *device,
01033                 char *buf,
01034                 size_t len,
01035                 const struct iio_ch_info *channel,
01036                 intptr_t id)
01037 {
01038     float aldo_voltge;
01039     int32_t adc_data_raw;
01040 
01041     /* Configure the channel multiplexer to select ALDO read */
01042     if (ad7606_spi_write_mask(device,
01043                   AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
01044                   AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
01045                   AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
01046                           ALDO_MUX)) == SUCCESS) {
01047 
01048         /* Allow to settle Mux channel */
01049         udelay(100);
01050 
01051         /* Sample the channel and read conversion result */
01052         read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
01053 
01054         /* Convert ADC data into equivalent voltage */
01055         aldo_voltge = convert_adc_raw_to_voltage(adc_data_raw,
01056                 attr_scale_val[channel->ch_num]);
01057 
01058         /* Divide by 4 since ALDO Mux has 4x multiplier on it */
01059         aldo_voltge /= VREF_MUX_MULTIPLIER;
01060 
01061         /* Change channel mux back to analog input */
01062         (void)ad7606_spi_write_mask(device,
01063                         AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
01064                         AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
01065                         AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
01066                                 ANALOG_INPUT_MUX));
01067 
01068         return (ssize_t)sprintf(buf, "%f", aldo_voltge);
01069     }
01070 
01071     return -EINVAL;
01072 }
01073 
01074 static ssize_t set_chn_aldo(void *device,
01075                 char *buf,
01076                 size_t len,
01077                 const struct iio_ch_info *channel,
01078                 intptr_t id)
01079 {
01080     // NA- Can't set ALDO
01081     return - EINVAL;
01082 }
01083 
01084 
01085 /*!
01086  * @brief   Getter/Setter for the channel DLDO attribute value
01087  * @param   device- pointer to IIO device structure
01088  * @param   buf- pointer to buffer holding attribute value
01089  * @param   len- length of buffer string data
01090  * @param   channel- pointer to IIO channel structure
01091  * @return  Number of characters read/written
01092  * @note    Available only for AD7606B and AD7606C
01093  */
01094 static ssize_t get_chn_dldo(void *device,
01095                 char *buf,
01096                 size_t len,
01097                 const struct iio_ch_info *channel,
01098                 intptr_t id)
01099 {
01100     float dldo_voltge;
01101     int32_t adc_data_raw;
01102 
01103     /* Configure the channel multiplexer to select DLDO read */
01104     if (ad7606_spi_write_mask(device,
01105                   AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
01106                   AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
01107                   AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
01108                           DLDO_MUX)) == SUCCESS) {
01109 
01110         /* Allow to settle Mux channel */
01111         udelay(100);
01112 
01113         /* Sample the channel and read conversion result */
01114         read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
01115 
01116         /* Convert ADC data into equivalent voltage */
01117         dldo_voltge = convert_adc_raw_to_voltage(adc_data_raw,
01118                 attr_scale_val[channel->ch_num]);
01119 
01120         /* Divide by 4 since ALDO Mux has 4x multiplier on it */
01121         dldo_voltge /= VREF_MUX_MULTIPLIER;
01122 
01123         /* Change channel mux back to analog input */
01124         (void)ad7606_spi_write_mask(device,
01125                         AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num),
01126                         AD7606_DIAGN_MUX_CH_MSK(channel->ch_num),
01127                         AD7606_DIAGN_MUX_CH_VAL((channel->ch_num),
01128                                 ANALOG_INPUT_MUX));
01129 
01130         return (ssize_t)sprintf(buf, "%f", dldo_voltge);
01131     }
01132 
01133     return -EINVAL;
01134 }
01135 
01136 static ssize_t set_chn_dldo(void *device,
01137                 char *buf,
01138                 size_t len,
01139                 const struct iio_ch_info *channel,
01140                 intptr_t id)
01141 {
01142     // NA- Can't set DLDO
01143     return - EINVAL;
01144 }
01145 
01146 
01147 /*!
01148  * @brief   Getter/Setter for the channel open circuit detect manual attribute value
01149  * @param   device- pointer to IIO device structure
01150  * @param   buf- pointer to buffer holding attribute value
01151  * @param   len- length of buffer string data
01152  * @param   channel- pointer to IIO channel structure
01153  * @return  Number of characters read/written
01154  */
01155 static ssize_t get_chn_open_circuit_detect_manual(void *device,
01156         char *buf,
01157         size_t len,
01158         const struct iio_ch_info *channel,
01159         intptr_t id)
01160 {
01161     int32_t prev_adc_code, curr_adc_code;
01162     bool open_detect_flag = false;
01163     bool open_detect_done = false;
01164     uint8_t cnt;
01165 
01166     /* Enter into manual open circuit detection mode */
01167     do {
01168         if (ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 1) == SUCCESS) {
01169             /* Read the ADC on selected chnnel (first reading post open circuit detection start) */
01170             read_single_sample(channel->ch_num, (uint32_t *)&prev_adc_code);
01171 
01172             /* Perform N conversions and monitor the code delta */
01173             for (cnt = 0; cnt < MANUAL_OPEN_DETECT_CONV_CNTS; cnt++) {
01174                 /* Check if code is within 350LSB (nearest ZS code) */
01175                 if (prev_adc_code >= 0 && prev_adc_code < MANUAL_OPEN_DETECT_ENTRY_TRHLD) {
01176                     /* Perform next conversion and read the result */
01177                     read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code);
01178 
01179                     /* Check if delta b/w current and previus reading is within 10 LSB code */
01180                     if (abs(curr_adc_code - prev_adc_code) > MANUAL_OPEN_DETECT_CONV_TRSHLD) {
01181                         open_detect_done = true;
01182                         break;
01183                     }
01184 
01185                     /* Get the previous code */
01186                     prev_adc_code = curr_adc_code;
01187                 } else {
01188                     open_detect_done = true;
01189                     break;
01190                 }
01191             }
01192 
01193             /* Break if open circuit detection aborted (in case above conditions not met) */
01194             if (open_detect_done)
01195                 break;
01196 
01197             /* Set common mode high (enabling open circuit detect on selected channel) */
01198             if (ad7606_spi_reg_write(device,
01199                          AD7606_REG_OPEN_DETECT_ENABLE,
01200                          (1 << (channel->ch_num))) == SUCCESS) {
01201 
01202                 /* Perform next conversions (~2-3) and read the result (with common mode set high) */
01203                 for (cnt = 0; cnt < MANUAL_OPEN_DETECT_CM_CNV_CNT; cnt++) {
01204                     udelay(100);
01205                     read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code);
01206                 }
01207 
01208                 /* Check if delta b/w common mode high code and previous N conversion code is > threshold */
01209                 if ((curr_adc_code - prev_adc_code) < MANUAL_OPEN_DETECT_THRESHOLD_RPD50K) {
01210                     open_detect_done = true;
01211                     break;
01212                 }
01213             } else {
01214                 return -EINVAL;
01215             }
01216 
01217             /* Break if open circuit detection aborted (in case above conditions not met) */
01218             if (open_detect_done)
01219                 break;
01220 
01221             /* Set common mode low (disabling open circuit detect on channel) */
01222             if (ad7606_spi_reg_write(device,
01223                          AD7606_REG_OPEN_DETECT_ENABLE,
01224                          0) == SUCCESS) {
01225                 /* Perform next conversion and read the result (with common mode set low) */
01226                 read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code);
01227 
01228                 /* Check if delta b/w common mode low code and previous N conversion code is < threshold */
01229                 if (abs(curr_adc_code - prev_adc_code) < MANUAL_OPEN_DETECT_THRESHOLD_RPD50K) {
01230                     open_detect_flag = true;
01231                     open_detect_done = true;
01232                 }
01233             } else {
01234                 return -EINVAL;
01235             }
01236         } else {
01237             return -EINVAL;
01238         }
01239     } while (0);
01240 
01241     /* Disable open detect mode */
01242     (void)ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 0);
01243 
01244     if (open_detect_done) {
01245         if (open_detect_flag) {
01246             strcpy(buf, "Open Circuit Detected");
01247         } else {
01248             strcpy(buf, "Open Circuit Not Detected");
01249         }
01250 
01251         return len;
01252     }
01253 
01254     return -EINVAL;
01255 }
01256 
01257 static ssize_t set_chn_open_circuit_detect_manual(void *device,
01258         char *buf,
01259         size_t len,
01260         const struct iio_ch_info *channel,
01261         intptr_t id)
01262 {
01263     // NA- Can't set open circuit detect
01264     return - EINVAL;
01265 }
01266 
01267 
01268 /*!
01269  * @brief   Getter/Setter for the channel open circuit detect auto attribute value
01270  * @param   device- pointer to IIO device structure
01271  * @param   buf- pointer to buffer holding attribute value
01272  * @param   len- length of buffer string data
01273  * @param   channel- pointer to IIO channel structure
01274  * @return  Number of characters read/written
01275  */
01276 static ssize_t get_chn_open_circuit_detect_auto(void *device,
01277         char *buf,
01278         size_t len,
01279         const struct iio_ch_info *channel,
01280         intptr_t id)
01281 {
01282     if (open_circuit_detect_read_done) {
01283         open_circuit_detect_read_done = false;
01284 
01285         if (open_circuit_detection_error) {
01286             strcpy(buf, "Error!!");
01287         }
01288 
01289         if (open_circuit_detection_done) {
01290             strcpy(buf, "Open Circuit Detected");
01291         } else {
01292             strcpy(buf, "Open Circuit Not Detected");
01293         }
01294 
01295         return len;
01296     }
01297 
01298     return (ssize_t)sprintf(buf, "OPEN_DETECT_QUEUE: %d",
01299                 open_detect_queue_cnts[channel->ch_num]);
01300 }
01301 
01302 static ssize_t set_chn_open_circuit_detect_auto(void *device,
01303         char *buf,
01304         size_t len,
01305         const struct iio_ch_info *channel,
01306         intptr_t id)
01307 {
01308     uint8_t data;
01309     uint8_t open_detect_flag = false;
01310     int32_t rw_status = FAILURE;
01311     uint16_t conv_cnts;
01312 
01313     (void)sscanf(buf, "%d", &data);
01314     open_circuit_detection_error = false;
01315 
01316     if ((data > 1 && data <= AUTO_OPEN_DETECT_QUEUE_MAX_CNT) && (buf[0] >= '0'
01317             && buf[0] <= '9')) {
01318         open_detect_queue_cnts[channel->ch_num] = data;
01319 
01320         /* Enter into open circuit auto open detect mode */
01321         if (ad7606_spi_reg_write(device,
01322                      AD7606_REG_OPEN_DETECT_QUEUE,
01323                      open_detect_queue_cnts[channel->ch_num]) == SUCCESS) {
01324             /* Enable open circuit detection on selected channel */
01325             if (ad7606_spi_reg_write(device,
01326                          AD7606_REG_OPEN_DETECT_ENABLE,
01327                          (1 << (channel->ch_num))) == SUCCESS) {
01328                 /* Monitor the open detect flag for max N+15 (open detect queue count) conversions.
01329                  * Note: In ideal scenario, the open detect flash should be monitored continuously while
01330                  * background N conversions are in progress */
01331                 for (conv_cnts = 0;
01332                      conv_cnts < (open_detect_queue_cnts[channel->ch_num] +
01333                           AUTO_OPEN_DETECT_QUEUE_EXTRA_CONV_CNT);
01334                      conv_cnts++) {
01335                     if (ad7606_convst(device) == SUCCESS) {
01336                         udelay(100);
01337 
01338                         /* Monitor the open detect flag */
01339                         if (ad7606_spi_reg_read(device,
01340                                     AD7606_REG_OPEN_DETECTED,
01341                                     &open_detect_flag) == SUCCESS) {
01342                             open_detect_flag >>= (channel->ch_num);
01343                             open_detect_flag &= 0x1;
01344 
01345                             rw_status = SUCCESS;
01346                             if (open_detect_flag) {
01347                                 break;
01348                             }
01349                         } else {
01350                             rw_status = FAILURE;
01351                             break;
01352                         }
01353                     } else {
01354                         rw_status = FAILURE;
01355                         break;
01356                     }
01357                 }
01358             }
01359         }
01360 
01361         /* Disable open detect mode and clear open detect flag */
01362         (void)ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 0);
01363         (void)ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECTED, 0xFF);
01364 
01365         open_detect_queue_cnts[channel->ch_num] = 0;
01366 
01367         if (rw_status == SUCCESS) {
01368             if (open_detect_flag) {
01369                 open_circuit_detection_done = true;
01370             } else {
01371                 open_circuit_detection_done = false;
01372             }
01373 
01374             open_circuit_detect_read_done = true;
01375             return len;
01376         }
01377     }
01378 
01379     open_circuit_detection_error = true;
01380     return -EINVAL;
01381 }
01382 
01383 
01384 /*!
01385  * @brief   Getter/Setter for the adc offset calibration
01386  * @param   device- pointer to IIO device structure
01387  * @param   buf- pointer to buffer holding attribute value
01388  * @param   len- length of buffer string data
01389  * @param   channel- pointer to IIO channel structure
01390  * @return  Number of characters read/written
01391  */
01392 static ssize_t get_chn_calibrate_adc_offset(void *device,
01393         char *buf,
01394         size_t len,
01395         const struct iio_ch_info *channel,
01396         intptr_t id)
01397 {
01398     float lsb_voltage;
01399     float adc_voltage;
01400     polarity_e polarity = attr_polarity_val[channel->ch_num];
01401     int32_t adc_raw_data;
01402     int8_t chn_offset;
01403 
01404     /* Perform the system offset calibration */
01405 
01406     if (polarity == UNIPOLAR) {
01407         lsb_voltage = attr_chn_range[channel->ch_num] / ADC_MAX_COUNT_UNIPOLAR;
01408     } else {
01409         lsb_voltage = attr_chn_range[channel->ch_num] / ADC_MAX_COUNT_BIPOLAR;
01410     }
01411 
01412     /* Sample and read the ADC channel */
01413     read_single_sample(channel->ch_num, (uint32_t *)&adc_raw_data);
01414 
01415     /* Get an equivalent ADC voltage */
01416     adc_voltage = convert_adc_raw_to_voltage(adc_raw_data,
01417             attr_scale_val[channel->ch_num]);
01418 
01419     /* Calculate the channel offset and write it to offset register */
01420     chn_offset = -(adc_voltage / lsb_voltage / OFFSET_REG_RESOLUTION);
01421 
01422     if (ad7606_set_ch_offset(device, channel->ch_num,
01423                  chn_offset) == SUCCESS) {
01424         return sprintf(buf, "%s", "ADC Calibration Done");
01425     }
01426 
01427     return -EINVAL;
01428 }
01429 
01430 static ssize_t set_chn_calibrate_adc_offset(void *device,
01431         char *buf,
01432         size_t len,
01433         const struct iio_ch_info *channel,
01434         intptr_t id)
01435 {
01436     // NA- Can't set open circuit detect
01437     return - EINVAL;
01438 }
01439 
01440 
01441 /*!
01442  * @brief   Getter/Setter for the adc gain calibration
01443  * @param   device- pointer to IIO device structure
01444  * @param   buf- pointer to buffer holding attribute value
01445  * @param   len- length of buffer string data
01446  * @param   channel- pointer to IIO channel structure
01447  * @return  Number of characters read/written
01448  */
01449 static ssize_t get_chn_calibrate_adc_gain(void *device,
01450         char *buf,
01451         size_t len,
01452         const struct iio_ch_info *channel,
01453         intptr_t id)
01454 {
01455     uint8_t read_val;
01456 
01457     if (gain_calibration_done) {
01458         /* Get calibration status for previous gain value write event */
01459         gain_calibration_done = false;
01460         return sprintf(buf, "Calibration Done (Rfilter=%d K)",
01461                    gain_calibration_reg_val[channel->ch_num]);
01462     }
01463 
01464     /* Return gain value when normal read event is triggered */
01465     if (ad7606_spi_reg_read(device,
01466                 AD7606_REG_GAIN_CH(channel->ch_num),
01467                 &read_val) == SUCCESS) {
01468         gain_calibration_reg_val[channel->ch_num] = (read_val & AD7606_GAIN_MSK);
01469         return sprintf(buf, "Rfilter= %d K",
01470                    gain_calibration_reg_val[channel->ch_num]);
01471     }
01472 
01473     return -EINVAL;
01474 }
01475 
01476 static ssize_t set_chn_calibrate_adc_gain(void *device,
01477         char *buf,
01478         size_t len,
01479         const struct iio_ch_info *channel,
01480         intptr_t id)
01481 {
01482     float data;
01483 
01484     if (buf[0] >= '0' && buf[0] <= '9') {
01485         (void)sscanf(buf, "%f", &data);
01486 
01487         if (data >= 0 && data < ADC_CALIBRATION_GAIN_MAX) {
01488             /* Get the nearest value of unsigned integer */
01489             gain_calibration_reg_val[channel->ch_num] = (uint8_t)(round(data));
01490 
01491             /* Perform the gain calibration by writing gain value into gain register */
01492             if (ad7606_set_ch_gain(device,
01493                            channel->ch_num,
01494                            gain_calibration_reg_val[channel->ch_num]) == SUCCESS) {
01495                 gain_calibration_done = true;
01496                 return len;
01497             }
01498         }
01499     }
01500 
01501     return -EINVAL;
01502 }
01503 
01504 
01505 /*!
01506  * @brief   Read the debug register value
01507  * @param   dev- Pointer to IIO device instance
01508  * @param   reg- Register address to read from
01509  * @param   readval- Pointer to variable to read data into
01510  * @return  SUCCESS in case of success, negative value otherwise
01511  */
01512 int32_t debug_reg_read(void *dev, uint32_t reg, uint32_t *readval)
01513 {
01514     /* Read the data from device */
01515     if (reg <= NUM_OF_REGISTERS) {
01516         if ((ad7606_spi_reg_read(dev, reg, (uint8_t *)readval) == SUCCESS)) {
01517             return SUCCESS;
01518         }
01519     }
01520 
01521     return FAILURE;
01522 }
01523 
01524 
01525 /*!
01526  * @brief   Write into the debug register
01527  * @param   dev- Pointer to IIO device instance
01528  * @param   reg- Register address to write into
01529  * @param   writeval- Register value to write
01530  * @return  SUCCESS in case of success, negative value otherwise
01531  */
01532 int32_t debug_reg_write(void *dev, uint32_t reg, uint32_t writeval)
01533 {
01534     if (reg <= NUM_OF_REGISTERS) {
01535         if ((ad7606_spi_reg_write(dev, reg, (uint8_t)writeval) == SUCCESS)) {
01536             save_local_attributes();
01537             return SUCCESS;
01538         }
01539     }
01540 
01541     return FAILURE;
01542 }
01543 
01544 
01545 /**
01546  * @brief   Read buffer data corresponding to AD7606 IIO device
01547  * @param   dev_instance[in] - IIO device instance
01548  * @param   pbuf[out] - Pointer to output data buffer
01549  * @return  SUCCESS in case of success or negative value otherwise
01550  */
01551 static ssize_t iio_ad7606_read_data(void *dev_instance,
01552                     char *pbuf,
01553                     size_t offset,
01554                     size_t bytes_count,
01555                     uint32_t ch_mask)
01556 {
01557     if (adc_data_capture_started == false) {
01558         start_data_capture(ch_mask, AD7606X_ADC_CHANNELS);
01559         adc_data_capture_started = true;
01560     }
01561 
01562     /* Read the buffered data */
01563     return (ssize_t)read_buffered_data(pbuf,
01564                        bytes_count,
01565                        offset,
01566                        ch_mask,
01567                        BYTES_PER_SAMPLE);
01568 }
01569 
01570 
01571 /**
01572  * @brief   Transfer the device data into memory (optional)
01573  * @param   dev_instance[in] - IIO device instance
01574  * @param   bytes_count[in] - Number of bytes to read
01575  * @param   ch_mask[in] - Channels select mask
01576  * @return  SUCCESS in case of success or negative value otherwise
01577  */
01578 static ssize_t iio_ad7606_transfer_dev_data(void *dev_instance,
01579         size_t bytes_count,
01580         uint32_t ch_mask)
01581 {
01582     /* The function insures that data is first read into memory from the device.
01583      * This function doesn't do any sort of data transfer but it make sure data
01584      * read and it's transfer to memory from device is happening in application through
01585      * iio_ad7606_read_data() function */
01586 
01587     /* Store the requested samples count value for data capture */
01588     store_requested_samples_count(bytes_count, BYTES_PER_SAMPLE);
01589 
01590     return SUCCESS;
01591 }
01592 
01593 
01594 /**
01595  * @brief   Perform tasks before new data transfer
01596  * @param   dev_instance[in] - IIO device instance
01597  * @param   ch_mask[in] - Channels select mask
01598  * @return  SUCCESS in case of success or negative value otherwise
01599  */
01600 static int32_t iio_ad7606_start_transfer(void *dev_instance, uint32_t ch_mask)
01601 {
01602     return SUCCESS;
01603 }
01604 
01605 
01606 /**
01607  * @brief   Perform tasks before end of current data transfer
01608  * @param   dev_instance[in] - IIO device instance
01609  * @return  SUCCESS in case of success or negative value otherwise
01610  */
01611 static int32_t iio_ad7606_stop_transfer(void *dev)
01612 {
01613     adc_data_capture_started = false;
01614     stop_data_capture();
01615 
01616     return SUCCESS;
01617 }
01618 
01619 /*********************************************************
01620  *               IIO Attributes and Structures
01621  ********************************************************/
01622 
01623 /* IIOD channels attributes list */
01624 struct iio_attribute channel_input_attributes[] = {
01625     {
01626         .name = "raw",
01627         .show = get_chn_raw,
01628         .store = set_chn_raw,
01629     },
01630     {
01631         .name = "scale",
01632         .show = get_chn_scale,
01633         .store = set_chn_scale,
01634     },
01635 #if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16)
01636     {
01637         .name = "chn_range",
01638         .show = get_chn_range,
01639         .store = set_chn_range,
01640     },
01641     {
01642         .name = "offset",
01643         .show = get_chn_offset,
01644         .store = set_chn_offset,
01645     },
01646     {
01647         .name = "chn_phase offset",
01648         .show = get_chn_phase_offset,
01649         .store = set_chn_phase_offset,
01650     },
01651     {
01652         .name = "temperature",
01653         .show = get_chn_temperature,
01654         .store = set_chn_temperature,
01655     },
01656     {
01657         .name = "vref",
01658         .show = get_chn_vref,
01659         .store = set_chn_vref,
01660     },
01661     {
01662         .name = "vdrive",
01663         .show = get_chn_vdrive,
01664         .store = set_chn_vdrive,
01665     },
01666     {
01667         .name = "ALDO",
01668         .show = get_chn_aldo,
01669         .store = set_chn_aldo,
01670     },
01671     {
01672         .name = "DLDO",
01673         .show = get_chn_dldo,
01674         .store = set_chn_dldo,
01675     },
01676     {
01677         .name = "open_circuit_detect_manual",
01678         .show = get_chn_open_circuit_detect_manual,
01679         .store = set_chn_open_circuit_detect_manual,
01680     },
01681     {
01682         .name = "open_circuit_detect_auto",
01683         .show = get_chn_open_circuit_detect_auto,
01684         .store = set_chn_open_circuit_detect_auto,
01685     },
01686     {
01687         .name = "calibrate_adc_offset",
01688         .show = get_chn_calibrate_adc_offset,
01689         .store = set_chn_calibrate_adc_offset,
01690     },
01691     {
01692         .name = "calibrate_adc_gain",
01693         .show = get_chn_calibrate_adc_gain,
01694         .store = set_chn_calibrate_adc_gain,
01695     },
01696 #if defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16)
01697     {
01698         .name = "bandwidth",
01699         .show = get_bandwidth,
01700         .store = set_bandwidth,
01701     },
01702 #endif
01703 #endif
01704 
01705     END_ATTRIBUTES_ARRAY
01706 };
01707 
01708 /* IIOD device (global) attributes list */
01709 static struct iio_attribute global_attributes[] = {
01710 #if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16)
01711     {
01712         .name = "operating_mode",
01713         .show = get_operating_mode,
01714         .store = set_operating_mode,
01715     },
01716     {
01717         .name = "oversampling_ratio",
01718         .show = get_oversampling,
01719         .store = set_oversampling,
01720     },
01721 #else
01722     {
01723         .name = "power_down_mode",
01724         .show = get_power_down_mode,
01725         .store = set_power_down_mode,
01726     },
01727     {
01728         .name = "dev_range",
01729         .show = get_range,
01730         .store = set_range,
01731     },
01732 #endif
01733     {
01734         .name = "sampling_frequency",
01735         .show = get_sampling_frequency,
01736         .store = set_sampling_frequency,
01737     },
01738 
01739     END_ATTRIBUTES_ARRAY
01740 };
01741 
01742 /* IIOD debug attributes list */
01743 static struct iio_attribute debug_attributes[] = {
01744 #if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16)
01745     {
01746         .name = "direct_reg_access",
01747         .show = NULL,
01748         .store = NULL,
01749     },
01750 #endif
01751 
01752     END_ATTRIBUTES_ARRAY
01753 };
01754 
01755 /* IIOD channels configurations */
01756 struct scan_type chn_scan = {
01757     .sign = 's',
01758     .realbits = CHN_STORAGE_BITS,
01759     .storagebits = CHN_STORAGE_BITS,
01760     .shift = 0,
01761     .is_big_endian = false
01762 };
01763 
01764 static struct iio_channel iio_ad7606_channels[] = {
01765     {
01766         .name = "voltage0",
01767         .ch_type = IIO_VOLTAGE,
01768         .channel = 0,
01769         .scan_index = 0,
01770         .scan_type = &chn_scan,
01771         .attributes = channel_input_attributes,
01772         .ch_out = false,
01773         .indexed = true,
01774     },
01775     {
01776         .name = "voltage1",
01777         .ch_type = IIO_VOLTAGE,
01778         .channel = 1,
01779         .scan_index = 1,
01780         .scan_type = &chn_scan,
01781         .attributes = channel_input_attributes,
01782         .ch_out = false,
01783         .indexed = true
01784     },
01785     {
01786         .name = "voltage2",
01787         .ch_type = IIO_VOLTAGE,
01788         .channel = 2,
01789         .scan_index = 2,
01790         .scan_type = &chn_scan,
01791         .attributes = channel_input_attributes,
01792         .ch_out = false,
01793         .indexed = true
01794     },
01795     {
01796         .name = "voltage3",
01797         .ch_type = IIO_VOLTAGE,
01798         .channel = 3,
01799         .scan_index = 3,
01800         .scan_type = &chn_scan,
01801         .attributes = channel_input_attributes,
01802         .ch_out = false,
01803         .indexed = true
01804     },
01805     {
01806         .name = "voltage4",
01807         .ch_type = IIO_VOLTAGE,
01808         .channel = 4,
01809         .scan_index = 4,
01810         .scan_type = &chn_scan,
01811         .attributes = channel_input_attributes,
01812         .ch_out = false,
01813         .indexed = true
01814     },
01815     {
01816         .name = "voltage5",
01817         .ch_type = IIO_VOLTAGE,
01818         .channel = 5,
01819         .scan_index = 5,
01820         .scan_type = &chn_scan,
01821         .attributes = channel_input_attributes,
01822         .ch_out = false,
01823         .indexed = true
01824     },
01825     {
01826         .name = "voltage6",
01827         .ch_type = IIO_VOLTAGE,
01828         .channel = 6,
01829         .scan_index = 6,
01830         .scan_type = &chn_scan,
01831         .attributes = channel_input_attributes,
01832         .ch_out = false,
01833         .indexed = true
01834     },
01835     {
01836         .name = "voltage7",
01837         .ch_type = IIO_VOLTAGE,
01838         .channel = 7,
01839         .scan_index = 7,
01840         .scan_type = &chn_scan,
01841         .attributes = channel_input_attributes,
01842         .ch_out = false,
01843         .indexed = true
01844     }
01845 };
01846 
01847 
01848 /**
01849  * @brief   Init for reading/writing and parameterization of a
01850  *          ad7606 IIO device
01851  * @param   desc[in,out] - IIO device descriptor
01852  * @param   init[in] - Configuration structure
01853  * @return  SUCCESS in case of success, FAILURE otherwise
01854  */
01855 static int32_t iio_ad7606_init(struct iio_device **desc)
01856 {
01857     struct iio_device *iio_ad7606_inst;
01858 
01859     iio_ad7606_inst = calloc(1, sizeof(struct iio_device));
01860     if (!iio_ad7606_inst) {
01861         return FAILURE;
01862     }
01863 
01864     iio_ad7606_inst->num_ch = sizeof(iio_ad7606_channels) / sizeof(
01865                       iio_ad7606_channels[0]);
01866     iio_ad7606_inst->channels = iio_ad7606_channels;
01867     iio_ad7606_inst->attributes = global_attributes;
01868     iio_ad7606_inst->debug_attributes = debug_attributes;
01869 
01870     iio_ad7606_inst->transfer_dev_to_mem = iio_ad7606_transfer_dev_data;
01871     iio_ad7606_inst->transfer_mem_to_dev = NULL;
01872     iio_ad7606_inst->read_data = iio_ad7606_read_data;
01873     iio_ad7606_inst->write_data = NULL;
01874     iio_ad7606_inst->prepare_transfer = iio_ad7606_start_transfer;
01875     iio_ad7606_inst->end_transfer = iio_ad7606_stop_transfer;
01876     iio_ad7606_inst->debug_reg_read = debug_reg_read;
01877     iio_ad7606_inst->debug_reg_write = debug_reg_write;
01878 
01879     *desc = iio_ad7606_inst;
01880 
01881     return SUCCESS;
01882 }
01883 
01884 
01885 /**
01886  * @brief Release resources allocated for IIO device
01887  * @param desc[in] - IIO device descriptor
01888  * @return SUCCESS in case of success, FAILURE otherwise
01889  */
01890 static int32_t iio_ad7606_remove(struct iio_desc *desc)
01891 {
01892     int32_t status;
01893 
01894     if (!desc) {
01895         return FAILURE;
01896     }
01897 
01898     status = iio_unregister(desc, (char *)dev_name);
01899     if (status != SUCCESS) {
01900         return FAILURE;
01901     }
01902 
01903     return SUCCESS;
01904 }
01905 
01906 
01907 /*!
01908  * @brief   Get scale factor for adc data to voltage conversion for IIO client
01909  * @param   chn_range[in] - Current channel voltage range
01910  * @param   chn_range_bits[in] - Channel range register bits
01911  * @return  scale
01912  * @details This function samples and capture the new data when previous data
01913  *          is transmitted to IIO client
01914  */
01915 static float get_vltg_conv_scale_factor(float chn_range, polarity_e polarity)
01916 {
01917     float scale;
01918 
01919     /* Get the scale factor for voltage conversion from range */
01920     if (polarity == UNIPOLAR) {
01921         scale = (chn_range / ADC_MAX_COUNT_UNIPOLAR) * 1000;
01922     } else {
01923         scale = (chn_range / ADC_MAX_COUNT_BIPOLAR) * 1000;
01924     }
01925 
01926     return scale;
01927 }
01928 
01929 
01930 /**
01931  * @brief   Save local variables
01932  * @return  none
01933  * @details This function saves the local parameters with updated device values
01934  */
01935 static void save_local_attributes(void)
01936 {
01937     char buf[50];
01938     struct iio_ch_info channel;
01939 
01940     for (uint8_t chn = 0; chn < AD7606X_ADC_CHANNELS; chn++) {
01941         channel.ch_num = chn;
01942 
01943         /* Get channel range */
01944         (void)get_chn_range(p_ad7606_dev_inst, buf, 0, &channel, 0);
01945 
01946         /* Get scale */
01947         attr_scale_val[channel.ch_num] = get_vltg_conv_scale_factor(
01948                 attr_chn_range[channel.ch_num],
01949                 attr_polarity_val[channel.ch_num]);
01950     }
01951 }
01952 
01953 
01954 /**
01955  * @brief   Initialize the IIO interface for AD7606 IIO device
01956  * @return  none
01957  * @return  SUCCESS in case of success, FAILURE otherwise
01958  */
01959 int32_t ad7606_iio_initialize(void)
01960 {
01961     int32_t init_status;
01962 
01963     /* IIO device descriptor */
01964     struct iio_device *p_iio_ad7606_dev;
01965 
01966     /**
01967     * IIO interface init parameters
01968     */
01969     struct iio_init_param iio_init_params = {
01970         .phy_type = USE_UART,
01971         {
01972             &uart_init_params
01973         }
01974     };
01975 
01976     /* Initialize AD7606 device and peripheral interface */
01977     init_status = ad7606_init(&p_ad7606_dev_inst, &ad7606_init_str);
01978     if (init_status != SUCCESS) {
01979         return init_status;
01980     }
01981 
01982     /* Initialize the IIO interface */
01983     init_status = iio_init(&p_ad7606_iio_desc, &iio_init_params);
01984     if (init_status != SUCCESS) {
01985         return init_status;
01986     }
01987 
01988     /* Initialize the AD7606 IIO application interface */
01989     init_status = iio_ad7606_init(&p_iio_ad7606_dev);
01990     if (init_status != SUCCESS) {
01991         return init_status;
01992     }
01993 
01994     /* Register AD7606 IIO interface */
01995     init_status = iio_register(p_ad7606_iio_desc,
01996                    p_iio_ad7606_dev,
01997                    (char *)dev_name,
01998                    p_ad7606_dev_inst,
01999                    NULL,
02000                    NULL);
02001     if (init_status != SUCCESS) {
02002         return init_status;
02003     }
02004 
02005     /* Init the system peripherals */
02006     init_status = init_system();
02007     if (init_status != SUCCESS) {
02008         return init_status;
02009     }
02010 
02011     return init_status;
02012 }
02013 
02014 
02015 /**
02016  * @brief   Run the AD7606 IIO event handler
02017  * @return  none
02018  * @details This function monitors the new IIO client event
02019  */
02020 void ad7606_iio_event_handler(void)
02021 {
02022     while (1) {
02023         (void)iio_step(p_ad7606_iio_desc);
02024     }
02025 }