Pratyush Mallick / Mbed OS EVAL-AD4696

Dependencies:   platform_drivers

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ad4696_data_capture.c Source File

ad4696_data_capture.c

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  *   @file    ad4696_data_capture.c
00003  *   @brief   Data capture interface for AD4696 IIO application
00004  *   @details This module handles the AD4696 data capturing for IIO client
00005 ********************************************************************************
00006  * Copyright (c) 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 "iio_ad4696.h"
00023 #include "ad4696_data_capture.h"
00024 #include "adc_data_capture.h"
00025 #include "error.h"
00026 #include "gpio.h"
00027 #include "util.h"
00028 #include "pwm.h"
00029 #include "ad4696_support.h"
00030 
00031 /******************************************************************************/
00032 /********************** Macros and Constants Definition ***********************/
00033 /******************************************************************************/
00034 /* Note: Timeout is dependent upon MCU clock frequency and tested for SDP-K1 
00035  * Mbed platform 
00036  * */
00037 #define BSY_CHECK_TIMEOUT 1000
00038 
00039 /******************************************************************************/
00040 /********************** Variables and User Defined Data Types *****************/
00041 /******************************************************************************/
00042 /* Flag to mark the start of continuous read event */
00043 static volatile bool continuous_data_read = false;
00044 /* Previously active channels */
00045 static uint32_t ad4696_prev_active_chns = 0;
00046 
00047 /******************************************************************************/
00048 /************************ Functions Declarations ******************************/
00049 /******************************************************************************/
00050 
00051 /* Save the previous active channels value */
00052 static int32_t ad4696_save_prev_active_chns(void);
00053 /* Restore (enable) the previous active channels */
00054 static int32_t ad4696_restore_prev_active_chns(void);
00055 /* Enable ADC current (user input) channel */
00056 static int32_t ad4696_enable_curr_chn(uint8_t chn);
00057 /* Enable ADC channels according to channel mask*/
00058 static int32_t ad4696_enable_channel_mask(uint32_t chn_msk);
00059 /* Disable ADC current (user input) channel */
00060 static int32_t ad4696_disable_curr_chn(uint8_t chn);
00061 /* Disable all ADC channels */
00062 static int32_t ad4696_disable_all_chns(void);
00063 /* Enable conversion for single sample read */
00064 static int32_t ad4696_single_sample_read_start_ops(uint8_t input_chn);
00065 /* Enable conversion for continuous sample read */
00066 static int32_t ad4696_enable_continuous_read_conversion(uint32_t ch_mask);
00067 /* Disable conversion */
00068 static int32_t ad4696_continuous_sample_read_stop_ops(void);
00069 /* Wait for conversion to finish on enabled channels and read conversion data */
00070 static int32_t ad4696_perform_conv_and_read_sample(uint32_t *adc_data);
00071 /* Read ADC raw sample/data */
00072 static int32_t ad4696_read_converted_sample(uint32_t *adc_data);
00073 /* Monitor end of conversion event */
00074 static int32_t ad4696_end_of_conversion_check(void);
00075 
00076 /* Define the variable for data_capture_ops structure */
00077 struct data_capture_ops data_capture_ops = {
00078     /* Point ad7134 data capture functions to generic ADC data capture functions */
00079     .single_sample_read_start_ops = ad4696_single_sample_read_start_ops,
00080     .perform_conv_and_read_sample = ad4696_perform_conv_and_read_sample,
00081     .single_sample_read_stop_ops = ad4696_continuous_sample_read_stop_ops,
00082     .continuous_sample_read_start_ops = ad4696_enable_continuous_read_conversion,
00083     .read_converted_sample = ad4696_read_converted_sample,
00084     .continuous_sample_read_stop_ops = ad4696_continuous_sample_read_stop_ops,
00085     .trigger_next_conversion = NULL
00086 };      
00087 
00088 /******************************************************************************/
00089 /************************ Functions Definitions *******************************/
00090 /******************************************************************************/
00091 
00092 /*!
00093  * @brief   Save the previous active channels 
00094  * @return  SUCCESS in case of success, FAILURE otherwise
00095  */
00096 static int32_t ad4696_save_prev_active_chns(void)
00097 {
00098     uint8_t data;
00099     /* Read the upper byte of the standard sequencer configuration register*/
00100     if (ad469x_spi_reg_read(p_ad4696_dev, AD469x_REG_SEQ_UB, &data) != SUCCESS) {
00101         return FAILURE;
00102     }
00103     
00104     /* The upper byte channel configuration is saved to the variable and is
00105      * shifted by 8 bits to save the lower byte register configuration */
00106     ad4696_prev_active_chns = data;
00107     ad4696_prev_active_chns <<= 8; 
00108     
00109     /* Reads the lower byte of the standard sequencer configuration register*/
00110     if (ad469x_spi_reg_read(p_ad4696_dev, AD469x_REG_SEQ_LB, &data) != SUCCESS) { 
00111         return FAILURE;
00112     }
00113     ad4696_prev_active_chns |= data; 
00114 
00115     return SUCCESS;
00116 }
00117 
00118 /*!
00119  * @brief   Restore (re-enable) the previous active channels
00120  * @return  SUCCESS in case of success, FAILURE otherwise
00121  */
00122 static int32_t ad4696_restore_prev_active_chns(void)
00123 {   
00124     if (ad469x_exit_conversion_mode(p_ad4696_dev) != SUCCESS)
00125         return FAILURE;
00126     
00127     /* Configure the lower byte of the standard sequencer configuration register*/
00128     if (ad469x_spi_reg_write(p_ad4696_dev, 
00129         AD469x_REG_SEQ_LB, 
00130         AD469x_SEQ_LB_CONFIG(ad4696_prev_active_chns)) != SUCCESS) {
00131         return FAILURE;
00132     }
00133     
00134     /* Configure the upper byte of the standard sequencer configuration register*/
00135     if (ad469x_spi_reg_write(p_ad4696_dev,
00136         AD469x_REG_SEQ_UB,
00137         AD469x_SEQ_UB_CONFIG(ad4696_prev_active_chns)) != SUCCESS) {
00138         return FAILURE;
00139     }
00140     
00141     return SUCCESS;
00142 }
00143 
00144 /*!
00145  * @brief   Disable all active channels
00146  * @return  SUCCESS in case of success, FAILURE otherwise
00147  */
00148 static int32_t ad4696_disable_all_chns(void)
00149 {   
00150     /* Reset the lower byte of the standard sequencer configuration register*/
00151     if (ad469x_spi_reg_write(p_ad4696_dev,
00152         AD469x_REG_SEQ_LB,
00153         AD469x_SEQ_CHANNELS_RESET) != SUCCESS) {
00154         return FAILURE;
00155     }
00156     
00157     /* Reset the upper byte of the standard sequencer configuration register*/
00158     if (ad469x_spi_reg_write(p_ad4696_dev, 
00159         AD469x_REG_SEQ_UB,
00160         AD469x_SEQ_CHANNELS_RESET) != SUCCESS) {
00161         return FAILURE;
00162     }
00163     
00164     return SUCCESS;
00165 }
00166 
00167 /*!
00168  * @brief   Enable input channel
00169  * @param   chn[in] - Channel to enable
00170  * @return  SUCCESS in case of success, FAILURE otherwise
00171  */
00172 static int32_t ad4696_enable_curr_chn(uint8_t chn)
00173 {
00174     /* If channel number is less than 8, then write to 
00175      * lower byte configuration register or else write 
00176      * to upper byte configuration register 
00177      * */
00178     if (chn < (NO_OF_CHANNELS / 2)) {
00179         if (ad469x_spi_write_mask(p_ad4696_dev, 
00180             AD469x_REG_SEQ_LB,
00181             AD469x_SEQ_CHANNELS_RESET,
00182             AD469x_SINGLE_CHANNEL_EN(chn))  != SUCCESS) {
00183             return FAILURE; 
00184         }
00185     }   
00186     else {
00187         if (ad469x_spi_write_mask(p_ad4696_dev,
00188             AD469x_REG_SEQ_UB, 
00189             AD469x_SEQ_CHANNELS_RESET,
00190             AD469x_SINGLE_CHANNEL_EN(chn - 8)) != SUCCESS) {
00191             return FAILURE;
00192         }
00193     } 
00194     
00195     return SUCCESS;
00196 }
00197 
00198 /*!
00199  * @brief   Enable input channels according to the mask
00200  * @param   chn_msk[in] - Mask containing channels to be enabled
00201  * @return  SUCCESS in case of success, FAILURE otherwise
00202  */
00203 static int32_t ad4696_enable_channel_mask(uint32_t chn_msk)
00204 {
00205     /* Write the lower byte of the channel mask to the lower byte 
00206      * of the standard sequencer configuration register 
00207      * */
00208     if (ad469x_spi_reg_write(p_ad4696_dev, 
00209         AD469x_REG_SEQ_LB,
00210         AD469x_SEQ_LB_CONFIG(chn_msk))  != SUCCESS) {
00211         return FAILURE; 
00212     }
00213     
00214     /* Write the upper byte of the channel mask to the upper byte 
00215      * of the standard sequencer configuration register
00216      * */
00217     if (ad469x_spi_reg_write(p_ad4696_dev,
00218         AD469x_REG_SEQ_UB, 
00219         AD469x_SEQ_UB_CONFIG(chn_msk)) != SUCCESS) {
00220         return FAILURE;
00221     }
00222     
00223     return SUCCESS;
00224 }
00225 
00226 /*!
00227  * @brief   Disable input channel
00228  * @param   chn[in] - Channel to disable
00229  * @return  SUCCESS in case of success, FAILURE otherwise
00230  */
00231 static int32_t ad4696_disable_curr_chn(uint8_t chn)
00232 {
00233     /* If channel number is less than 8, then write 
00234      * to lower byte configuration register or else 
00235      * write to upper byte configuration register 
00236      * */
00237     if (chn < (NO_OF_CHANNELS/2)) {
00238         if (ad469x_spi_write_mask(p_ad4696_dev,
00239             AD469x_REG_SEQ_LB, 
00240             AD469x_SINGLE_CHANNEL_EN(chn),
00241             AD469x_SEQ_CHANNEL_DI) != SUCCESS) {
00242             return FAILURE;
00243         }
00244     }
00245     else {
00246         if (ad469x_spi_write_mask(p_ad4696_dev,
00247             AD469x_REG_SEQ_UB,
00248             AD469x_SINGLE_CHANNEL_EN(chn - 8),
00249             AD469x_SEQ_CHANNEL_DI) != SUCCESS) {
00250             return FAILURE;
00251         }
00252     } 
00253 
00254     return SUCCESS;
00255 }
00256 
00257 /*!
00258  * @brief   Enable conversion for single data read
00259  * @param   input_chn[in] - Channel to be enabled
00260  * @return  SUCCESS in case of success, FAILURE otherwise
00261  */
00262 static int32_t ad4696_single_sample_read_start_ops(uint8_t input_chn)
00263 {
00264     do {
00265         /* Save previously active channels */
00266         if (ad4696_save_prev_active_chns() != SUCCESS) {
00267             break;
00268         }
00269         
00270         /* Disable all channels */
00271         if (ad4696_disable_all_chns() != SUCCESS) {
00272             break;
00273         }
00274         
00275         /* Enable user input channel */
00276         if (ad4696_enable_curr_chn(input_chn) != SUCCESS) {
00277             break;
00278         }
00279         
00280         /* Enter into conversion mode */
00281         if (ad469x_enter_conversion_mode(p_ad4696_dev) != SUCCESS) {
00282             break;
00283         }
00284         
00285         return SUCCESS;
00286     } while (0);
00287     
00288     return FAILURE;
00289 }
00290 
00291 /*!
00292  * @brief   Enable conversion for continuous (sequencing) data read
00293  * @param   ch_mask[in] - Mask containing channels to be enabled
00294  * @return  SUCCESS in case of success, FAILURE otherwise
00295  */
00296 static int32_t ad4696_enable_continuous_read_conversion(uint32_t ch_mask)
00297 {
00298     do {
00299         /* Save previously active channels */
00300         if (ad4696_save_prev_active_chns() != SUCCESS) {
00301             break;
00302         }
00303         
00304         /* Disable all channels */
00305         if (ad4696_disable_all_chns() != SUCCESS) {
00306             break;
00307         }
00308         
00309         /* Enable user input channels */
00310         if (ad4696_enable_channel_mask(ch_mask) != SUCCESS) {
00311             break;
00312         }
00313 
00314         /* Start Generating PWM signal */
00315         if (pwm_enable(pwm_desc) != SUCCESS) {
00316             break;
00317         }
00318         
00319         continuous_data_read = true;
00320         /* Enter into conversion mode */
00321         if (ad469x_enter_conversion_mode(p_ad4696_dev) != SUCCESS) {
00322             break;
00323         }
00324 
00325         return SUCCESS;
00326     } while (0);    
00327     
00328     return FAILURE;
00329 }
00330 
00331 /*!
00332  * @brief   Disable ADC conversion
00333  * @return  SUCCESS in case of success, FAILURE otherwise
00334  */
00335 static int32_t ad4696_continuous_sample_read_stop_ops(void)
00336 {   
00337     if (continuous_data_read) {
00338         /* Stop Generating PWM signal */
00339         if (pwm_disable(pwm_desc) != SUCCESS) {
00340             return FAILURE;
00341         }
00342     }
00343     
00344     /* Enter into register mode or exit from conversion mode */
00345     if (ad469x_exit_conversion_mode(p_ad4696_dev) != SUCCESS) {
00346         return FAILURE;
00347     }
00348     
00349     /* Enable back channels which were disabled prior to conversion start*/
00350     if (ad4696_restore_prev_active_chns() != SUCCESS) {
00351         return FAILURE;
00352     }
00353     
00354     continuous_data_read = false;
00355     return SUCCESS;
00356 }
00357 
00358 /*!
00359  * @brief   Read ADC raw data for recently sampled channel
00360  * @param   adc_raw[out] - Pointer to adc data read variable
00361  * @return  SUCCESS in case of success, FAILURE otherwise
00362  * @note    This function is intended to call from the conversion end trigger
00363  *          event. Therefore, this function should just read raw ADC data
00364  *          without further monitoring conversion end event
00365  */
00366 static int32_t ad4696_read_converted_sample(uint32_t *adc_raw)
00367 {
00368     /* Null Check */
00369     if (!adc_raw) {
00370         return FAILURE;
00371     }
00372     
00373     /* Read the converted ADC raw data and return the transaction result*/
00374     return ad469x_read_data(p_ad4696_dev, 0, adc_raw, 1);
00375 }
00376 
00377 /*!
00378  * @brief   Read ADC single sample data
00379  * @param   read_adc_data[out] - Pointer to adc data read variable
00380  * @return  SUCCESS in case of success, FAILURE otherwise
00381  * @details This function performs the sampling on previously active channels
00382  *          and then reads conversion result
00383  */
00384 static int32_t ad4696_perform_conv_and_read_sample(uint32_t *read_adc_data)
00385 {
00386     uint32_t adc_raw = 0;
00387 
00388     /* Read the converted ADC raw data */
00389     if (ad469x_read_data(p_ad4696_dev, 1, &adc_raw, 1) != SUCCESS) {
00390         return FAILURE;
00391     }
00392     
00393     *read_adc_data = adc_raw;
00394     return SUCCESS;
00395 }
00396 
00397 /*!
00398  * @brief   Check for the end of conversion event
00399  * @return  SUCCESS in case of success, FAILURE otherwise
00400  * @details This function monitors the state line for BSY pin 
00401  *          until timeout is reached
00402  */
00403 static int32_t ad4696_end_of_conversion_check(void)
00404 {
00405     uint16_t timeout = (uint16_t)BSY_CHECK_TIMEOUT; /* time out counter */
00406     uint8_t busy = GPIO_HIGH; /* GPIO initial state */
00407     
00408     /* Check for BSY to go low */
00409     while (busy == GPIO_HIGH) {
00410         gpio_get_value(((struct ad469x_dev *)p_ad4696_dev)->gpio_busy, &busy);
00411         timeout--;
00412         if (!timeout) {
00413             return FAILURE;
00414         }
00415     }
00416         
00417     timeout = (uint16_t)BSY_CHECK_TIMEOUT;
00418     /* Check for BSY pin to go high */
00419     while (busy == GPIO_LOW) {
00420         gpio_get_value(((struct ad469x_dev *)p_ad4696_dev)->gpio_busy, &busy);
00421         timeout--;
00422         if (!timeout) {
00423             return FAILURE;
00424         }
00425     }
00426     
00427     return SUCCESS;
00428 }