Example Program for EVAL-AD7606
Dependencies: platform_drivers
app/ad7606_data_capture.c
- Committer:
- Kjansen
- Date:
- 2021-08-03
- Revision:
- 7:054dbd5e1f45
- Parent:
- 6:32de160dce43
File content as of revision 7:054dbd5e1f45:
/***************************************************************************//** * @file ad7606_data_capture.c * @brief Data capture interface for AD7606 IIO application * @details This module handles the AD7606 data capturing ******************************************************************************** * Copyright (c) 2020-2021 Analog Devices, Inc. * All rights reserved. * * 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 <string.h> #include <stdlib.h> #include "app_config.h" #include "ad7606_data_capture.h" #include "iio_ad7606.h" #include "ad7606_support.h" #include "error.h" #include "adc_data_capture.h" /******************************************************************************/ /********************** Macros and Constants Definition ***********************/ /******************************************************************************/ #if (AD7606X_ADC_RESOLUTION == 18) #define SAMPLE_SIZE_IN_BYTE 3 #else #define SAMPLE_SIZE_IN_BYTE 2 #endif /******************************************************************************/ /********************** Variables and User Defined Data Types *****************/ /******************************************************************************/ /* Polarity of channels */ static polarity_e polarity[AD7606X_ADC_CHANNELS]; /******************************************************************************/ /************************ Functions Declarations ******************************/ /******************************************************************************/ /* Perform conversion on input channel and read single conversion sample */ static int32_t ad7606_perform_conv_and_read_sample(uint32_t *adc_data, uint8_t chn); /* Perform continuous sample read pre-operations */ static int32_t ad7606_continuous_sample_read_start_ops(uint32_t ch_mask); /* Read ADC sampled/conversion data */ static int32_t ad7606_read_converted_sample(uint32_t *adc_data, uint8_t input_chn); /* Trigger next ADC conversion */ static int32_t ad7606_trigger_next_conversion(void); /* Define the variable for data_capture_ops structure */ struct data_capture_ops data_capture_ops = { /* Point AD7606 data capture functions to generic ADC data capture functions */ .single_sample_read_start_ops = NULL, .perform_conv_and_read_sample = ad7606_perform_conv_and_read_sample, .single_sample_read_stop_ops = NULL, .continuous_sample_read_start_ops = ad7606_continuous_sample_read_start_ops, .read_converted_sample = ad7606_read_converted_sample, .continuous_sample_read_stop_ops = NULL, .trigger_next_conversion = ad7606_trigger_next_conversion }; /******************************************************************************/ /************************ Functions Definitions *******************************/ /******************************************************************************/ /*! * @brief Remove the offset from data to change output data format to * normal or stright binary representation (needed for IIO client) * @param adc_raw[out] - Pointer to adc data read variable * @param bipolar[in] - Channel polarity * @return SUCCESS in case of success, FAILURE otherwise */ static int32_t reformat_adc_raw_data(uint32_t adc_raw_data, polarity_e polarity) { int32_t adc_data; /* Bipolar ADC Range: (-FS) <-> 0 <-> (+FS) : 2^(ADC_RES-1) <-> 0 <-> 2^(ADC_RES-1)-1 Unipolar ADC Range: 0 <-> (+FS) : 0 <-> 2^ADC_RES **/ if (polarity == BIPOLAR) { /* Data output format is 2's complement for bipolar mode */ if (adc_raw_data > ADC_MAX_COUNT_BIPOLAR) { /* Remove the offset from result to convert into negative reading */ adc_data = ADC_MAX_COUNT_UNIPOLAR - adc_raw_data; adc_data = -adc_data; } else { adc_data = adc_raw_data; } } else { /* Data output format is straight binary for unipolar mode */ adc_data = adc_raw_data; } return adc_data; } /*! * @brief Perform conversion and read conversion sample * @param adc_data[out] - Pointer to adc data read variable * @param chn[in] - Channel for which data is to read * @return SUCCESS in case of success, FAILURE otherwise */ int32_t ad7606_perform_conv_and_read_sample(uint32_t *adc_data, uint8_t chn) { uint32_t adc_raw[AD7606X_ADC_CHANNELS] = { 0 }; uint8_t read_val; uint8_t chn_range; polarity_e polarity; /* Get input channel range */ if (ad7606_spi_reg_read(p_ad7606_dev_inst, AD7606_REG_RANGE_CH_ADDR(chn), &read_val) != SUCCESS) { return FAILURE; } if (((chn) % 2) != 0) { read_val >>= CHANNEL_RANGE_MSK_OFFSET; chn_range = read_val; } else { chn_range = (read_val & AD7606_RANGE_CH_MSK(chn)); } /* Get polarity based on input channel range */ polarity = ad7606_get_input_polarity(chn_range); /* This function monitors BUSY line for EOC and read ADC result post that */ if (ad7606_read(p_ad7606_dev_inst, adc_raw) != SUCCESS) { adc_raw[chn] = 0; } *adc_data = reformat_adc_raw_data(adc_raw[chn], polarity); return SUCCESS; } /*! * @brief Perform the operations required before starting continuous sample read * @param chn_mask[in] - active channels list received from IIO client * @return SUCCESS in case of success, FAILURE otherwise */ int32_t ad7606_continuous_sample_read_start_ops(uint32_t chn_mask) { uint8_t read_val; uint8_t chn_range; for (uint8_t chn = 0; chn < AD7606X_ADC_CHANNELS; chn++) { /* Store the channels polarity */ if (ad7606_spi_reg_read(p_ad7606_dev_inst, AD7606_REG_RANGE_CH_ADDR(chn), &read_val) == SUCCESS) { if (((chn) % 2) != 0) { read_val >>= CHANNEL_RANGE_MSK_OFFSET; chn_range = read_val; } else { chn_range = (read_val & AD7606_RANGE_CH_MSK(chn)); } polarity[chn] = ad7606_get_input_polarity(chn_range); } } /* Trigger first conversion */ return ad7606_trigger_next_conversion(); } /*! * @brief Read ADC raw data for recently sampled channel * @param adc_data[out] - Pointer to adc data read variable * @param input_chn[in] - Input channel * @return SUCCESS in case of success, FAILURE otherwise * @note This function is intended to call from the conversion end trigger * event. Therefore, this function should just read raw ADC data * without further monitoring conversion end event */ int32_t ad7606_read_converted_sample(uint32_t *adc_data, uint8_t input_chn) { uint32_t adc_raw; uint8_t bytes_to_read; uint8_t buffer_offset; if (!adc_data) { return FAILURE; } /* Get number of bytes to read count = chn_cnt * bytes per sample */ bytes_to_read = AD7606X_ADC_CHANNELS * SAMPLE_SIZE_IN_BYTE; buffer_offset = input_chn * SAMPLE_SIZE_IN_BYTE; /* Read data over spi interface for all ADC channels */ memset(p_ad7606_dev_inst->data, 0, sizeof(p_ad7606_dev_inst->data)); spi_write_and_read(p_ad7606_dev_inst->spi_desc, p_ad7606_dev_inst->data, bytes_to_read); #if (AD7606X_ADC_RESOLUTION == 18) adc_raw = (((uint32_t)p_ad7606_dev_inst->data[buffer_offset] << 16) | // MSB ((uint32_t)p_ad7606_dev_inst->data[buffer_offset + 1] << 8) | ((uint32_t)p_ad7606_dev_inst->data[buffer_offset + 2])); // LSB #else adc_raw = (uint16_t)(((uint16_t)p_ad7606_dev_inst->data[buffer_offset] << 8) | // MSB p_ad7606_dev_inst->data[buffer_offset + 1]); // LSB #endif *adc_data = reformat_adc_raw_data(adc_raw, polarity[input_chn]); return SUCCESS; } /*! * @brief Trigger next ADC conversion * @return SUCCESS in case of success, FAILURE otherwise */ int32_t ad7606_trigger_next_conversion(void) { if (ad7606_convst(p_ad7606_dev_inst) != SUCCESS) { return FAILURE; } return SUCCESS; }