Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: platform_drivers
ad4696_data_capture.c
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 }
Generated on Thu Jul 21 2022 03:20:48 by
1.7.2