Example Program for EVAL-AD7606
Dependencies: platform_drivers
ad7606_data_capture.c
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 }
Generated on Wed Jul 13 2022 11:55:04 by 1.7.2