Example Program for EVAL-AD7606

Dependencies:   platform_drivers

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ad7606_data_capture.c Source File

ad7606_data_capture.c

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  *   @file    ad7606_data_capture.c
00003  *   @brief   Data capture interface for AD7606 IIO application
00004  *   @details This module handles the AD7606 data capturing
00005 ********************************************************************************
00006  * Copyright (c) 2020-2021 Analog Devices, Inc.
00007  * All rights reserved.
00008  *
00009  * This software is proprietary to Analog Devices, Inc. and its licensors.
00010  * By using this software you agree to the terms of the associated
00011  * Analog Devices Software License Agreement.
00012 *******************************************************************************/
00013 
00014 /******************************************************************************/
00015 /***************************** Include Files **********************************/
00016 /******************************************************************************/
00017 
00018 #include <string.h>
00019 #include <stdlib.h>
00020 
00021 #include "app_config.h"
00022 #include "ad7606_data_capture.h"
00023 #include "iio_ad7606.h"
00024 #include "ad7606_support.h"
00025 #include "error.h"
00026 #include "adc_data_capture.h"
00027 
00028 /******************************************************************************/
00029 /********************** Macros and Constants Definition ***********************/
00030 /******************************************************************************/
00031 
00032 #if (AD7606X_ADC_RESOLUTION == 18)
00033 #define SAMPLE_SIZE_IN_BYTE     3
00034 #else
00035 #define SAMPLE_SIZE_IN_BYTE     2
00036 #endif
00037 
00038 /******************************************************************************/
00039 /********************** Variables and User Defined Data Types *****************/
00040 /******************************************************************************/
00041 
00042 /* Polarity of channels */
00043 static polarity_e polarity[AD7606X_ADC_CHANNELS];
00044 
00045 /******************************************************************************/
00046 /************************ Functions Declarations ******************************/
00047 /******************************************************************************/
00048 
00049 /* Perform conversion on input channel and read single conversion sample */
00050 static int32_t ad7606_perform_conv_and_read_sample(uint32_t *adc_data,
00051         uint8_t chn);
00052 
00053 /* Perform continuous sample read pre-operations */
00054 static int32_t ad7606_continuous_sample_read_start_ops(uint32_t ch_mask);
00055 
00056 /* Read ADC sampled/conversion data */
00057 static int32_t ad7606_read_converted_sample(uint32_t *adc_data,
00058         uint8_t input_chn);
00059 
00060 /* Trigger next ADC conversion */
00061 static int32_t ad7606_trigger_next_conversion(void);
00062 
00063 /* Define the variable for data_capture_ops structure */
00064 struct data_capture_ops data_capture_ops = {
00065     /* Point AD7606 data capture functions to generic ADC data capture functions */
00066     .single_sample_read_start_ops = NULL,
00067     .perform_conv_and_read_sample = ad7606_perform_conv_and_read_sample,
00068     .single_sample_read_stop_ops = NULL,
00069     .continuous_sample_read_start_ops = ad7606_continuous_sample_read_start_ops,
00070     .read_converted_sample = ad7606_read_converted_sample,
00071     .continuous_sample_read_stop_ops = NULL,
00072     .trigger_next_conversion = ad7606_trigger_next_conversion
00073 };
00074 
00075 /******************************************************************************/
00076 /************************ Functions Definitions *******************************/
00077 /******************************************************************************/
00078 
00079 /*!
00080  * @brief   Remove the offset from data to change output data format to
00081  *          normal or stright  binary representation (needed for IIO client)
00082  * @param   adc_raw[out] - Pointer to adc data read variable
00083  * @param   bipolar[in] - Channel polarity
00084  * @return  SUCCESS in case of success, FAILURE otherwise
00085  */
00086 static int32_t reformat_adc_raw_data(uint32_t adc_raw_data, polarity_e polarity)
00087 {
00088     int32_t adc_data;
00089 
00090     /* Bipolar ADC Range:  (-FS) <-> 0 <-> (+FS) : 2^(ADC_RES-1) <-> 0 <-> 2^(ADC_RES-1)-1
00091        Unipolar ADC Range: 0 <-> (+FS) : 0 <-> 2^ADC_RES
00092      **/
00093     if (polarity == BIPOLAR) {
00094         /* Data output format is 2's complement for bipolar mode */
00095         if (adc_raw_data > ADC_MAX_COUNT_BIPOLAR) {
00096             /* Remove the offset from result to convert into negative reading */
00097             adc_data = ADC_MAX_COUNT_UNIPOLAR - adc_raw_data;
00098             adc_data = -adc_data;
00099         } else {
00100             adc_data = adc_raw_data;
00101         }
00102     } else {
00103         /* Data output format is straight binary for unipolar mode */
00104         adc_data = adc_raw_data;
00105     }
00106 
00107     return adc_data;
00108 }
00109 
00110 
00111 /*!
00112  * @brief   Perform conversion and read conversion sample
00113  * @param   adc_data[out] - Pointer to adc data read variable
00114  * @param   chn[in] - Channel for which data is to read
00115  * @return  SUCCESS in case of success, FAILURE otherwise
00116  */
00117 int32_t ad7606_perform_conv_and_read_sample(uint32_t *adc_data, uint8_t chn)
00118 {
00119     uint32_t adc_raw[AD7606X_ADC_CHANNELS] = { 0 };
00120     uint8_t read_val;
00121     uint8_t chn_range;
00122     polarity_e polarity;
00123 
00124     /* Get input channel range */
00125     if (ad7606_spi_reg_read(p_ad7606_dev_inst,
00126                 AD7606_REG_RANGE_CH_ADDR(chn),
00127                 &read_val) != SUCCESS) {
00128         return FAILURE;
00129     }
00130 
00131     if (((chn) % 2) != 0) {
00132         read_val >>= CHANNEL_RANGE_MSK_OFFSET;
00133         chn_range = read_val;
00134     } else {
00135         chn_range = (read_val & AD7606_RANGE_CH_MSK(chn));
00136     }
00137 
00138     /* Get polarity based on input channel range */
00139     polarity = ad7606_get_input_polarity(chn_range);
00140 
00141     /* This function monitors BUSY line for EOC and read ADC result post that */
00142     if (ad7606_read(p_ad7606_dev_inst, adc_raw) != SUCCESS) {
00143         adc_raw[chn] = 0;
00144     }
00145 
00146     *adc_data = reformat_adc_raw_data(adc_raw[chn], polarity);
00147 
00148     return SUCCESS;
00149 }
00150 
00151 
00152 /*!
00153  * @brief   Perform the operations required before starting continuous sample read
00154  * @param   chn_mask[in] - active channels list received from IIO client
00155  * @return  SUCCESS in case of success, FAILURE otherwise
00156  */
00157 int32_t ad7606_continuous_sample_read_start_ops(uint32_t chn_mask)
00158 {
00159     uint8_t read_val;
00160     uint8_t chn_range;
00161 
00162     for (uint8_t chn = 0; chn < AD7606X_ADC_CHANNELS; chn++) {
00163         /* Store the channels polarity */
00164         if (ad7606_spi_reg_read(p_ad7606_dev_inst,
00165                     AD7606_REG_RANGE_CH_ADDR(chn),
00166                     &read_val) == SUCCESS) {
00167             if (((chn) % 2) != 0) {
00168                 read_val >>= CHANNEL_RANGE_MSK_OFFSET;
00169                 chn_range = read_val;
00170             } else {
00171                 chn_range = (read_val & AD7606_RANGE_CH_MSK(chn));
00172             }
00173 
00174             polarity[chn] = ad7606_get_input_polarity(chn_range);
00175         }
00176     }
00177 
00178     /* Trigger first conversion */
00179     return ad7606_trigger_next_conversion();
00180 }
00181 
00182 
00183 /*!
00184  * @brief   Read ADC raw data for recently sampled channel
00185  * @param   adc_data[out] - Pointer to adc data read variable
00186  * @param   input_chn[in] - Input channel
00187  * @return  SUCCESS in case of success, FAILURE otherwise
00188  * @note    This function is intended to call from the conversion end trigger
00189  *          event. Therefore, this function should just read raw ADC data
00190  *          without further monitoring conversion end event
00191  */
00192 int32_t ad7606_read_converted_sample(uint32_t *adc_data,
00193                      uint8_t input_chn)
00194 {
00195     uint32_t adc_raw;
00196     uint8_t bytes_to_read;
00197     uint8_t buffer_offset;
00198 
00199     if (!adc_data) {
00200         return FAILURE;
00201     }
00202 
00203     /* Get number of bytes to read count = chn_cnt * bytes per sample */
00204     bytes_to_read = AD7606X_ADC_CHANNELS * SAMPLE_SIZE_IN_BYTE;
00205     buffer_offset = input_chn * SAMPLE_SIZE_IN_BYTE;
00206 
00207     /* Read data over spi interface for all ADC channels */
00208     memset(p_ad7606_dev_inst->data, 0, sizeof(p_ad7606_dev_inst->data));
00209     spi_write_and_read(p_ad7606_dev_inst->spi_desc,
00210                p_ad7606_dev_inst->data, bytes_to_read);
00211 
00212 #if (AD7606X_ADC_RESOLUTION == 18)
00213     adc_raw =
00214         (((uint32_t)p_ad7606_dev_inst->data[buffer_offset] << 16) |     // MSB
00215          ((uint32_t)p_ad7606_dev_inst->data[buffer_offset + 1] << 8) |
00216          ((uint32_t)p_ad7606_dev_inst->data[buffer_offset + 2]));       // LSB
00217 #else
00218     adc_raw =
00219         (uint16_t)(((uint16_t)p_ad7606_dev_inst->data[buffer_offset] << 8) |    // MSB
00220                p_ad7606_dev_inst->data[buffer_offset + 1]);         // LSB
00221 #endif
00222 
00223     *adc_data = reformat_adc_raw_data(adc_raw, polarity[input_chn]);
00224 
00225     return SUCCESS;
00226 }
00227 
00228 
00229 /*!
00230  * @brief   Trigger next ADC conversion
00231  * @return  SUCCESS in case of success, FAILURE otherwise
00232  */
00233 int32_t ad7606_trigger_next_conversion(void)
00234 {
00235     if (ad7606_convst(p_ad7606_dev_inst) != SUCCESS) {
00236         return FAILURE;
00237     }
00238 
00239     return SUCCESS;
00240 }