Example program for EVAL-AD4130
Dependencies: tempsensors sdp_k1_sdram
ad4130_support.c
00001 /*************************************************************************//** 00002 * @file ad4130_support.c 00003 * @brief AD4130 device No-OS driver supports 00004 ****************************************************************************** 00005 * Copyright (c) 2020, 2022 Analog Devices, Inc. 00006 * All rights reserved. 00007 * 00008 * This software is proprietary to Analog Devices, Inc. and its licensors. 00009 * By using this software you agree to the terms of the associated 00010 * Analog Devices Software License Agreement. 00011 *****************************************************************************/ 00012 00013 /******************************************************************************/ 00014 /***************************** Include Files **********************************/ 00015 /******************************************************************************/ 00016 00017 #include <stdint.h> 00018 00019 #include "app_config.h" 00020 #include "ad4130_support.h" 00021 #include "no_os_error.h" 00022 00023 /******************************************************************************/ 00024 /********************** Macros and Constants Definition ***********************/ 00025 /******************************************************************************/ 00026 00027 /* AD4130 FIFO size and readback command size in bytes */ 00028 #define AD4130_FIFO_MAX_SIZE (256) 00029 #define AD4130_FIFO_READ_CMD_BYTES (2) 00030 00031 #define BYTE_SIZE (8) 00032 00033 /* Timeout to monitor CON monitor GPIO. The timeout count is dependent upon the 00034 * MCU clock frequency. This timeout is tested for SDP-K1 Mbed controller platform */ 00035 #define CONV_MON_GPIO_TIMEOUT (10000) 00036 00037 /* Select between GPIO Or STATUS register to monitor the end 00038 * of conversion in single conversion mode */ 00039 //#define CONV_MON_USING_RDY_STATUS // Uncomment to use STATUS reg 00040 00041 /* FIFO busy time as per specifications (in usec) 00042 * Note : This time is stringent in FIFO readback.The minimum time period 00043 * as per specifications is 20usec 00044 */ 00045 #define FIFO_BUSY_TIME (20) 00046 00047 /******************************************************************************/ 00048 /********************** Variables and User Defined Data Types *****************/ 00049 /******************************************************************************/ 00050 00051 /* AD4130 FIFO readback buffer. 00052 * Size for 24-bit ADC = (256 * 3) + 2 = 770 bytes 00053 * Size for 16-bit ADC = (256 * 2) + 2 = 514 bytes 00054 * */ 00055 static uint8_t fifo_buf[(AD4130_FIFO_MAX_SIZE * (ADC_RESOLUTION / BYTE_SIZE)) + 00056 AD4130_FIFO_READ_CMD_BYTES]; 00057 00058 /******************************************************************************/ 00059 /************************ Functions Definitions *******************************/ 00060 /******************************************************************************/ 00061 00062 /*! 00063 * @brief Get reference voltage based on the reference source 00064 * @param dev[in] - Device instance 00065 * @param chn[in] - ADC channel 00066 * @return Reference voltage 00067 */ 00068 float ad4130_get_reference_voltage(struct ad413x_dev *dev, uint8_t chn) 00069 { 00070 float ref_voltage; 00071 uint8_t preset = dev->ch[chn].preset; 00072 enum ad413x_ref_sel ref = dev->preset[preset].ref_sel; 00073 enum ad413x_int_ref int_ref = dev->int_ref; 00074 00075 switch (ref) { 00076 case AD413X_REFIN1: 00077 ref_voltage = AD4130_REFIN1_VOLTAGE; 00078 break; 00079 00080 case AD413X_REFIN2: 00081 ref_voltage = AD4130_REFIN2_VOLTAGE; 00082 break; 00083 00084 case AD413X_AVDD_AVSS: 00085 ref_voltage = AD4130_AVDD_VOLTAGE; 00086 break; 00087 00088 case AD413X_REFOUT_AVSS: 00089 if (int_ref == AD413X_INTREF_1_25V) { 00090 ref_voltage = AD4170_1_25V_INT_REF_VOLTAGE; 00091 } else { 00092 ref_voltage = AD4170_2_5V_INT_REF_VOLTAGE; 00093 } 00094 break; 00095 00096 default: 00097 ref_voltage = AD4170_2_5V_INT_REF_VOLTAGE; 00098 break; 00099 } 00100 00101 return ref_voltage; 00102 } 00103 00104 /*! 00105 * @brief Perform the sign conversion for handling negative voltages in 00106 * bipolar mode 00107 * @param dev[in] - Device instance 00108 * @param adc_raw_data[in] - ADC raw value 00109 * @param chn[in] - ADC Channel 00110 * @return ADC data after signed conversion 00111 */ 00112 int32_t perform_sign_conversion(struct ad413x_dev *dev, uint32_t adc_raw_data, 00113 uint8_t chn) 00114 { 00115 int32_t adc_data; 00116 bool bipolar = dev->bipolar; 00117 00118 /* Bipolar ADC Range: (-FS) <-> 0 <-> (+FS) : 0 <-> 2^(ADC_RES-1)-1 <-> 2^(ADC_RES-1) 00119 Unipolar ADC Range: 0 <-> (+FS) : 0 <-> 2^ADC_RES 00120 **/ 00121 if (bipolar) { 00122 /* Data output format is offset binary for bipolar mode */ 00123 adc_data = adc_raw_data - ADC_MAX_COUNT_BIPOLAR; 00124 } else { 00125 /* Data output format is straight binary for unipolar mode */ 00126 adc_data = adc_raw_data; 00127 } 00128 00129 return adc_data; 00130 } 00131 00132 /*! 00133 * @brief Convert the ADC raw value into equivalent voltage 00134 * @param dev[in] - Device instance 00135 * @param adc_raw[in]- ADC raw data 00136 * @param chn[in] - ADC channel 00137 * @return ADC voltage value 00138 */ 00139 float convert_adc_sample_into_voltage(void *dev, uint32_t adc_raw, 00140 uint8_t chn) 00141 { 00142 enum ad413x_gain pga; 00143 float vref; 00144 int32_t adc_data; 00145 uint8_t preset = ((struct ad413x_dev *)dev)->ch[chn].preset; 00146 bool bipolar = ((struct ad413x_dev *)dev)->bipolar; 00147 00148 pga = ((struct ad413x_dev *)dev)->preset[preset].gain; 00149 vref = ad4130_get_reference_voltage(dev, chn); 00150 adc_data = perform_sign_conversion(dev, adc_raw, chn); 00151 00152 if (bipolar) { 00153 return (adc_data * (vref / (ADC_MAX_COUNT_BIPOLAR * (1 << pga)))); 00154 } else { 00155 return (adc_data * (vref / (ADC_MAX_COUNT_UNIPOLAR * (1 << pga)))); 00156 } 00157 } 00158 00159 /*! 00160 * @brief Convert the ADC raw value into equivalent RTD resistance 00161 * @param dev[in] - Device instance 00162 * @param adc_raw[in] - ADC raw sample 00163 * @param rtd_ref[in] - RTD reference resistance in ohms 00164 * @param chn[in] - ADC channel 00165 * @return RTD resistance value 00166 * @note RTD is biased with constant excitation current. Below formula 00167 * is based on ratiometric measurement, where fixed value of RTD RREF 00168 * (reference resistor) and gain is taken into account 00169 */ 00170 float convert_adc_raw_into_rtd_resistance(void *dev, uint32_t adc_raw, 00171 float rtd_ref, uint8_t chn) 00172 { 00173 enum ad413x_gain pga; 00174 int32_t adc_data; 00175 uint8_t preset = ((struct ad413x_dev *)dev)->ch[chn].preset; 00176 bool bipolar = ((struct ad413x_dev *)dev)->bipolar; 00177 00178 pga = ((struct ad413x_dev *)dev)->preset[preset].gain; 00179 adc_data = perform_sign_conversion(dev, adc_raw, chn); 00180 00181 if (bipolar) { 00182 return (((float)adc_data * rtd_ref) / (ADC_MAX_COUNT_BIPOLAR * (1 << pga))); 00183 } else { 00184 return (((float)adc_data * rtd_ref) / (ADC_MAX_COUNT_UNIPOLAR * (1 << pga))); 00185 } 00186 } 00187 00188 /*! 00189 * @brief Function to monitor end of conversion and read 00190 * conversion result 00191 * @param dev[in] - Device instance 00192 * @param raw_data[in, out]- ADC raw data 00193 * @return 0 in case of success, negative error code otherwise 00194 */ 00195 int32_t ad413x_mon_conv_and_read_data(struct ad413x_dev *dev, 00196 uint32_t *raw_data) 00197 { 00198 int32_t ret; 00199 uint8_t conv_mon = 0; 00200 uint32_t timeout = CONV_MON_GPIO_TIMEOUT; 00201 00202 if (!dev || !raw_data) { 00203 return -EINVAL; 00204 } 00205 00206 /* Wait for conversion */ 00207 #if defined(CONV_MON_USING_RDY_STATUS) 00208 while (!conv_mon && timeout--) { 00209 /* Read the value of the Status Register */ 00210 ret = ad413x_reg_read(dev, AD413X_REG_STATUS, raw_data); 00211 if (ret) { 00212 return ret; 00213 } 00214 00215 /* Check the RDY bit in the Status Register */ 00216 conv_mon = (*raw_data & AD413X_ADC_DATA_STATUS); 00217 } 00218 00219 if (!timeout) { 00220 return -EIO; 00221 } 00222 00223 /* Read the conversion result */ 00224 ret = ad413x_reg_read(dev, AD413X_REG_DATA, raw_data); 00225 if (ret) { 00226 return ret; 00227 } 00228 #else 00229 conv_mon = NO_OS_GPIO_HIGH; 00230 while (conv_mon == NO_OS_GPIO_HIGH && timeout--) { 00231 ret = no_os_gpio_get_value(conv_mon_gpio_desc, &conv_mon); 00232 if (ret) { 00233 return ret; 00234 } 00235 } 00236 00237 if (!timeout) { 00238 return -EIO; 00239 } 00240 00241 /* Read the conversion result */ 00242 ret = ad413x_reg_read(dev, AD413X_REG_DATA, raw_data); 00243 if (ret) { 00244 return ret; 00245 } 00246 00247 conv_mon = NO_OS_GPIO_LOW; 00248 timeout = CONV_MON_GPIO_TIMEOUT; 00249 while (conv_mon == NO_OS_GPIO_LOW && timeout--) { 00250 ret = no_os_gpio_get_value(conv_mon_gpio_desc, &conv_mon); 00251 if (ret) { 00252 return ret; 00253 } 00254 } 00255 00256 if (!timeout) { 00257 return -EIO; 00258 } 00259 #endif 00260 00261 return 0; 00262 } 00263 00264 /*! 00265 * @brief Read the data from FIFO 00266 * @param dev[in] - device instance 00267 * @param data[in] - Buffer to store FIFO data 00268 * @param adc_samples[in] - Number of ADC samples to read 00269 * @return 0 in case of success, negative error code otherwise 00270 * @note This function doesn't consider the FIFO status and header information 00271 * during data readback. It is assumed data user is intending to read 00272 * only the data from FIFO. 00273 */ 00274 int32_t ad4130_read_fifo(struct ad413x_dev *dev, uint32_t *data, 00275 uint32_t adc_samples) 00276 { 00277 int32_t ret; 00278 uint32_t loop_cntr; 00279 uint32_t buf_indx = 0; 00280 uint32_t bytes; 00281 00282 if (!dev || !data) { 00283 return -EINVAL; 00284 } 00285 00286 /* Watermark count of 0 implies full FIFO readback */ 00287 if ((adc_samples == 0) || (adc_samples > AD4130_FIFO_MAX_SIZE)) { 00288 adc_samples = AD4130_FIFO_MAX_SIZE; 00289 } 00290 00291 /* Delay b/w interrupt trigger and FIFO readback start */ 00292 no_os_udelay(FIFO_BUSY_TIME); 00293 00294 /* MOSI pin outputs 0x00 during FIFO data readback */ 00295 memset(fifo_buf, 0, sizeof(fifo_buf)); 00296 00297 /* Enter into FIFO read mode by issuing dummy read command. Command consists of first byte as 00298 * address of FIFO data register and 2nd byte as number of samples to read from FIFO */ 00299 fifo_buf[0] = AD413X_COMM_REG_RD | AD413X_ADDR(AD413X_REG_FIFO_DATA); 00300 fifo_buf[1] = adc_samples; 00301 00302 /* Bytes to read = (samples * data size) + fifo data reg address + sample_cnt */ 00303 bytes = (adc_samples * (ADC_RESOLUTION / BYTE_SIZE)) + 00304 AD4130_FIFO_READ_CMD_BYTES; 00305 00306 /* Read all bytes over SPI */ 00307 ret = no_os_spi_write_and_read(dev->spi_dev, fifo_buf, bytes); 00308 if (ret) { 00309 return ret; 00310 } 00311 00312 /* Extract the data from buffer (data doesn't contain header/status info) */ 00313 for (loop_cntr = AD4130_FIFO_READ_CMD_BYTES; loop_cntr < bytes; 00314 loop_cntr += (ADC_RESOLUTION / BYTE_SIZE)) { 00315 #if (ADC_RESOLUTION == 24) 00316 data[buf_indx++] = ((int32_t)fifo_buf[loop_cntr] << 16) | 00317 ((int32_t)fifo_buf[loop_cntr + 1] << 8) | 00318 (int32_t)fifo_buf[loop_cntr + 2]; 00319 #else 00320 /* For 16-bit resolution */ 00321 data[buf_indx++] = ((int32_t)fifo_buf[loop_cntr] << 8) | 00322 (int32_t)fifo_buf[loop_cntr + 1]; 00323 #endif 00324 } 00325 00326 return 0; 00327 } 00328 00329 /*! 00330 * @brief Set interrupt conversion source (GPIO) 00331 * @param dev[in] - Device instance 00332 * @param conv_int_source[in]- Interrupt source 00333 * @return 0 in case of success, negative error code otherwise 00334 */ 00335 int32_t ad413x_set_int_source(struct ad413x_dev *dev, 00336 adc_conv_int_source_e conv_int_source) 00337 { 00338 int32_t ret; 00339 00340 if (!dev) { 00341 return -EINVAL; 00342 } 00343 00344 ret = ad413x_reg_write_msk(dev, 00345 AD413X_REG_IO_CTRL, 00346 AD413X_INT_PIN_SEL(conv_int_source), 00347 AD4130_INT_SRC_SEL_MSK); 00348 if (ret) { 00349 return ret; 00350 } 00351 00352 return 0; 00353 } 00354 00355 /*! 00356 * @brief Set filter FS value 00357 * @param dev[in] - Device instance 00358 * @param fs[in]- FS value 00359 * @param preset[in] - Channel setup 00360 * @return 0 in case of success, negative error code otherwise 00361 */ 00362 int32_t ad413x_set_filter_fs(struct ad413x_dev *dev, uint32_t fs, 00363 uint8_t preset) 00364 { 00365 int32_t ret; 00366 00367 if (!dev) { 00368 return -EINVAL; 00369 } 00370 00371 ret = ad413x_reg_write_msk(dev, 00372 AD413X_REG_FILTER(preset), 00373 AD413X_FS_N(fs), 00374 AD4130_FILTER_FS_MSK); 00375 if (ret) { 00376 return ret; 00377 } 00378 00379 return 0; 00380 }
Generated on Wed Jul 20 2022 12:42:25 by 1.7.2