Pratyush Mallick
/
testing
this is testing
Diff: app/src/iio_ad7606.c
- Revision:
- 0:3afcd581558d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/src/iio_ad7606.c Thu Jan 14 18:54:16 2021 +0530 @@ -0,0 +1,1702 @@ +/***************************************************************************//** + * @file iio_ad7606.c + * @brief Implementation of AD7606 IIO application interfaces + * @details This module acts as an interface for AD7606 IIO application +******************************************************************************** + * Copyright (c) 2020 Analog Devices, Inc. + * + * This software is proprietary to Analog Devices, Inc. and its licensors. + * By using this software you agree to the terms of the associated + * Analog Devices Software License Agreement. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include <inttypes.h> +#include <string.h> +#include <errno.h> + +#include "app_config.h" + +#include "tinyiiod.h" +#include "iio_ad7606.h" +#include "iio_ad7606_attr.h" +#include "iio_app.h" +#include "iio_transport.h" + +#include "platform_support.h" +#include "spi_extra.h" +#include "gpio_extra.h" +#include "uart_extra.h" +#include "irq_extra.h" + +#include "ad7606.h" +#include "ad7606_data_capture.h" +#include "ad7606_support.h" +#include "ad7606_user_config.h" + +/******************************************************************************/ +/************************ Macros/Constants ************************************/ +/******************************************************************************/ + +/* ADC data to Voltage conversion scale factor for IIO client */ +#define DEFAULT_SCALE ((DEFAULT_CHN_RANGE / ADC_MAX_COUNT_BIPOLAR) * 1000) + +/* Select open wire detection mode (disable to select auto mode) */ +#define MANUAL_OPEN_DETECT + +/* Open detect threshold @50K Rpd as per datasheet */ +#define OPEN_DETECT_THRESHOLD_RPD50K 15 + +/* Number of conversions to be performed before detecting open wire */ +#define OPEN_DETECT_AUTO_MODE_CNTS 10 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** +* IIO application instance descriptor. +*/ +static struct iio_app_desc *iio_app_desc; + +/** + * Device name. + */ +static const char dev_name[] = ACTIVE_DEVICE_NAME; + +/** + * Pointer to the struct representing the AD7606 IIO device + */ +static struct ad7606_dev *p_ad7606_dev = NULL; + + +/* Device attributes with default values */ + +/* Power down mode values string representation (possible values specified in datasheet) */ +static char *operating_mode_str[] = { + "0 (Normal Mode)", + "1 (Standby Mode)", + "2 (Auto Standby Mode)", + "3 (Shutdown Mode)" +}; + +/* Bandwidth values string */ +static char *bandwidth_str[] = { + "0 (Low)", + "1 (High)" +}; + +/* Channel range values string representation (possible values specified in datasheet) */ +static char *chn_range_str[] = { +#if defined(DEV_AD7606B) + "0 (+/-2.5V SE)", "1 (+/-5.0V SE)", "2 (+/-10.0V SE)", "3 (+/-10.0V SE)", + "4 (+/-10.0V SE)", "5 (+/-10.0V SE)", "6 (+/-10.0V SE)", "7 (+/-10.0V SE)", + "8 (+/-10.0V SE)", "9 (+/-10.0V SE)", "10 (+/-10.0V SE)", "11 (+/-10.0V SE)", +#elif defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) + "0 (+/-2.5V SE)", "1 (+/-5.0V SE)", "2 (+/-6.25V SE)", "3 (+/-10.0V SE)", + "4 (+/-12.5V SE)", "5 (+5.0V SE)", "6 (+10.0V SE)", "7 (+12.5V SE)", + "8 (+/-5.0V DE)", "9 (+/-10.0V DE)", "10 (+/-12.5V DE)", "11 (+/-20.0V DE)" +#elif defined(DEV_AD7609) + "0 (+/-10.0V SE)", "1 (+/-20.0V SE)" +#else + "0 (+/-5.0V SE)", "1 (+/-10.0V SE)" +#endif +}; + +/* Oversampling values string representation (possible values specified in datasheet) */ +static char *oversampling_val_str[] = { + "0 (no oversampling)", "1 (oversampling by 2)", "2 (oversampling by 4)", + "3 (oversampling by 8)", "4 (oversampling by 16)", "5 (oversampling by 32)", + "6 (oversampling by 64)", "7 (oversampling by 128)", "8 (oversampling by 256)" +}; + + +/* Channel range values string representation (possible values specified in datasheet) */ +static float chn_range_val[] = { +#if defined(DEV_AD7606B) + 2.5, 5.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0 +#elif defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) + 2.5, 5.0, 6.25, 10.0, 12.5, 5.0, 10.0, 12.5, 5.0, 10.0, 12.5, 20.0 +#elif defined(DEV_AD7609) + 10.0, 20.0 +#else + 5.0, 10.0 +#endif +}; + +/* Range value per channel */ +static float attr_chn_range[NO_OF_CHANNELS] = { + DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, + DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE +}; + +/* Scale value per channel */ +static float attr_scale_val[NO_OF_CHANNELS] = { + DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, + DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE +}; + +/* Scale value per channel */ +static polarity_e attr_polarity_val[NO_OF_CHANNELS] = { + BIPOLAR, BIPOLAR, BIPOLAR, BIPOLAR, + BIPOLAR, BIPOLAR, BIPOLAR, BIPOLAR +}; + +/* Channel range */ +typedef enum { + LOW, + HIGH +} range_e; + +/* Device register value */ +static uint8_t device_reg_val; + +/* GPIO LED descriptor and init structure */ +static struct gpio_desc *gpio_led; + +/******************************************************************************/ +/************************ Functions Prototypes ********************************/ +/******************************************************************************/ + +static float get_vltg_conv_scale_factor(float chn_range, polarity_e polarity); + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/*! + * @brief Getter/Setter for the scale attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + */ +ssize_t get_chn_scale(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + return (ssize_t) sprintf(buf, "%f", attr_scale_val[channel->ch_num - 1]); +} + +ssize_t set_chn_scale(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + float scale; + + (void)sscanf(buf, "%f", &scale); + + if (scale > 0.0) { + attr_scale_val[channel->ch_num - 1] = scale; + return len; + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the raw attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + */ +ssize_t get_chn_raw(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + int32_t adc_data_raw; + + /* Capture the raw adc data */ + adc_data_raw = single_data_read(device, channel->ch_num - 1, + attr_polarity_val[channel->ch_num - 1]); + + return (ssize_t) sprintf(buf, "%d", adc_data_raw); +} + +ssize_t set_chn_raw(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + /* NA- Can't set raw value */ + return len; +} + + +/*! + * @brief Getter/Setter for the operating mode attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_operating_mode(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t read_val; + uint8_t operating_mode_value; + + if (ad7606_spi_reg_read(device, AD7606_REG_CONFIG, &read_val) == SUCCESS) { + operating_mode_value = (read_val & AD7606_CONFIG_OPERATION_MODE_MSK); + + if (operating_mode_value < sizeof(operating_mode_str) / sizeof( + operating_mode_str[0])) { + return (ssize_t)sprintf(buf, "%s", operating_mode_str[operating_mode_value]); + } + } + + return -EINVAL; +} + +ssize_t set_operating_mode(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t operating_mode_value; + + (void)sscanf(buf, "%d", &operating_mode_value); + + if (operating_mode_value < sizeof(operating_mode_str) / sizeof( + operating_mode_str[0])) { + if (ad7606_spi_write_mask(device, + AD7606_REG_CONFIG, + AD7606_CONFIG_OPERATION_MODE_MSK, + operating_mode_value) == SUCCESS) { + return len; + } + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the power down mode attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available for all devices except AD7606B and AD7606C + */ +ssize_t get_power_down_mode(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t gpio_stby_val; + uint8_t gpio_range_val; + + if (gpio_get_value(((struct ad7606_dev *)device)->gpio_stby_n, + &gpio_stby_val) == SUCCESS) { + if (gpio_get_value(((struct ad7606_dev *)device)->gpio_range, + &gpio_range_val) == SUCCESS) { + + if (gpio_stby_val) { + return sprintf(buf, "%s", operating_mode_str[AD7606_NORMAL]); + } else { + if (gpio_range_val) { + return sprintf(buf, "%s", operating_mode_str[AD7606_STANDBY]); + } else { + return sprintf(buf, "%s", operating_mode_str[AD7606_SHUTDOWN]); + } + } + } + } + + return -EINVAL; +} + +ssize_t set_power_down_mode(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t power_down_mode_value; + static enum ad7606_op_mode prev_power_down_mode = AD7606_NORMAL; + struct ad7606_config dev_config; + + sscanf(buf, "%d", &power_down_mode_value); + + if (power_down_mode_value < (sizeof(operating_mode_str) / sizeof( + operating_mode_str[0]))) { + + dev_config.op_mode = power_down_mode_value; + + switch (power_down_mode_value) { + case AD7606_NORMAL: + if (ad7606_set_config(device, dev_config) == SUCCESS) { + /* Reset the device if previous power down mode was either standby + * or shutdown */ + if (prev_power_down_mode != AD7606_NORMAL) { + + /* Power-up wait time */ + mdelay(1); + + /* Toggle reset pin */ + if (gpio_set_value(((struct ad7606_dev *)device)->gpio_reset, + GPIO_HIGH) == SUCCESS) { + mdelay(1); + + if (gpio_set_value(((struct ad7606_dev *)device)->gpio_reset, + GPIO_LOW) == SUCCESS) { + prev_power_down_mode = AD7606_NORMAL; + return len; + } + } + } + } + break; + + case AD7606_STANDBY: + if (ad7606_set_config(device, dev_config) == SUCCESS) { + prev_power_down_mode = AD7606_STANDBY; + return len; + } + break; + + case AD7606_SHUTDOWN: + if (ad7606_set_config(device, dev_config) == SUCCESS) { + prev_power_down_mode = AD7606_SHUTDOWN; + return len; + } + break; + + default: + break; + } + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the range attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available for all devices except AD7606B and AD7606C + */ +ssize_t get_range(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t gpio_range_val; + struct ad7606_dev *dev = device; + + if (gpio_get_value(dev->gpio_range, &gpio_range_val) == SUCCESS) { + if (gpio_range_val) { + return sprintf(buf, "%s", chn_range_str[HIGH]); + } else { + return sprintf(buf, "%s", chn_range_str[LOW]); + } + } + + return -EINVAL; +} + +ssize_t set_range(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t range_value; + struct ad7606_dev *dev = device; + + (void)sscanf(buf, "%d", &range_value); + + if (range_value < (sizeof(chn_range_str) / sizeof(chn_range_str[0]))) { + if (range_value == LOW) { + if (gpio_set_value(dev->gpio_range, GPIO_LOW) == SUCCESS) { + return len; + } + } else { + if (gpio_set_value(dev->gpio_range, GPIO_HIGH) == SUCCESS) { + return len; + } + } + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the oversampling attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available for all devices except AD7606B and AD7606C + */ +ssize_t get_oversampling(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t oversampling_value; + uint8_t read_val; + uint8_t gpio_osr0_val; + uint8_t gpio_osr1_val; + uint8_t gpio_osr2_val; + struct ad7606_dev *dev = device; + +#if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) + if (ad7606_spi_reg_read(device, + AD7606_REG_OVERSAMPLING, + &read_val) == SUCCESS) { + oversampling_value = (read_val & AD7606_OVERSAMPLING_MSK); + + if (oversampling_value < sizeof(oversampling_val_str) / sizeof( + oversampling_val_str[0])) { + return (ssize_t)sprintf(buf, "%s", oversampling_val_str[oversampling_value]); + } + } +#else + if (gpio_get_value(dev->gpio_os0, &gpio_osr0_val) == SUCCESS) { + if (gpio_get_value(dev->gpio_os1, &gpio_osr1_val) == SUCCESS) { + if (gpio_get_value(dev->gpio_os2, &gpio_osr2_val) == SUCCESS) { + oversampling_value = (gpio_osr2_val << 2) | (gpio_osr1_val << 1) | + gpio_osr0_val; + + if (oversampling_value < (sizeof(oversampling_val_str) / sizeof( + oversampling_val_str[0]))) { + return sprintf(buf, "%s", oversampling_val_str[oversampling_value]); + } + } + } + } +#endif + + return -EINVAL; +} + +ssize_t set_oversampling(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t oversampling_value; + struct ad7606_oversampling oversampling_cfg; + + (void)sscanf(buf, "%d", &oversampling_value); + + if (oversampling_value < (sizeof(oversampling_val_str) / sizeof( + oversampling_val_str[0]))) { + + oversampling_cfg.os_pad = 0; + oversampling_cfg.os_ratio = oversampling_value; + + ad7606_set_oversampling(device, oversampling_cfg); + + return len; + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the bandwidth attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available for only AD7606C + */ +ssize_t get_bandwidth(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t bw_value; + uint8_t read_val; + + if (ad7606_spi_reg_read(device, + AD7606_REG_BANDWIDTH, + &read_val) == SUCCESS) { + bw_value = (read_val >> (channel->ch_num - 1)) & 0x1; + + if (bw_value < sizeof(bandwidth_str) / sizeof( + bandwidth_str[0])) { + return (ssize_t)sprintf(buf, "%s", bandwidth_str[bw_value]); + } + } + + return -EINVAL; +} + +ssize_t set_bandwidth(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t bw_value; + uint8_t read_val; + + (void)sscanf(buf, "%d", &bw_value); + + if (bw_value < sizeof(bandwidth_str) / sizeof( + bandwidth_str[0])) { + if (ad7606_spi_reg_read(device, + AD7606_REG_BANDWIDTH, + &read_val) == SUCCESS) { + if (bw_value) { + read_val |= (1 << (channel->ch_num - 1)); + } else { + read_val &= (~(1 << (channel->ch_num - 1))); + } + + if (ad7606_spi_reg_write(device, + AD7606_REG_BANDWIDTH, + read_val) == SUCCESS) { + return len; + } + } + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel range attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_range(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t read_val; + uint8_t chn_range; + + if (ad7606_spi_reg_read(device, AD7606_REG_RANGE_CH_ADDR(channel->ch_num-1), + &read_val) == SUCCESS) { + if (((channel->ch_num - 1) % 2) != 0) { + read_val >>= CHANNEL_RANGE_MSK_OFFSET; + chn_range = read_val; + } else { + chn_range = (read_val & AD7606_RANGE_CH_MSK(channel->ch_num - 1)); + } + + if (chn_range < sizeof(chn_range_str) / sizeof(chn_range_str[0])) { + return (ssize_t)sprintf(buf, "%s", chn_range_str[chn_range]); + } + } + + return -EINVAL; +} + +ssize_t set_chn_range(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t chn_range; + + (void)sscanf(buf, "%d", &chn_range); + + if (chn_range < sizeof(chn_range_val) / sizeof(chn_range_val[0])) { + + /* Get the polarity of channel */ + attr_polarity_val[channel->ch_num - 1] = ad7606_get_input_polarity(chn_range); + + attr_chn_range[channel->ch_num - 1] = chn_range_val[chn_range]; + attr_scale_val[channel->ch_num - 1] = get_vltg_conv_scale_factor( + chn_range_val[chn_range], + attr_polarity_val[channel->ch_num - 1]); + + if (((channel->ch_num - 1) % 2) != 0) { + chn_range <<= CHANNEL_RANGE_MSK_OFFSET; + } + + if (ad7606_spi_write_mask(device, + AD7606_REG_RANGE_CH_ADDR(channel->ch_num-1), + AD7606_RANGE_CH_MSK(channel->ch_num-1), + chn_range) == SUCCESS) { + return len; + } + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel gain attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_gain(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t read_val; + uint8_t chn_gain_value; + + if (ad7606_spi_reg_read(device, + AD7606_REG_GAIN_CH(channel->ch_num - 1), + &read_val) == SUCCESS) { + chn_gain_value = (read_val & AD7606_GAIN_MSK); + return (ssize_t)sprintf(buf, "%d", chn_gain_value); + } + + return -EINVAL; +} + +ssize_t set_chn_gain(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t chn_gain_value; + + (void)sscanf(buf, "%d", &chn_gain_value); + + if (ad7606_set_ch_gain(device, channel->ch_num - 1, + chn_gain_value) == SUCCESS) { + return len; + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel offset attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_offset(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t chn_offset_value; + + if (ad7606_spi_reg_read(device, AD7606_REG_OFFSET_CH(channel->ch_num-1), + &chn_offset_value) == SUCCESS) { + return (ssize_t)sprintf(buf, "%d", chn_offset_value); + } + + return -EINVAL; +} + +ssize_t set_chn_offset(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t chn_offset_value = 0; + + (void)sscanf(buf, "%d", &chn_offset_value); + + if (ad7606_set_ch_offset(device, channel->ch_num - 1, + chn_offset_value) == SUCCESS) { + return len; + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel pahse offset attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_phase_offset(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t chn_phase_offset_value; + + if (ad7606_spi_reg_read(device, + AD7606_REG_PHASE_CH(channel->ch_num - 1), + &chn_phase_offset_value) == SUCCESS) { + return (ssize_t)sprintf(buf, "%d", chn_phase_offset_value); + } + + return -EINVAL; +} + +ssize_t set_chn_phase_offset(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t chn_phase_offset_value = 0; + + (void)sscanf(buf, "%d", &chn_phase_offset_value); + + if (ad7606_set_ch_phase(device, channel->ch_num - 1, + chn_phase_offset_value) == SUCCESS) { + return len; + } + + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel temperature attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_temperature(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + int32_t adc_chn_data = 0; + float temperature; + float voltage; + + /* Configure the channel multiplexer to select temperature read */ + if (ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + TEMPERATURE_MUX)) == SUCCESS) { + + /* Allow to settle Mux channel */ + udelay(100); + + /* Sample the channel and read conversion result */ + adc_chn_data = single_data_read(device, channel->ch_num - 1, + attr_polarity_val[channel->ch_num - 1]); + + /* Convert ADC data into equivalent voltage */ + voltage = convert_adc_raw_to_voltage(adc_chn_data, + attr_scale_val[channel->ch_num - 1]); + + /* Obtain the temperature using equation specified in device datasheet */ + temperature = ((voltage - 0.69068) / 0.019328) + 25.0; + + /* Change channel mux back to analog input */ + (void)ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + ANALOG_INPUT_MUX)); + + return (ssize_t)sprintf(buf, "%f", temperature); + } + + return -EINVAL; +} + +ssize_t set_chn_temperature(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + // NA- Can't set temperature + return -EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel Vref attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_vref(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + float vref_voltge; + int32_t adc_chn_data; + + /* Configure the channel multiplexer to select Vref read */ + if (ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + VREF_MUX)) == SUCCESS) { + + /* Allow to settle Mux channel */ + udelay(100); + + /* Sample the channel and read conversion result */ + adc_chn_data = single_data_read(device, channel->ch_num - 1, + attr_polarity_val[channel->ch_num - 1]); + + /* Convert ADC data into equivalent voltage */ + vref_voltge = convert_adc_raw_to_voltage(adc_chn_data, + attr_scale_val[channel->ch_num - 1]); + + /* Divide by 4 since Vref Mux has 4x multiplier on it */ + vref_voltge /= VREF_MUX_MULTIPLIER; + + /* Change channel mux back to analog input */ + (void)ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + ANALOG_INPUT_MUX)); + + return (ssize_t)sprintf(buf, "%f", vref_voltge); + } + + return -EINVAL; +} + +ssize_t set_chn_vref(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + // NA- Can't set Vref + return - EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel Vdrive attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_vdrive(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + float vdrive_voltge; + int32_t adc_chn_data; + + /* Configure the channel multiplexer to select Vdrive read */ + if (ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + VDRIVE_MUX)) == SUCCESS) { + + /* Allow to settle Mux channel */ + udelay(100); + + /* Sample the channel and read conversion result */ + adc_chn_data = single_data_read(device, channel->ch_num - 1, + attr_polarity_val[channel->ch_num - 1]); + + /* Convert ADC data into equivalent voltage */ + vdrive_voltge = convert_adc_raw_to_voltage(adc_chn_data, + attr_scale_val[channel->ch_num - 1]); + + /* Change channel mux back to analog input */ + (void)ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + ANALOG_INPUT_MUX)); + + return (ssize_t)sprintf(buf, "%f", vdrive_voltge); + } + + return -EINVAL; +} + +ssize_t set_chn_vdrive(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + // NA- Can't set Vdrive + return - EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel ALDO attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_aldo(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + float aldo_voltge; + int32_t adc_chn_data; + + /* Configure the channel multiplexer to select ALDO read */ + if (ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + ALDO_MUX)) == SUCCESS) { + + /* Allow to settle Mux channel */ + udelay(100); + + /* Sample the channel and read conversion result */ + adc_chn_data = single_data_read(device, channel->ch_num - 1, + attr_polarity_val[channel->ch_num - 1]); + + /* Convert ADC data into equivalent voltage */ + aldo_voltge = convert_adc_raw_to_voltage(adc_chn_data, + attr_scale_val[channel->ch_num - 1]); + + /* Divide by 4 since ALDO Mux has 4x multiplier on it */ + aldo_voltge /= VREF_MUX_MULTIPLIER; + + /* Change channel mux back to analog input */ + (void)ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + ANALOG_INPUT_MUX)); + + return (ssize_t)sprintf(buf, "%f", aldo_voltge); + } + + return -EINVAL; +} + +ssize_t set_chn_aldo(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + // NA- Can't set ALDO + return - EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel DLDO attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + * @note Available only for AD7606B and AD7606C + */ +ssize_t get_chn_dldo(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + float dldo_voltge; + int32_t adc_chn_data; + + /* Configure the channel multiplexer to select DLDO read */ + if (ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + DLDO_MUX)) == SUCCESS) { + + /* Allow to settle Mux channel */ + udelay(100); + + /* Sample the channel and read conversion result */ + adc_chn_data = single_data_read(device, + channel->ch_num - 1, + attr_polarity_val[channel->ch_num - 1]); + + /* Convert ADC data into equivalent voltage */ + dldo_voltge = convert_adc_raw_to_voltage(adc_chn_data, + attr_scale_val[channel->ch_num - 1]); + + /* Divide by 4 since ALDO Mux has 4x multiplier on it */ + dldo_voltge /= VREF_MUX_MULTIPLIER; + + /* Change channel mux back to analog input */ + (void)ad7606_spi_write_mask(device, + AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_MSK(channel->ch_num - 1), + AD7606_DIAGN_MUX_CH_VAL((channel->ch_num - 1), + ANALOG_INPUT_MUX)); + + return (ssize_t)sprintf(buf, "%f", dldo_voltge); + } + + return -EINVAL; +} + +ssize_t set_chn_dldo(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + // NA- Can't set DLDO + return - EINVAL; +} + + +/*! + * @brief Getter/Setter for the channel open wire detect attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + */ +ssize_t get_chn_open_wire_detect(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + int32_t data[2]; + uint8_t open_detect_flag = false; + int32_t rw_status = FAILURE; + +#if defined MANUAL_OPEN_DETECT + /* Read the ADC output voltage on channel */ + data[0] = single_data_read(device, channel->ch_num - 1, + attr_polarity_val[channel->ch_num - 1]); + + /* Enter into manual open detect mode */ + if (ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 1) == SUCCESS) { + /* Enable open wire detection on selected channel */ + if (ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_ENABLE, + (1 << ((channel->ch_num) - 1))) == SUCCESS) { + /* Read the ADC output after open wire detection */ + data[1] = single_data_read(device, channel->ch_num - 1, + attr_polarity_val[channel->ch_num - 1]); + + /* Check for shift in common mode output voltage */ + if ((data[1] - data[0]) > OPEN_DETECT_THRESHOLD_RPD50K) { + open_detect_flag = true; + } + + rw_status = SUCCESS; + } + } +#else + /* Enter into auto open detect mode */ + if (ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, + OPEN_DETECT_AUTO_MODE_CNTS) == SUCCESS) { + /* Enable open wire detection on selected channel */ + if (ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_ENABLE, + (1 << ((channel->ch_num) - 1))) == SUCCESS) { + mdelay(1); + + if (ad7606_spi_reg_read(device, AD7606_REG_OPEN_DETECTED, + &open_detect_flag) == SUCCESS) { + rw_status = SUCCESS; + + open_detect_flag >>= (channel->ch_num -1); + open_detect_flag &= 0x1; + } + } + } +#endif + + /* Disable open detect mode */ + (void)ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 0); + + if (rw_status == SUCCESS) { + if (open_detect_flag) { + strcpy(buf, "Open Wire Detected"); + } else { + strcpy(buf, "Open Wire Not Detected"); + } + + return len; + } + + return -EINVAL; +} + +ssize_t set_chn_open_wire_detect(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + // NA- Can't set open wire detect + return - EINVAL; +} + + +/*! + * @brief Getter/Setter for the adc calibration + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + */ +ssize_t get_chn_calibrate_adc(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + float lsb_voltage; + float adc_voltage; + polarity_e polarity = attr_polarity_val[channel->ch_num - 1]; + int32_t adc_data; + int8_t chn_offset; + + /* Perform the system offset calibration */ + + if (polarity == UNIPOLAR) { + lsb_voltage = attr_chn_range[channel->ch_num - 1] / ADC_MAX_COUNT_UNIPOLAR; + } else { + lsb_voltage = attr_chn_range[channel->ch_num - 1] / ADC_MAX_COUNT_BIPOLAR; + } + + /* Sample and read the ADC channel */ + adc_data = single_data_read(device, channel->ch_num - 1, + polarity); + + /* Get an equivalent ADC voltage */ + adc_voltage = convert_adc_raw_to_voltage(adc_data, + attr_scale_val[channel->ch_num - 1]); + + /* Calculate the channel offset and write it to offset register (0x80-chn_offset) */ + chn_offset = (adc_voltage / lsb_voltage); + + if (ad7606_set_ch_offset(device, channel->ch_num - 1, + chn_offset) == SUCCESS) { + return sprintf(buf, "%s", "ADC Calibration Done"); + } + + return -EINVAL; +} + +ssize_t set_chn_calibrate_adc(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + // NA- Can't set open wire detect + return - EINVAL; +} + + +/*! + * @brief Getter/Setter for the direct register access attribute value + * @param device- pointer to IIO device structure + * @param buf- pointer to buffer holding attribute value + * @param len- length of buffer string data + * @param channel- pointer to IIO channel structure + * @return Number of characters read/written + */ +ssize_t get_direct_reg_access(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + return (ssize_t)sprintf(buf, "%d", device_reg_val); +} + +ssize_t set_direct_reg_access(void *device, + char *buf, + size_t len, + const struct iio_ch_info *channel) +{ + uint8_t reg_address; + char *token; + uint8_t offset = strlen("0x"); + char str[10] = ""; + uint8_t i=0; + uint8_t reg_data; + + if (buf[1] == 'x') { + /* Write a data to device */ + + /* Extract the register address from received string */ + strcpy(str, buf); + token = strtok(str, " "); + (void)sscanf(token + offset, "%x", ®_address); + + /* Extract the register data from received string */ + i = (strlen(str) + 1) + offset; + (void)sscanf(str + i, "%x", ®_data); + + if (reg_address <= NUM_OF_REGISTERS) { + if ((ad7606_spi_reg_write(device, reg_address, reg_data) == SUCCESS)) { + return len; + } + } + } else { + /* Read the data from device */ + (void)sscanf(buf, "%d", ®_address); + if ((ad7606_spi_reg_read(device, reg_address, &device_reg_val) == SUCCESS)) { + return len; + } + } + + return -EINVAL; +} + + +/** + * @brief Get xml corresponding to an AD7606 device. + * @param xml - Xml containing description of a device. + * @param iio_dev - Structure describing a device, channels and attributes. + * @return SUCCESS in case of success or negative value otherwise. + */ +static ssize_t iio_ad7606_get_xml(char **xml, struct iio_device *iio_dev) +{ + *xml = (char*)calloc(1, strlen(ad7606_phy_xml) + 1); + if (!(*xml)) { + return -ENOMEM; + } + + memcpy(*xml, ad7606_phy_xml, strlen(ad7606_phy_xml)); + + return SUCCESS; +} + + +/** + * @brief Read buffer data corresponding to AD7606 IIO device + * @param dev_instance[in] - IIO device instance + * @param pbuf[out] - Pointer to output data buffer + * @return SUCCESS in case of success or negative value otherwise + */ +static ssize_t iio_ad7606_read_data(void *dev_instance, + char *pbuf, + size_t offset, + size_t bytes_count, + uint32_t ch_mask) +{ + /* Read the buffered data */ + buffered_data_read(pbuf, bytes_count, offset, ch_mask); + + return bytes_count; +} + + +/** + * @brief Create structure describing a device, channels and attributes + * @param device_name[in] - Device name + * @return iio_device or NULL, in case of failure + */ +static struct iio_device *iio_ad7606_create_device(const char *device_name) +{ + struct iio_device *iio_ad7606_device; + + iio_ad7606_device = calloc(1, sizeof(struct iio_device)); + if (!iio_ad7606_device) { + return NULL; + } + + iio_ad7606_device->name = device_name; + iio_ad7606_device->num_ch = sizeof(iio_ad7606_channels) / sizeof( + iio_ad7606_channels[0]); + iio_ad7606_device->channels = iio_ad7606_channels; + iio_ad7606_device->attributes = global_attributes; + + return iio_ad7606_device; +} + + +/** + * @brief Delete IIO device. + * @param iio_device - Structure describing a device, channels and attributes + * @return SUCCESS in case of success or negative value otherwise + */ +static ssize_t iio_ad7606_delete_device(struct iio_device *iio_device) +{ + if (!iio_device) { + return FAILURE; + } + + free(iio_device); + + return SUCCESS; +} + + +/** + * @brief Init for reading/writing and parameterization of a + * ad7606 IIO device + * @param desc[in,out] - IIO device descriptor + * @param init[in] - Configuration structure + * @return SUCCESS in case of success, FAILURE otherwise + */ +int32_t iio_ad7606_init(struct iio_ad7606_desc **desc, + struct iio_ad7606_init_param *init) +{ + int32_t status; + struct iio_interface *iio_interface; + + iio_interface = (struct iio_interface *)calloc(1, sizeof(struct iio_interface)); + if (!iio_interface) { + return -ENOMEM; + } + + *iio_interface = (struct iio_interface) { + .name = dev_name, + .dev_instance = init->ad7606_phy, + .iio = iio_ad7606_create_device(dev_name), + .get_xml = iio_ad7606_get_xml, + .transfer_dev_to_mem = NULL, + .transfer_mem_to_dev = NULL, + .read_data = iio_ad7606_read_data, + .write_data = NULL, + }; + + status = iio_register(iio_interface); + if (status < 0) { + free(iio_interface); + return FAILURE; + } + + *desc = calloc(1, sizeof(struct iio_ad7606_desc)); + if (!(*desc)) { + iio_unregister(iio_interface); + free(iio_interface); + return FAILURE; + } + + (*desc)->iio_interface = iio_interface; + + return SUCCESS; +} + + +/** + * @brief Release resources allocated for IIO device + * @param desc[in] - IIO device descriptor + * @return SUCCESS in case of success, FAILURE otherwise + */ +int32_t iio_ad7606_remove(struct iio_ad7606_desc *desc) +{ + int32_t status; + + if (!desc) { + return FAILURE; + } + + status = iio_unregister(desc->iio_interface); + if (status < 0) { + return FAILURE; + } + + status = iio_ad7606_delete_device(desc->iio_interface->iio); + if (status < 0) { + return FAILURE; + } + + free(desc->iio_interface); + free(desc); + + return SUCCESS; +} + + +/*! + * @brief Get scale factor for adc data to voltage conversion for IIO client + * @param chn_range[in] - Current channel voltage range + * @param chn_range_bits[in] - Channel range register bits + * @return scale + * @details This function samples and capture the new data when previous data + * is transmitted to IIO client + */ +static float get_vltg_conv_scale_factor(float chn_range, polarity_e polarity) +{ + float scale; + + /* Get the scale factor for voltage conversion from range */ + if (polarity == UNIPOLAR) { + scale = (chn_range / ADC_MAX_COUNT_UNIPOLAR) * 1000; + } else { + scale = (chn_range / ADC_MAX_COUNT_BIPOLAR) * 1000; + } + + return scale; +} + + +/** + * @brief Initialize the IRQ contoller + * @param uart_desc[in] - UART descriptor for UART Rx IRQ event init + * @return none + * @details This function initialize the interrupt controller + */ +static int32_t iio_interrupt_handler_init(mbed_uart_desc *uart_desc) +{ + /* Pin to generate external interrupt */ + PinName ext_int_pin = BUSY_PIN; + + /* External interrupt descriptor */ + struct irq_ctrl_desc *external_int_desc; + + /* Define external interrupt platform specific parameters structure */ + mbed_irq_init_param mbed_ext_int_init_param = { + .int_mode = EXT_IRQ_FALL, + .int_obj_type = &ext_int_pin + }; + + /* External interrupt init parameters */ + struct irq_init_param external_int_init_param = { + .irq_ctrl_id = EXTERNAL_INT_ID, + .extra = &mbed_ext_int_init_param + }; + + /* External interrupt callback descriptor */ + struct callback_desc external_int_callback_desc = { + &do_conversion_callback, + NULL, + NULL + }; + + /* UART Rx interrupt descriptor */ + struct irq_ctrl_desc *uart_rx_int_desc; + + /* Define external interrupt platform specific parameters structure */ + mbed_irq_init_param mbed_uart_rx_int_init_param = { + .int_mode = 0, + .int_obj_type = uart_desc->uart_port + }; + + /* UART Rx interrupt init parameters */ + struct irq_init_param uart_rx_int_init_param = { + .irq_ctrl_id = UART_RX_INT_ID, + .extra = &mbed_uart_rx_int_init_param + }; + + /* UART Rx interrupt callback descriptor */ + struct callback_desc uart_rx_int_callback_desc = { + &iio_uart_rx_callback, + NULL, + NULL + }; + + /* Init interrupt controller for external interrupt */ + if (irq_ctrl_init(&external_int_desc, &external_int_init_param) == FAILURE) { + return FAILURE; + } + + /* Init interrupt controller for UART Rx interrupt */ + if (irq_ctrl_init(&uart_rx_int_desc, &uart_rx_int_init_param) == FAILURE) { + return FAILURE; + } + + /* Register a callback function for external interrupt */ + if (irq_register_callback(external_int_desc, EXTERNAL_INT_ID, + &external_int_callback_desc) == FAILURE) { + return FAILURE; + } + + /* Register a callback function for UART Rx interrupt */ + if (irq_register_callback(uart_rx_int_desc, UART_RX_INT_ID, + &uart_rx_int_callback_desc) == FAILURE) { + return FAILURE; + } + + return SUCCESS; +} + + +/** + * @brief Initialize the IIO interface for AD7606 IIO device + * @return none + * @return SUCCESS in case of success, FAILURE otherwise + */ +int32_t ad7606_iio_initialize(void) +{ + int32_t init_status; + + /** + * AD7606 IIO instance descriptor + */ + struct iio_ad7606_desc *piio_ad7606_desc; + + /** + * AD7606 IIO init parameters + */ + struct iio_ad7606_init_param iio_ad7606_init_param; + + /** + * IIO application init parameters + */ + struct iio_app_init_param iio_app_init_par; + + /** + * UART serial interface read/write callback + */ + struct iio_server_ops uart_iio_server_ops; + + /* + * UART Mbed init extra parameters structure + */ + mbed_uart_init_param uart_extra_init_param; + + /* + * UART init parameters structure + */ + struct uart_init_param uart_init_param; + + /** + * IIO application UART descriptor + */ + struct uart_desc *uart_desc = NULL; + + /* + * GPIO LED Init parameters structure + */ + struct gpio_init_param gpio_init_led; + + iio_ad7606_init_param = (struct iio_ad7606_init_param) { + .ad7606_phy = NULL, + }; + + uart_extra_init_param = (mbed_uart_init_param) { + .uart_tx_pin = UART_TX, + .uart_rx_pin = UART_RX + }; + + uart_init_param = (struct uart_init_param ) { + .device_id = NULL, + .baud_rate = IIO_UART_BAUD_RATE, + .extra = &uart_extra_init_param + }; + + uart_iio_server_ops = (struct iio_server_ops) { + .read = iio_uart_read, + .write = iio_uart_write, + }; + + gpio_init_led = (struct gpio_init_param) { + .number = LED_GREEN, + .extra = NULL + }; + + iio_app_init_par = (struct iio_app_init_param) { + .iio_server_ops = &uart_iio_server_ops, + }; + + /* Initialize AD7606 device and peripheral interface */ + init_status = ad7606_init(&p_ad7606_dev, &ad7606_init_str); + if (init_status != SUCCESS) { + return init_status; + } + + /* Initialize the LED GPIO descriptor */ + init_status = gpio_get_optional(&gpio_led, &gpio_init_led); + if (init_status != SUCCESS) { + return init_status; + } else { + init_status = gpio_direction_output(gpio_led, GPIO_HIGH); + if (init_status != SUCCESS) { + return init_status; + } + } + + /* Get the AD7606 IIO device instance */ + iio_ad7606_init_param.ad7606_phy = p_ad7606_dev; + + /* Initialize the UART interface for IIO application */ + init_status = iio_uart_init(&uart_desc, &uart_init_param); + if (init_status != SUCCESS) { + return init_status; + } + + /* Initialize the IIO application interface */ + init_status = iio_app_init(&iio_app_desc, &iio_app_init_par); + if (init_status != SUCCESS) { + return init_status; + } + + /* Register and initialize the AD7606 device into IIO interface */ + init_status = iio_ad7606_init(&piio_ad7606_desc, &iio_ad7606_init_param); + if (init_status != SUCCESS) { + return init_status; + } + + /* Init the data capture for AD7606 IIO app */ + init_status = iio_data_capture_init(p_ad7606_dev); + if (init_status != SUCCESS) { + return init_status; + } + + /* Init the interrupt event handler for AD7606 IIO app */ + init_status = iio_interrupt_handler_init(uart_desc->extra); + if (init_status != SUCCESS) { + return init_status; + } + + return init_status; +} + + +/** + * @brief Run the AD7606 IIO event handler + * @return none + * @details This function monitors the new IIO client event + */ +void ad7606_iio_event_handler(void) +{ + static bool background_conversion_started = false; + + /* Handle new IIO command */ + if (is_new_iio_command_detected()) { + /* Start/Stop the bakground conversion based on buffer read request */ + if (!check_iio_cmd("READBUF", 7)) { + stop_background_data_conversion(); + background_conversion_started = false; + } else { + if (background_conversion_started == false) { + start_background_data_conversion(); + background_conversion_started = true; + } + } + + /* Run the IIO interface when new command is detected */ + (void)iio_app(iio_app_desc); + } +}