Example Program for EVAL-AD7606
Dependencies: platform_drivers
iio_ad7606.c
00001 /***************************************************************************//** 00002 * @file iio_ad7606.c 00003 * @brief Implementation of AD7606 IIO application interfaces 00004 * @details This module acts as an interface for AD7606 IIO application 00005 ******************************************************************************** 00006 * Copyright (c) 2020-2021 Analog Devices, Inc. 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 <inttypes.h> 00018 #include <string.h> 00019 #include <errno.h> 00020 #include <math.h> 00021 00022 #include "app_config.h" 00023 #include "iio_ad7606.h" 00024 #include "platform_support.h" 00025 #include "spi_extra.h" 00026 #include "gpio_extra.h" 00027 #include "uart_extra.h" 00028 #include "irq_extra.h" 00029 #include "error.h" 00030 00031 #include "ad7606.h" 00032 #include "adc_data_capture.h" 00033 #include "ad7606_support.h" 00034 #include "ad7606_user_config.h" 00035 00036 /******************************************************************************/ 00037 /************************ Macros/Constants ************************************/ 00038 /******************************************************************************/ 00039 00040 /* ADC data to Voltage conversion scale factor for IIO client */ 00041 #define DEFAULT_SCALE ((DEFAULT_CHN_RANGE / ADC_MAX_COUNT_BIPOLAR) * 1000) 00042 00043 /* LSB Threshold to entry into open circuit detection as per datasheet */ 00044 #define MANUAL_OPEN_DETECT_ENTRY_TRHLD 350 00045 00046 /* Manual open circuit detect LSB threshold @50K Rpd as per datasheet */ 00047 #define MANUAL_OPEN_DETECT_THRESHOLD_RPD50K 20 00048 00049 /* Number of consecutive conversions (N) in manual open circuit detection */ 00050 #define MANUAL_OPEN_DETECT_CONV_CNTS 10 00051 00052 /* LSB Threshold b/w consecutive N conversions */ 00053 #define MANUAL_OPEN_DETECT_CONV_TRSHLD 10 00054 00055 /* Number of common mode conversions in manual open circuit detect */ 00056 #define MANUAL_OPEN_DETECT_CM_CNV_CNT 3 00057 00058 /* Max number of queue counts for auto mode open circuit detection */ 00059 #define AUTO_OPEN_DETECT_QUEUE_MAX_CNT 128 00060 #define AUTO_OPEN_DETECT_QUEUE_EXTRA_CONV_CNT 15 00061 00062 /* Maximum ADC calibration gain value */ 00063 #define ADC_CALIBRATION_GAIN_MAX 64.0 00064 00065 #if defined(DEV_AD7606C_18) 00066 #define OFFSET_REG_RESOLUTION 4 00067 #else 00068 #define OFFSET_REG_RESOLUTION 1 00069 #endif 00070 00071 /* Bytes per sample. This count should divide the total 256 bytes into 'n' equivalent 00072 * ADC samples as IIO library requests only 256bytes of data at a time in a given 00073 * data read query. 00074 * For 1 to 8-bit ADC, bytes per sample = 1 (2^0) 00075 * For 9 to 16-bit ADC, bytes per sample = 2 (2^1) 00076 * For 17 to 32-bit ADC, bytes per sample = 4 (2^2) 00077 **/ 00078 #if (AD7606X_ADC_RESOLUTION == 18) 00079 #define BYTES_PER_SAMPLE sizeof(uint32_t) // For ADC resolution of 18-bits 00080 #else 00081 #define BYTES_PER_SAMPLE sizeof(uint16_t) // For ADC resolution of 16-bits 00082 #endif 00083 00084 /* Number of data storage bits (needed for IIO client to plot ADC data) */ 00085 #define CHN_STORAGE_BITS (BYTES_PER_SAMPLE * 8) 00086 00087 /******************************************************************************/ 00088 /*************************** Types Declarations *******************************/ 00089 /******************************************************************************/ 00090 00091 /* IIO interface descriptor */ 00092 static struct iio_desc *p_ad7606_iio_desc; 00093 00094 /** 00095 * Device name. 00096 */ 00097 static const char dev_name[] = ACTIVE_DEVICE_NAME; 00098 00099 /** 00100 * Pointer to the struct representing the AD7606 IIO device 00101 */ 00102 struct ad7606_dev *p_ad7606_dev_inst = NULL; 00103 00104 00105 /* Device attributes with default values */ 00106 00107 /* Power down mode values string representation (possible values specified in datasheet) */ 00108 static char *operating_mode_str[] = { 00109 "0 (Normal Mode)", 00110 "1 (Standby Mode)", 00111 "2 (Auto Standby Mode)", 00112 "3 (Shutdown Mode)" 00113 }; 00114 00115 /* Bandwidth values string */ 00116 static char *bandwidth_str[] = { 00117 "0 (Low)", 00118 "1 (High)" 00119 }; 00120 00121 /* Channel range values string representation (possible values specified in datasheet) */ 00122 static char *chn_range_str[] = { 00123 #if defined(DEV_AD7606B) 00124 "0 (+/-2.5V SE)", "1 (+/-5.0V SE)", "2 (+/-10.0V SE)", "3 (+/-10.0V SE)", 00125 "4 (+/-10.0V SE)", "5 (+/-10.0V SE)", "6 (+/-10.0V SE)", "7 (+/-10.0V SE)", 00126 "8 (+/-10.0V SE)", "9 (+/-10.0V SE)", "10 (+/-10.0V SE)", "11 (+/-10.0V SE)", 00127 #elif defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) 00128 "0 (+/-2.5V SE)", "1 (+/-5.0V SE)", "2 (+/-6.25V SE)", "3 (+/-10.0V SE)", 00129 "4 (+/-12.5V SE)", "5 (0 to 5V SE)", "6 (0 to 10V SE)", "7 (0 to 12.5V SE)", 00130 "8 (+/-5.0V Diff)", "9 (+/-10.0V Diff)", "10 (+/-12.5V Diff)", "11 (+/-20.0V Diff)" 00131 #elif defined(DEV_AD7609) 00132 "0 (+/-10.0V SE)", "1 (+/-20.0V SE)" 00133 #else 00134 "0 (+/-5.0V SE)", "1 (+/-10.0V SE)" 00135 #endif 00136 }; 00137 00138 /* Oversampling values string representation (possible values specified in datasheet) */ 00139 static char *oversampling_val_str[] = { 00140 "0 (no oversampling)", "1 (oversampling by 2)", "2 (oversampling by 4)", 00141 "3 (oversampling by 8)", "4 (oversampling by 16)", "5 (oversampling by 32)", 00142 "6 (oversampling by 64)", "7 (oversampling by 128)", "8 (oversampling by 256)" 00143 }; 00144 00145 00146 /* Channel range values string representation (possible values specified in datasheet) */ 00147 static float chn_range_val[] = { 00148 #if defined(DEV_AD7606B) 00149 2.5, 5.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0, 10.0 00150 #elif defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) 00151 2.5, 5.0, 6.25, 10.0, 12.5, 5.0, 10.0, 12.5, 5.0, 10.0, 12.5, 20.0 00152 #elif defined(DEV_AD7609) 00153 10.0, 20.0 00154 #else 00155 5.0, 10.0 00156 #endif 00157 }; 00158 00159 /* Range value per channel */ 00160 static float attr_chn_range[AD7606X_ADC_CHANNELS] = { 00161 DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, 00162 DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE, DEFAULT_CHN_RANGE 00163 }; 00164 00165 /* Scale value per channel */ 00166 static float attr_scale_val[AD7606X_ADC_CHANNELS] = { 00167 DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, 00168 DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE 00169 }; 00170 00171 /* Scale value per channel */ 00172 static polarity_e attr_polarity_val[AD7606X_ADC_CHANNELS] = { 00173 BIPOLAR, BIPOLAR, BIPOLAR, BIPOLAR, 00174 BIPOLAR, BIPOLAR, BIPOLAR, BIPOLAR 00175 }; 00176 00177 /* Channel range */ 00178 typedef enum { 00179 LOW, 00180 HIGH 00181 } range_e; 00182 00183 /* Open detect auto mode QUEUE register count */ 00184 static uint8_t open_detect_queue_cnts[AD7606X_ADC_CHANNELS] = { 00185 0 00186 }; 00187 00188 /* ADC gain calibration Rfilter value (in Kohms) */ 00189 static uint8_t gain_calibration_reg_val[AD7606X_ADC_CHANNELS] = { 00190 0 00191 }; 00192 00193 /* Flag to trigger new background conversion and capture when READBUFF command is issued */ 00194 static bool adc_data_capture_started = false; 00195 00196 /* Gain calibration status */ 00197 static bool gain_calibration_done = false; 00198 00199 /* Open circuit mode detection flags */ 00200 static bool open_circuit_detection_done = false; 00201 static bool open_circuit_detection_error = false; 00202 static bool open_circuit_detect_read_done = false; 00203 00204 /******************************************************************************/ 00205 /************************ Functions Prototypes ********************************/ 00206 /******************************************************************************/ 00207 00208 static float get_vltg_conv_scale_factor(float chn_range, polarity_e polarity); 00209 static void save_local_attributes(void); 00210 00211 /******************************************************************************/ 00212 /************************ Functions Definitions *******************************/ 00213 /******************************************************************************/ 00214 00215 /*! 00216 * @brief Getter/Setter for the scale attribute value 00217 * @param device- pointer to IIO device structure 00218 * @param buf- pointer to buffer holding attribute value 00219 * @param len- length of buffer string data 00220 * @param channel- pointer to IIO channel structure 00221 * @return Number of characters read/written 00222 */ 00223 static ssize_t get_chn_scale(void *device, 00224 char *buf, 00225 size_t len, 00226 const struct iio_ch_info *channel, 00227 intptr_t id) 00228 { 00229 return (ssize_t) sprintf(buf, "%f", attr_scale_val[channel->ch_num]); 00230 } 00231 00232 static ssize_t set_chn_scale(void *device, 00233 char *buf, 00234 size_t len, 00235 const struct iio_ch_info *channel, 00236 intptr_t id) 00237 { 00238 float scale; 00239 00240 (void)sscanf(buf, "%f", &scale); 00241 00242 if (scale > 0.0) { 00243 attr_scale_val[channel->ch_num] = scale; 00244 return len; 00245 } 00246 00247 return -EINVAL; 00248 } 00249 00250 00251 /*! 00252 * @brief Getter/Setter for the sampling frequency attribute value 00253 * @param device- pointer to IIO device structure 00254 * @param buf- pointer to buffer holding attribute value 00255 * @param len- length of buffer string data 00256 * @param channel- pointer to IIO channel structure 00257 * @return Number of characters read/written 00258 * @Note This attribute is used to define the timeout period in IIO 00259 * client during data capture. 00260 * Timeout = (number of requested samples * (1/sampling frequency)) + 1sec 00261 * e.g. if sampling frequency = 1KSPS and requested samples = 400 00262 * Timeout = (400 * 0.001) + 1 = 1.4sec 00263 */ 00264 static ssize_t get_sampling_frequency(void *device, 00265 char *buf, 00266 size_t len, 00267 const struct iio_ch_info *channel, 00268 intptr_t id) 00269 { 00270 return (ssize_t) sprintf(buf, "%d", SAMPLING_RATE); 00271 } 00272 00273 static ssize_t set_sampling_frequency(void *device, 00274 char *buf, 00275 size_t len, 00276 const struct iio_ch_info *channel, 00277 intptr_t id) 00278 { 00279 /* NA- Can't set sampling frequency value */ 00280 return len; 00281 } 00282 00283 00284 /*! 00285 * @brief Getter/Setter for the raw attribute value 00286 * @param device- pointer to IIO device structure 00287 * @param buf- pointer to buffer holding attribute value 00288 * @param len- length of buffer string data 00289 * @param channel- pointer to IIO channel structure 00290 * @return Number of characters read/written 00291 */ 00292 static ssize_t get_chn_raw(void *device, 00293 char *buf, 00294 size_t len, 00295 const struct iio_ch_info *channel, 00296 intptr_t id) 00297 { 00298 int32_t adc_data_raw; 00299 00300 /* Capture the raw adc data */ 00301 if (read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw) != SUCCESS) { 00302 return -EINVAL; 00303 } 00304 00305 return (ssize_t) sprintf(buf, "%d", adc_data_raw); 00306 } 00307 00308 static ssize_t set_chn_raw(void *device, 00309 char *buf, 00310 size_t len, 00311 const struct iio_ch_info *channel, 00312 intptr_t id) 00313 { 00314 /* NA- Can't set raw value */ 00315 return len; 00316 } 00317 00318 00319 /*! 00320 * @brief Getter/Setter for the operating mode attribute value 00321 * @param device- pointer to IIO device structure 00322 * @param buf- pointer to buffer holding attribute value 00323 * @param len- length of buffer string data 00324 * @param channel- pointer to IIO channel structure 00325 * @return Number of characters read/written 00326 * @note Available only for AD7606B and AD7606C 00327 */ 00328 static ssize_t get_operating_mode(void *device, 00329 char *buf, 00330 size_t len, 00331 const struct iio_ch_info *channel, 00332 intptr_t id) 00333 { 00334 uint8_t read_val; 00335 uint8_t operating_mode_value; 00336 00337 if (ad7606_spi_reg_read(device, AD7606_REG_CONFIG, &read_val) == SUCCESS) { 00338 operating_mode_value = (read_val & AD7606_CONFIG_OPERATION_MODE_MSK); 00339 00340 if (operating_mode_value < sizeof(operating_mode_str) / sizeof( 00341 operating_mode_str[0])) { 00342 return (ssize_t)sprintf(buf, "%s", operating_mode_str[operating_mode_value]); 00343 } 00344 } 00345 00346 return -EINVAL; 00347 } 00348 00349 static ssize_t set_operating_mode(void *device, 00350 char *buf, 00351 size_t len, 00352 const struct iio_ch_info *channel, 00353 intptr_t id) 00354 { 00355 uint8_t operating_mode_value; 00356 00357 (void)sscanf(buf, "%d", &operating_mode_value); 00358 00359 if (operating_mode_value < sizeof(operating_mode_str) / sizeof( 00360 operating_mode_str[0])) { 00361 if (ad7606_spi_write_mask(device, 00362 AD7606_REG_CONFIG, 00363 AD7606_CONFIG_OPERATION_MODE_MSK, 00364 operating_mode_value) == SUCCESS) { 00365 return len; 00366 } 00367 } 00368 00369 return -EINVAL; 00370 } 00371 00372 00373 /*! 00374 * @brief Getter/Setter for the power down mode attribute value 00375 * @param device- pointer to IIO device structure 00376 * @param buf- pointer to buffer holding attribute value 00377 * @param len- length of buffer string data 00378 * @param channel- pointer to IIO channel structure 00379 * @return Number of characters read/written 00380 * @note Available for all devices except AD7606B and AD7606C 00381 */ 00382 static ssize_t get_power_down_mode(void *device, 00383 char *buf, 00384 size_t len, 00385 const struct iio_ch_info *channel, 00386 intptr_t id) 00387 { 00388 uint8_t gpio_stby_val; 00389 uint8_t gpio_range_val; 00390 00391 if (gpio_get_value(((struct ad7606_dev *)device)->gpio_stby_n, 00392 &gpio_stby_val) == SUCCESS) { 00393 if (gpio_get_value(((struct ad7606_dev *)device)->gpio_range, 00394 &gpio_range_val) == SUCCESS) { 00395 00396 if (gpio_stby_val) { 00397 return sprintf(buf, "%s", operating_mode_str[AD7606_NORMAL]); 00398 } else { 00399 if (gpio_range_val) { 00400 return sprintf(buf, "%s", operating_mode_str[AD7606_STANDBY]); 00401 } else { 00402 return sprintf(buf, "%s", operating_mode_str[AD7606_SHUTDOWN]); 00403 } 00404 } 00405 } 00406 } 00407 00408 return -EINVAL; 00409 } 00410 00411 static ssize_t set_power_down_mode(void *device, 00412 char *buf, 00413 size_t len, 00414 const struct iio_ch_info *channel, 00415 intptr_t id) 00416 { 00417 uint8_t power_down_mode_value; 00418 static enum ad7606_op_mode prev_power_down_mode = AD7606_NORMAL; 00419 struct ad7606_config dev_config; 00420 00421 sscanf(buf, "%d", &power_down_mode_value); 00422 00423 if (power_down_mode_value < (sizeof(operating_mode_str) / sizeof( 00424 operating_mode_str[0]))) { 00425 00426 dev_config.op_mode = power_down_mode_value; 00427 00428 switch (power_down_mode_value) { 00429 case AD7606_NORMAL: 00430 if (ad7606_set_config(device, dev_config) == SUCCESS) { 00431 /* Reset the device if previous power down mode was either standby 00432 * or shutdown */ 00433 if (prev_power_down_mode != AD7606_NORMAL) { 00434 00435 /* Power-up wait time */ 00436 mdelay(1); 00437 00438 /* Toggle reset pin */ 00439 if (gpio_set_value(((struct ad7606_dev *)device)->gpio_reset, 00440 GPIO_HIGH) == SUCCESS) { 00441 mdelay(1); 00442 00443 if (gpio_set_value(((struct ad7606_dev *)device)->gpio_reset, 00444 GPIO_LOW) == SUCCESS) { 00445 prev_power_down_mode = AD7606_NORMAL; 00446 return len; 00447 } 00448 } 00449 } 00450 } 00451 break; 00452 00453 case AD7606_STANDBY: 00454 if (ad7606_set_config(device, dev_config) == SUCCESS) { 00455 prev_power_down_mode = AD7606_STANDBY; 00456 return len; 00457 } 00458 break; 00459 00460 case AD7606_SHUTDOWN: 00461 if (ad7606_set_config(device, dev_config) == SUCCESS) { 00462 prev_power_down_mode = AD7606_SHUTDOWN; 00463 return len; 00464 } 00465 break; 00466 00467 default: 00468 break; 00469 } 00470 } 00471 00472 return -EINVAL; 00473 } 00474 00475 00476 /*! 00477 * @brief Getter/Setter for the range attribute value 00478 * @param device- pointer to IIO device structure 00479 * @param buf- pointer to buffer holding attribute value 00480 * @param len- length of buffer string data 00481 * @param channel- pointer to IIO channel structure 00482 * @return Number of characters read/written 00483 * @note Available for all devices except AD7606B and AD7606C 00484 */ 00485 static ssize_t get_range(void *device, 00486 char *buf, 00487 size_t len, 00488 const struct iio_ch_info *channel, 00489 intptr_t id) 00490 { 00491 uint8_t gpio_range_val; 00492 struct ad7606_dev *dev = device; 00493 00494 if (gpio_get_value(dev->gpio_range, &gpio_range_val) == SUCCESS) { 00495 if (gpio_range_val) { 00496 return sprintf(buf, "%s", chn_range_str[HIGH]); 00497 } else { 00498 return sprintf(buf, "%s", chn_range_str[LOW]); 00499 } 00500 } 00501 00502 return -EINVAL; 00503 } 00504 00505 static ssize_t set_range(void *device, 00506 char *buf, 00507 size_t len, 00508 const struct iio_ch_info *channel, 00509 intptr_t id) 00510 { 00511 uint8_t range_value; 00512 struct ad7606_dev *dev = device; 00513 00514 (void)sscanf(buf, "%d", &range_value); 00515 00516 if (range_value < (sizeof(chn_range_str) / sizeof(chn_range_str[0]))) { 00517 if (range_value == LOW) { 00518 if (gpio_set_value(dev->gpio_range, GPIO_LOW) == SUCCESS) { 00519 return len; 00520 } 00521 } else { 00522 if (gpio_set_value(dev->gpio_range, GPIO_HIGH) == SUCCESS) { 00523 return len; 00524 } 00525 } 00526 } 00527 00528 return -EINVAL; 00529 } 00530 00531 00532 /*! 00533 * @brief Getter/Setter for the oversampling attribute value 00534 * @param device- pointer to IIO device structure 00535 * @param buf- pointer to buffer holding attribute value 00536 * @param len- length of buffer string data 00537 * @param channel- pointer to IIO channel structure 00538 * @return Number of characters read/written 00539 * @note Available for all devices except AD7606B and AD7606C 00540 */ 00541 static ssize_t get_oversampling(void *device, 00542 char *buf, 00543 size_t len, 00544 const struct iio_ch_info *channel, 00545 intptr_t id) 00546 { 00547 uint8_t oversampling_value; 00548 uint8_t read_val; 00549 uint8_t gpio_osr0_val; 00550 uint8_t gpio_osr1_val; 00551 uint8_t gpio_osr2_val; 00552 struct ad7606_dev *dev = device; 00553 00554 #if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) 00555 if (ad7606_spi_reg_read(device, 00556 AD7606_REG_OVERSAMPLING, 00557 &read_val) == SUCCESS) { 00558 oversampling_value = (read_val & AD7606_OVERSAMPLING_MSK); 00559 00560 if (oversampling_value < sizeof(oversampling_val_str) / sizeof( 00561 oversampling_val_str[0])) { 00562 return (ssize_t)sprintf(buf, "%s", oversampling_val_str[oversampling_value]); 00563 } 00564 } 00565 #else 00566 if (gpio_get_value(dev->gpio_os0, &gpio_osr0_val) == SUCCESS) { 00567 if (gpio_get_value(dev->gpio_os1, &gpio_osr1_val) == SUCCESS) { 00568 if (gpio_get_value(dev->gpio_os2, &gpio_osr2_val) == SUCCESS) { 00569 oversampling_value = (gpio_osr2_val << 2) | (gpio_osr1_val << 1) | 00570 gpio_osr0_val; 00571 00572 if (oversampling_value < (sizeof(oversampling_val_str) / sizeof( 00573 oversampling_val_str[0]))) { 00574 return sprintf(buf, "%s", oversampling_val_str[oversampling_value]); 00575 } 00576 } 00577 } 00578 } 00579 #endif 00580 00581 return -EINVAL; 00582 } 00583 00584 static ssize_t set_oversampling(void *device, 00585 char *buf, 00586 size_t len, 00587 const struct iio_ch_info *channel, 00588 intptr_t id) 00589 { 00590 uint8_t oversampling_value; 00591 struct ad7606_oversampling oversampling_cfg; 00592 00593 (void)sscanf(buf, "%d", &oversampling_value); 00594 00595 if (oversampling_value < (sizeof(oversampling_val_str) / sizeof( 00596 oversampling_val_str[0]))) { 00597 00598 oversampling_cfg.os_pad = 0; 00599 oversampling_cfg.os_ratio = oversampling_value; 00600 00601 ad7606_set_oversampling(device, oversampling_cfg); 00602 00603 return len; 00604 } 00605 00606 return -EINVAL; 00607 } 00608 00609 00610 /*! 00611 * @brief Getter/Setter for the bandwidth attribute value 00612 * @param device- pointer to IIO device structure 00613 * @param buf- pointer to buffer holding attribute value 00614 * @param len- length of buffer string data 00615 * @param channel- pointer to IIO channel structure 00616 * @return Number of characters read/written 00617 * @note Available for only AD7606C 00618 */ 00619 static ssize_t get_bandwidth(void *device, 00620 char *buf, 00621 size_t len, 00622 const struct iio_ch_info *channel, 00623 intptr_t id) 00624 { 00625 uint8_t bw_value; 00626 uint8_t read_val; 00627 00628 if (ad7606_spi_reg_read(device, 00629 AD7606_REG_BANDWIDTH, 00630 &read_val) == SUCCESS) { 00631 bw_value = (read_val >> (channel->ch_num)) & 0x1; 00632 00633 if (bw_value < sizeof(bandwidth_str) / sizeof( 00634 bandwidth_str[0])) { 00635 return (ssize_t)sprintf(buf, "%s", bandwidth_str[bw_value]); 00636 } 00637 } 00638 00639 return -EINVAL; 00640 } 00641 00642 static ssize_t set_bandwidth(void *device, 00643 char *buf, 00644 size_t len, 00645 const struct iio_ch_info *channel, 00646 intptr_t id) 00647 { 00648 uint8_t bw_value; 00649 uint8_t read_val; 00650 00651 (void)sscanf(buf, "%d", &bw_value); 00652 00653 if (bw_value < sizeof(bandwidth_str) / sizeof( 00654 bandwidth_str[0])) { 00655 if (ad7606_spi_reg_read(device, 00656 AD7606_REG_BANDWIDTH, 00657 &read_val) == SUCCESS) { 00658 if (bw_value) { 00659 read_val |= (1 << (channel->ch_num)); 00660 } else { 00661 read_val &= (~(1 << (channel->ch_num))); 00662 } 00663 00664 if (ad7606_spi_reg_write(device, 00665 AD7606_REG_BANDWIDTH, 00666 read_val) == SUCCESS) { 00667 return len; 00668 } 00669 } 00670 } 00671 00672 return -EINVAL; 00673 } 00674 00675 00676 /*! 00677 * @brief Getter/Setter for the channel range attribute value 00678 * @param device- pointer to IIO device structure 00679 * @param buf- pointer to buffer holding attribute value 00680 * @param len- length of buffer string data 00681 * @param channel- pointer to IIO channel structure 00682 * @return Number of characters read/written 00683 * @note Available only for AD7606B and AD7606C 00684 */ 00685 static ssize_t get_chn_range(void *device, 00686 char *buf, 00687 size_t len, 00688 const struct iio_ch_info *channel, 00689 intptr_t id) 00690 { 00691 uint8_t read_val; 00692 uint8_t chn_range; 00693 00694 if (ad7606_spi_reg_read(device, AD7606_REG_RANGE_CH_ADDR(channel->ch_num), 00695 &read_val) == SUCCESS) { 00696 if (((channel->ch_num) % 2) != 0) { 00697 read_val >>= CHANNEL_RANGE_MSK_OFFSET; 00698 chn_range = read_val; 00699 } else { 00700 chn_range = (read_val & AD7606_RANGE_CH_MSK(channel->ch_num)); 00701 } 00702 00703 if (chn_range < sizeof(chn_range_str) / sizeof(chn_range_str[0])) { 00704 attr_chn_range[channel->ch_num] = chn_range_val[chn_range]; 00705 attr_polarity_val[channel->ch_num] = ad7606_get_input_polarity(chn_range); 00706 00707 return (ssize_t)sprintf(buf, "%s", chn_range_str[chn_range]); 00708 } 00709 } 00710 00711 return -EINVAL; 00712 } 00713 00714 static ssize_t set_chn_range(void *device, 00715 char *buf, 00716 size_t len, 00717 const struct iio_ch_info *channel, 00718 intptr_t id) 00719 { 00720 uint8_t chn_range; 00721 00722 (void)sscanf(buf, "%d", &chn_range); 00723 00724 if (chn_range < sizeof(chn_range_val) / sizeof(chn_range_val[0])) { 00725 00726 /* Get the polarity of channel */ 00727 attr_polarity_val[channel->ch_num] = ad7606_get_input_polarity(chn_range); 00728 00729 attr_chn_range[channel->ch_num] = chn_range_val[chn_range]; 00730 attr_scale_val[channel->ch_num] = get_vltg_conv_scale_factor( 00731 chn_range_val[chn_range], 00732 attr_polarity_val[channel->ch_num]); 00733 00734 if (((channel->ch_num) % 2) != 0) { 00735 chn_range <<= CHANNEL_RANGE_MSK_OFFSET; 00736 } 00737 00738 if (ad7606_spi_write_mask(device, 00739 AD7606_REG_RANGE_CH_ADDR(channel->ch_num), 00740 AD7606_RANGE_CH_MSK(channel->ch_num), 00741 chn_range) == SUCCESS) { 00742 return len; 00743 } 00744 } 00745 00746 return -EINVAL; 00747 } 00748 00749 00750 /*! 00751 * @brief Getter/Setter for the channel offset attribute value 00752 * @param device- pointer to IIO device structure 00753 * @param buf- pointer to buffer holding attribute value 00754 * @param len- length of buffer string data 00755 * @param channel- pointer to IIO channel structure 00756 * @return Number of characters read/written 00757 * @note Available only for AD7606B and AD7606C 00758 */ 00759 static ssize_t get_chn_offset(void *device, 00760 char *buf, 00761 size_t len, 00762 const struct iio_ch_info *channel, 00763 intptr_t id) 00764 { 00765 uint8_t chn_offset_value; 00766 00767 if (ad7606_spi_reg_read(device, AD7606_REG_OFFSET_CH(channel->ch_num), 00768 &chn_offset_value) == SUCCESS) { 00769 return (ssize_t)sprintf(buf, "%d", chn_offset_value); 00770 } 00771 00772 return -EINVAL; 00773 } 00774 00775 static ssize_t set_chn_offset(void *device, 00776 char *buf, 00777 size_t len, 00778 const struct iio_ch_info *channel, 00779 intptr_t id) 00780 { 00781 uint8_t chn_offset_value = 0; 00782 00783 (void)sscanf(buf, "%d", &chn_offset_value); 00784 00785 if (ad7606_set_ch_offset(device, channel->ch_num, 00786 chn_offset_value) == SUCCESS) { 00787 return len; 00788 } 00789 00790 return -EINVAL; 00791 } 00792 00793 00794 /*! 00795 * @brief Getter/Setter for the channel pahse offset attribute value 00796 * @param device- pointer to IIO device structure 00797 * @param buf- pointer to buffer holding attribute value 00798 * @param len- length of buffer string data 00799 * @param channel- pointer to IIO channel structure 00800 * @return Number of characters read/written 00801 * @note Available only for AD7606B and AD7606C 00802 */ 00803 static ssize_t get_chn_phase_offset(void *device, 00804 char *buf, 00805 size_t len, 00806 const struct iio_ch_info *channel, 00807 intptr_t id) 00808 { 00809 uint8_t chn_phase_offset_value; 00810 00811 if (ad7606_spi_reg_read(device, 00812 AD7606_REG_PHASE_CH(channel->ch_num), 00813 &chn_phase_offset_value) == SUCCESS) { 00814 return (ssize_t)sprintf(buf, "%d", chn_phase_offset_value); 00815 } 00816 00817 return -EINVAL; 00818 } 00819 00820 static ssize_t set_chn_phase_offset(void *device, 00821 char *buf, 00822 size_t len, 00823 const struct iio_ch_info *channel, 00824 intptr_t id) 00825 { 00826 uint8_t chn_phase_offset_value = 0; 00827 00828 (void)sscanf(buf, "%d", &chn_phase_offset_value); 00829 00830 if (ad7606_set_ch_phase(device, channel->ch_num, 00831 chn_phase_offset_value) == SUCCESS) { 00832 return len; 00833 } 00834 00835 return -EINVAL; 00836 } 00837 00838 00839 /*! 00840 * @brief Getter/Setter for the channel temperature attribute value 00841 * @param device- pointer to IIO device structure 00842 * @param buf- pointer to buffer holding attribute value 00843 * @param len- length of buffer string data 00844 * @param channel- pointer to IIO channel structure 00845 * @return Number of characters read/written 00846 * @note Available only for AD7606B and AD7606C 00847 */ 00848 static ssize_t get_chn_temperature(void *device, 00849 char *buf, 00850 size_t len, 00851 const struct iio_ch_info *channel, 00852 intptr_t id) 00853 { 00854 int32_t adc_data_raw = 0; 00855 float temperature; 00856 float voltage; 00857 00858 /* Configure the channel multiplexer to select temperature read */ 00859 if (ad7606_spi_write_mask(device, 00860 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 00861 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 00862 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 00863 TEMPERATURE_MUX)) == SUCCESS) { 00864 00865 /* Allow to settle Mux channel */ 00866 udelay(100); 00867 00868 /* Sample the channel and read conversion result */ 00869 read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw); 00870 00871 /* Convert ADC data into equivalent voltage */ 00872 voltage = convert_adc_raw_to_voltage(adc_data_raw, 00873 attr_scale_val[channel->ch_num]); 00874 00875 /* Obtain the temperature using equation specified in device datasheet */ 00876 temperature = ((voltage - 0.69068) / 0.019328) + 25.0; 00877 00878 /* Change channel mux back to analog input */ 00879 (void)ad7606_spi_write_mask(device, 00880 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 00881 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 00882 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 00883 ANALOG_INPUT_MUX)); 00884 00885 return (ssize_t)sprintf(buf, "%f", temperature); 00886 } 00887 00888 return -EINVAL; 00889 } 00890 00891 static ssize_t set_chn_temperature(void *device, 00892 char *buf, 00893 size_t len, 00894 const struct iio_ch_info *channel, 00895 intptr_t id) 00896 { 00897 // NA- Can't set temperature 00898 return -EINVAL; 00899 } 00900 00901 00902 /*! 00903 * @brief Getter/Setter for the channel Vref attribute value 00904 * @param device- pointer to IIO device structure 00905 * @param buf- pointer to buffer holding attribute value 00906 * @param len- length of buffer string data 00907 * @param channel- pointer to IIO channel structure 00908 * @return Number of characters read/written 00909 * @note Available only for AD7606B and AD7606C 00910 */ 00911 static ssize_t get_chn_vref(void *device, 00912 char *buf, 00913 size_t len, 00914 const struct iio_ch_info *channel, 00915 intptr_t id) 00916 { 00917 float vref_voltge; 00918 int32_t adc_data_raw; 00919 00920 /* Configure the channel multiplexer to select Vref read */ 00921 if (ad7606_spi_write_mask(device, 00922 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 00923 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 00924 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 00925 VREF_MUX)) == SUCCESS) { 00926 00927 /* Allow to settle Mux channel */ 00928 udelay(100); 00929 00930 /* Sample the channel and read conversion result */ 00931 read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw); 00932 00933 /* Convert ADC data into equivalent voltage */ 00934 vref_voltge = convert_adc_raw_to_voltage(adc_data_raw, 00935 attr_scale_val[channel->ch_num]); 00936 00937 /* Divide by 4 since Vref Mux has 4x multiplier on it */ 00938 vref_voltge /= VREF_MUX_MULTIPLIER; 00939 00940 /* Change channel mux back to analog input */ 00941 (void)ad7606_spi_write_mask(device, 00942 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 00943 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 00944 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 00945 ANALOG_INPUT_MUX)); 00946 00947 return (ssize_t)sprintf(buf, "%f", vref_voltge); 00948 } 00949 00950 return -EINVAL; 00951 } 00952 00953 static ssize_t set_chn_vref(void *device, 00954 char *buf, 00955 size_t len, 00956 const struct iio_ch_info *channel, 00957 intptr_t id) 00958 { 00959 // NA- Can't set Vref 00960 return - EINVAL; 00961 } 00962 00963 00964 /*! 00965 * @brief Getter/Setter for the channel Vdrive attribute value 00966 * @param device- pointer to IIO device structure 00967 * @param buf- pointer to buffer holding attribute value 00968 * @param len- length of buffer string data 00969 * @param channel- pointer to IIO channel structure 00970 * @return Number of characters read/written 00971 * @note Available only for AD7606B and AD7606C 00972 */ 00973 static ssize_t get_chn_vdrive(void *device, 00974 char *buf, 00975 size_t len, 00976 const struct iio_ch_info *channel, 00977 intptr_t id) 00978 { 00979 float vdrive_voltge; 00980 int32_t adc_data_raw; 00981 00982 /* Configure the channel multiplexer to select Vdrive read */ 00983 if (ad7606_spi_write_mask(device, 00984 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 00985 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 00986 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 00987 VDRIVE_MUX)) == SUCCESS) { 00988 00989 /* Allow to settle Mux channel */ 00990 udelay(100); 00991 00992 /* Sample the channel and read conversion result */ 00993 read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw); 00994 00995 /* Convert ADC data into equivalent voltage */ 00996 vdrive_voltge = convert_adc_raw_to_voltage(adc_data_raw, 00997 attr_scale_val[channel->ch_num]); 00998 00999 /* Change channel mux back to analog input */ 01000 (void)ad7606_spi_write_mask(device, 01001 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 01002 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 01003 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 01004 ANALOG_INPUT_MUX)); 01005 01006 return (ssize_t)sprintf(buf, "%f", vdrive_voltge); 01007 } 01008 01009 return -EINVAL; 01010 } 01011 01012 static ssize_t set_chn_vdrive(void *device, 01013 char *buf, 01014 size_t len, 01015 const struct iio_ch_info *channel, 01016 intptr_t id) 01017 { 01018 // NA- Can't set Vdrive 01019 return - EINVAL; 01020 } 01021 01022 01023 /*! 01024 * @brief Getter/Setter for the channel ALDO attribute value 01025 * @param device- pointer to IIO device structure 01026 * @param buf- pointer to buffer holding attribute value 01027 * @param len- length of buffer string data 01028 * @param channel- pointer to IIO channel structure 01029 * @return Number of characters read/written 01030 * @note Available only for AD7606B and AD7606C 01031 */ 01032 static ssize_t get_chn_aldo(void *device, 01033 char *buf, 01034 size_t len, 01035 const struct iio_ch_info *channel, 01036 intptr_t id) 01037 { 01038 float aldo_voltge; 01039 int32_t adc_data_raw; 01040 01041 /* Configure the channel multiplexer to select ALDO read */ 01042 if (ad7606_spi_write_mask(device, 01043 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 01044 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 01045 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 01046 ALDO_MUX)) == SUCCESS) { 01047 01048 /* Allow to settle Mux channel */ 01049 udelay(100); 01050 01051 /* Sample the channel and read conversion result */ 01052 read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw); 01053 01054 /* Convert ADC data into equivalent voltage */ 01055 aldo_voltge = convert_adc_raw_to_voltage(adc_data_raw, 01056 attr_scale_val[channel->ch_num]); 01057 01058 /* Divide by 4 since ALDO Mux has 4x multiplier on it */ 01059 aldo_voltge /= VREF_MUX_MULTIPLIER; 01060 01061 /* Change channel mux back to analog input */ 01062 (void)ad7606_spi_write_mask(device, 01063 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 01064 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 01065 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 01066 ANALOG_INPUT_MUX)); 01067 01068 return (ssize_t)sprintf(buf, "%f", aldo_voltge); 01069 } 01070 01071 return -EINVAL; 01072 } 01073 01074 static ssize_t set_chn_aldo(void *device, 01075 char *buf, 01076 size_t len, 01077 const struct iio_ch_info *channel, 01078 intptr_t id) 01079 { 01080 // NA- Can't set ALDO 01081 return - EINVAL; 01082 } 01083 01084 01085 /*! 01086 * @brief Getter/Setter for the channel DLDO attribute value 01087 * @param device- pointer to IIO device structure 01088 * @param buf- pointer to buffer holding attribute value 01089 * @param len- length of buffer string data 01090 * @param channel- pointer to IIO channel structure 01091 * @return Number of characters read/written 01092 * @note Available only for AD7606B and AD7606C 01093 */ 01094 static ssize_t get_chn_dldo(void *device, 01095 char *buf, 01096 size_t len, 01097 const struct iio_ch_info *channel, 01098 intptr_t id) 01099 { 01100 float dldo_voltge; 01101 int32_t adc_data_raw; 01102 01103 /* Configure the channel multiplexer to select DLDO read */ 01104 if (ad7606_spi_write_mask(device, 01105 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 01106 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 01107 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 01108 DLDO_MUX)) == SUCCESS) { 01109 01110 /* Allow to settle Mux channel */ 01111 udelay(100); 01112 01113 /* Sample the channel and read conversion result */ 01114 read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw); 01115 01116 /* Convert ADC data into equivalent voltage */ 01117 dldo_voltge = convert_adc_raw_to_voltage(adc_data_raw, 01118 attr_scale_val[channel->ch_num]); 01119 01120 /* Divide by 4 since ALDO Mux has 4x multiplier on it */ 01121 dldo_voltge /= VREF_MUX_MULTIPLIER; 01122 01123 /* Change channel mux back to analog input */ 01124 (void)ad7606_spi_write_mask(device, 01125 AD7606_REG_DIAGNOSTIC_MUX_CH(channel->ch_num), 01126 AD7606_DIAGN_MUX_CH_MSK(channel->ch_num), 01127 AD7606_DIAGN_MUX_CH_VAL((channel->ch_num), 01128 ANALOG_INPUT_MUX)); 01129 01130 return (ssize_t)sprintf(buf, "%f", dldo_voltge); 01131 } 01132 01133 return -EINVAL; 01134 } 01135 01136 static ssize_t set_chn_dldo(void *device, 01137 char *buf, 01138 size_t len, 01139 const struct iio_ch_info *channel, 01140 intptr_t id) 01141 { 01142 // NA- Can't set DLDO 01143 return - EINVAL; 01144 } 01145 01146 01147 /*! 01148 * @brief Getter/Setter for the channel open circuit detect manual attribute value 01149 * @param device- pointer to IIO device structure 01150 * @param buf- pointer to buffer holding attribute value 01151 * @param len- length of buffer string data 01152 * @param channel- pointer to IIO channel structure 01153 * @return Number of characters read/written 01154 */ 01155 static ssize_t get_chn_open_circuit_detect_manual(void *device, 01156 char *buf, 01157 size_t len, 01158 const struct iio_ch_info *channel, 01159 intptr_t id) 01160 { 01161 int32_t prev_adc_code, curr_adc_code; 01162 bool open_detect_flag = false; 01163 bool open_detect_done = false; 01164 uint8_t cnt; 01165 01166 /* Enter into manual open circuit detection mode */ 01167 do { 01168 if (ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 1) == SUCCESS) { 01169 /* Read the ADC on selected chnnel (first reading post open circuit detection start) */ 01170 read_single_sample(channel->ch_num, (uint32_t *)&prev_adc_code); 01171 01172 /* Perform N conversions and monitor the code delta */ 01173 for (cnt = 0; cnt < MANUAL_OPEN_DETECT_CONV_CNTS; cnt++) { 01174 /* Check if code is within 350LSB (nearest ZS code) */ 01175 if (prev_adc_code >= 0 && prev_adc_code < MANUAL_OPEN_DETECT_ENTRY_TRHLD) { 01176 /* Perform next conversion and read the result */ 01177 read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code); 01178 01179 /* Check if delta b/w current and previus reading is within 10 LSB code */ 01180 if (abs(curr_adc_code - prev_adc_code) > MANUAL_OPEN_DETECT_CONV_TRSHLD) { 01181 open_detect_done = true; 01182 break; 01183 } 01184 01185 /* Get the previous code */ 01186 prev_adc_code = curr_adc_code; 01187 } else { 01188 open_detect_done = true; 01189 break; 01190 } 01191 } 01192 01193 /* Break if open circuit detection aborted (in case above conditions not met) */ 01194 if (open_detect_done) 01195 break; 01196 01197 /* Set common mode high (enabling open circuit detect on selected channel) */ 01198 if (ad7606_spi_reg_write(device, 01199 AD7606_REG_OPEN_DETECT_ENABLE, 01200 (1 << (channel->ch_num))) == SUCCESS) { 01201 01202 /* Perform next conversions (~2-3) and read the result (with common mode set high) */ 01203 for (cnt = 0; cnt < MANUAL_OPEN_DETECT_CM_CNV_CNT; cnt++) { 01204 udelay(100); 01205 read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code); 01206 } 01207 01208 /* Check if delta b/w common mode high code and previous N conversion code is > threshold */ 01209 if ((curr_adc_code - prev_adc_code) < MANUAL_OPEN_DETECT_THRESHOLD_RPD50K) { 01210 open_detect_done = true; 01211 break; 01212 } 01213 } else { 01214 return -EINVAL; 01215 } 01216 01217 /* Break if open circuit detection aborted (in case above conditions not met) */ 01218 if (open_detect_done) 01219 break; 01220 01221 /* Set common mode low (disabling open circuit detect on channel) */ 01222 if (ad7606_spi_reg_write(device, 01223 AD7606_REG_OPEN_DETECT_ENABLE, 01224 0) == SUCCESS) { 01225 /* Perform next conversion and read the result (with common mode set low) */ 01226 read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code); 01227 01228 /* Check if delta b/w common mode low code and previous N conversion code is < threshold */ 01229 if (abs(curr_adc_code - prev_adc_code) < MANUAL_OPEN_DETECT_THRESHOLD_RPD50K) { 01230 open_detect_flag = true; 01231 open_detect_done = true; 01232 } 01233 } else { 01234 return -EINVAL; 01235 } 01236 } else { 01237 return -EINVAL; 01238 } 01239 } while (0); 01240 01241 /* Disable open detect mode */ 01242 (void)ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 0); 01243 01244 if (open_detect_done) { 01245 if (open_detect_flag) { 01246 strcpy(buf, "Open Circuit Detected"); 01247 } else { 01248 strcpy(buf, "Open Circuit Not Detected"); 01249 } 01250 01251 return len; 01252 } 01253 01254 return -EINVAL; 01255 } 01256 01257 static ssize_t set_chn_open_circuit_detect_manual(void *device, 01258 char *buf, 01259 size_t len, 01260 const struct iio_ch_info *channel, 01261 intptr_t id) 01262 { 01263 // NA- Can't set open circuit detect 01264 return - EINVAL; 01265 } 01266 01267 01268 /*! 01269 * @brief Getter/Setter for the channel open circuit detect auto attribute value 01270 * @param device- pointer to IIO device structure 01271 * @param buf- pointer to buffer holding attribute value 01272 * @param len- length of buffer string data 01273 * @param channel- pointer to IIO channel structure 01274 * @return Number of characters read/written 01275 */ 01276 static ssize_t get_chn_open_circuit_detect_auto(void *device, 01277 char *buf, 01278 size_t len, 01279 const struct iio_ch_info *channel, 01280 intptr_t id) 01281 { 01282 if (open_circuit_detect_read_done) { 01283 open_circuit_detect_read_done = false; 01284 01285 if (open_circuit_detection_error) { 01286 strcpy(buf, "Error!!"); 01287 } 01288 01289 if (open_circuit_detection_done) { 01290 strcpy(buf, "Open Circuit Detected"); 01291 } else { 01292 strcpy(buf, "Open Circuit Not Detected"); 01293 } 01294 01295 return len; 01296 } 01297 01298 return (ssize_t)sprintf(buf, "OPEN_DETECT_QUEUE: %d", 01299 open_detect_queue_cnts[channel->ch_num]); 01300 } 01301 01302 static ssize_t set_chn_open_circuit_detect_auto(void *device, 01303 char *buf, 01304 size_t len, 01305 const struct iio_ch_info *channel, 01306 intptr_t id) 01307 { 01308 uint8_t data; 01309 uint8_t open_detect_flag = false; 01310 int32_t rw_status = FAILURE; 01311 uint16_t conv_cnts; 01312 01313 (void)sscanf(buf, "%d", &data); 01314 open_circuit_detection_error = false; 01315 01316 if ((data > 1 && data <= AUTO_OPEN_DETECT_QUEUE_MAX_CNT) && (buf[0] >= '0' 01317 && buf[0] <= '9')) { 01318 open_detect_queue_cnts[channel->ch_num] = data; 01319 01320 /* Enter into open circuit auto open detect mode */ 01321 if (ad7606_spi_reg_write(device, 01322 AD7606_REG_OPEN_DETECT_QUEUE, 01323 open_detect_queue_cnts[channel->ch_num]) == SUCCESS) { 01324 /* Enable open circuit detection on selected channel */ 01325 if (ad7606_spi_reg_write(device, 01326 AD7606_REG_OPEN_DETECT_ENABLE, 01327 (1 << (channel->ch_num))) == SUCCESS) { 01328 /* Monitor the open detect flag for max N+15 (open detect queue count) conversions. 01329 * Note: In ideal scenario, the open detect flash should be monitored continuously while 01330 * background N conversions are in progress */ 01331 for (conv_cnts = 0; 01332 conv_cnts < (open_detect_queue_cnts[channel->ch_num] + 01333 AUTO_OPEN_DETECT_QUEUE_EXTRA_CONV_CNT); 01334 conv_cnts++) { 01335 if (ad7606_convst(device) == SUCCESS) { 01336 udelay(100); 01337 01338 /* Monitor the open detect flag */ 01339 if (ad7606_spi_reg_read(device, 01340 AD7606_REG_OPEN_DETECTED, 01341 &open_detect_flag) == SUCCESS) { 01342 open_detect_flag >>= (channel->ch_num); 01343 open_detect_flag &= 0x1; 01344 01345 rw_status = SUCCESS; 01346 if (open_detect_flag) { 01347 break; 01348 } 01349 } else { 01350 rw_status = FAILURE; 01351 break; 01352 } 01353 } else { 01354 rw_status = FAILURE; 01355 break; 01356 } 01357 } 01358 } 01359 } 01360 01361 /* Disable open detect mode and clear open detect flag */ 01362 (void)ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 0); 01363 (void)ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECTED, 0xFF); 01364 01365 open_detect_queue_cnts[channel->ch_num] = 0; 01366 01367 if (rw_status == SUCCESS) { 01368 if (open_detect_flag) { 01369 open_circuit_detection_done = true; 01370 } else { 01371 open_circuit_detection_done = false; 01372 } 01373 01374 open_circuit_detect_read_done = true; 01375 return len; 01376 } 01377 } 01378 01379 open_circuit_detection_error = true; 01380 return -EINVAL; 01381 } 01382 01383 01384 /*! 01385 * @brief Getter/Setter for the adc offset calibration 01386 * @param device- pointer to IIO device structure 01387 * @param buf- pointer to buffer holding attribute value 01388 * @param len- length of buffer string data 01389 * @param channel- pointer to IIO channel structure 01390 * @return Number of characters read/written 01391 */ 01392 static ssize_t get_chn_calibrate_adc_offset(void *device, 01393 char *buf, 01394 size_t len, 01395 const struct iio_ch_info *channel, 01396 intptr_t id) 01397 { 01398 float lsb_voltage; 01399 float adc_voltage; 01400 polarity_e polarity = attr_polarity_val[channel->ch_num]; 01401 int32_t adc_raw_data; 01402 int8_t chn_offset; 01403 01404 /* Perform the system offset calibration */ 01405 01406 if (polarity == UNIPOLAR) { 01407 lsb_voltage = attr_chn_range[channel->ch_num] / ADC_MAX_COUNT_UNIPOLAR; 01408 } else { 01409 lsb_voltage = attr_chn_range[channel->ch_num] / ADC_MAX_COUNT_BIPOLAR; 01410 } 01411 01412 /* Sample and read the ADC channel */ 01413 read_single_sample(channel->ch_num, (uint32_t *)&adc_raw_data); 01414 01415 /* Get an equivalent ADC voltage */ 01416 adc_voltage = convert_adc_raw_to_voltage(adc_raw_data, 01417 attr_scale_val[channel->ch_num]); 01418 01419 /* Calculate the channel offset and write it to offset register */ 01420 chn_offset = -(adc_voltage / lsb_voltage / OFFSET_REG_RESOLUTION); 01421 01422 if (ad7606_set_ch_offset(device, channel->ch_num, 01423 chn_offset) == SUCCESS) { 01424 return sprintf(buf, "%s", "ADC Calibration Done"); 01425 } 01426 01427 return -EINVAL; 01428 } 01429 01430 static ssize_t set_chn_calibrate_adc_offset(void *device, 01431 char *buf, 01432 size_t len, 01433 const struct iio_ch_info *channel, 01434 intptr_t id) 01435 { 01436 // NA- Can't set open circuit detect 01437 return - EINVAL; 01438 } 01439 01440 01441 /*! 01442 * @brief Getter/Setter for the adc gain calibration 01443 * @param device- pointer to IIO device structure 01444 * @param buf- pointer to buffer holding attribute value 01445 * @param len- length of buffer string data 01446 * @param channel- pointer to IIO channel structure 01447 * @return Number of characters read/written 01448 */ 01449 static ssize_t get_chn_calibrate_adc_gain(void *device, 01450 char *buf, 01451 size_t len, 01452 const struct iio_ch_info *channel, 01453 intptr_t id) 01454 { 01455 uint8_t read_val; 01456 01457 if (gain_calibration_done) { 01458 /* Get calibration status for previous gain value write event */ 01459 gain_calibration_done = false; 01460 return sprintf(buf, "Calibration Done (Rfilter=%d K)", 01461 gain_calibration_reg_val[channel->ch_num]); 01462 } 01463 01464 /* Return gain value when normal read event is triggered */ 01465 if (ad7606_spi_reg_read(device, 01466 AD7606_REG_GAIN_CH(channel->ch_num), 01467 &read_val) == SUCCESS) { 01468 gain_calibration_reg_val[channel->ch_num] = (read_val & AD7606_GAIN_MSK); 01469 return sprintf(buf, "Rfilter= %d K", 01470 gain_calibration_reg_val[channel->ch_num]); 01471 } 01472 01473 return -EINVAL; 01474 } 01475 01476 static ssize_t set_chn_calibrate_adc_gain(void *device, 01477 char *buf, 01478 size_t len, 01479 const struct iio_ch_info *channel, 01480 intptr_t id) 01481 { 01482 float data; 01483 01484 if (buf[0] >= '0' && buf[0] <= '9') { 01485 (void)sscanf(buf, "%f", &data); 01486 01487 if (data >= 0 && data < ADC_CALIBRATION_GAIN_MAX) { 01488 /* Get the nearest value of unsigned integer */ 01489 gain_calibration_reg_val[channel->ch_num] = (uint8_t)(round(data)); 01490 01491 /* Perform the gain calibration by writing gain value into gain register */ 01492 if (ad7606_set_ch_gain(device, 01493 channel->ch_num, 01494 gain_calibration_reg_val[channel->ch_num]) == SUCCESS) { 01495 gain_calibration_done = true; 01496 return len; 01497 } 01498 } 01499 } 01500 01501 return -EINVAL; 01502 } 01503 01504 01505 /*! 01506 * @brief Read the debug register value 01507 * @param dev- Pointer to IIO device instance 01508 * @param reg- Register address to read from 01509 * @param readval- Pointer to variable to read data into 01510 * @return SUCCESS in case of success, negative value otherwise 01511 */ 01512 int32_t debug_reg_read(void *dev, uint32_t reg, uint32_t *readval) 01513 { 01514 /* Read the data from device */ 01515 if (reg <= NUM_OF_REGISTERS) { 01516 if ((ad7606_spi_reg_read(dev, reg, (uint8_t *)readval) == SUCCESS)) { 01517 return SUCCESS; 01518 } 01519 } 01520 01521 return FAILURE; 01522 } 01523 01524 01525 /*! 01526 * @brief Write into the debug register 01527 * @param dev- Pointer to IIO device instance 01528 * @param reg- Register address to write into 01529 * @param writeval- Register value to write 01530 * @return SUCCESS in case of success, negative value otherwise 01531 */ 01532 int32_t debug_reg_write(void *dev, uint32_t reg, uint32_t writeval) 01533 { 01534 if (reg <= NUM_OF_REGISTERS) { 01535 if ((ad7606_spi_reg_write(dev, reg, (uint8_t)writeval) == SUCCESS)) { 01536 save_local_attributes(); 01537 return SUCCESS; 01538 } 01539 } 01540 01541 return FAILURE; 01542 } 01543 01544 01545 /** 01546 * @brief Read buffer data corresponding to AD7606 IIO device 01547 * @param dev_instance[in] - IIO device instance 01548 * @param pbuf[out] - Pointer to output data buffer 01549 * @return SUCCESS in case of success or negative value otherwise 01550 */ 01551 static ssize_t iio_ad7606_read_data(void *dev_instance, 01552 char *pbuf, 01553 size_t offset, 01554 size_t bytes_count, 01555 uint32_t ch_mask) 01556 { 01557 if (adc_data_capture_started == false) { 01558 start_data_capture(ch_mask, AD7606X_ADC_CHANNELS); 01559 adc_data_capture_started = true; 01560 } 01561 01562 /* Read the buffered data */ 01563 return (ssize_t)read_buffered_data(pbuf, 01564 bytes_count, 01565 offset, 01566 ch_mask, 01567 BYTES_PER_SAMPLE); 01568 } 01569 01570 01571 /** 01572 * @brief Transfer the device data into memory (optional) 01573 * @param dev_instance[in] - IIO device instance 01574 * @param bytes_count[in] - Number of bytes to read 01575 * @param ch_mask[in] - Channels select mask 01576 * @return SUCCESS in case of success or negative value otherwise 01577 */ 01578 static ssize_t iio_ad7606_transfer_dev_data(void *dev_instance, 01579 size_t bytes_count, 01580 uint32_t ch_mask) 01581 { 01582 /* The function insures that data is first read into memory from the device. 01583 * This function doesn't do any sort of data transfer but it make sure data 01584 * read and it's transfer to memory from device is happening in application through 01585 * iio_ad7606_read_data() function */ 01586 01587 /* Store the requested samples count value for data capture */ 01588 store_requested_samples_count(bytes_count, BYTES_PER_SAMPLE); 01589 01590 return SUCCESS; 01591 } 01592 01593 01594 /** 01595 * @brief Perform tasks before new data transfer 01596 * @param dev_instance[in] - IIO device instance 01597 * @param ch_mask[in] - Channels select mask 01598 * @return SUCCESS in case of success or negative value otherwise 01599 */ 01600 static int32_t iio_ad7606_start_transfer(void *dev_instance, uint32_t ch_mask) 01601 { 01602 return SUCCESS; 01603 } 01604 01605 01606 /** 01607 * @brief Perform tasks before end of current data transfer 01608 * @param dev_instance[in] - IIO device instance 01609 * @return SUCCESS in case of success or negative value otherwise 01610 */ 01611 static int32_t iio_ad7606_stop_transfer(void *dev) 01612 { 01613 adc_data_capture_started = false; 01614 stop_data_capture(); 01615 01616 return SUCCESS; 01617 } 01618 01619 /********************************************************* 01620 * IIO Attributes and Structures 01621 ********************************************************/ 01622 01623 /* IIOD channels attributes list */ 01624 struct iio_attribute channel_input_attributes[] = { 01625 { 01626 .name = "raw", 01627 .show = get_chn_raw, 01628 .store = set_chn_raw, 01629 }, 01630 { 01631 .name = "scale", 01632 .show = get_chn_scale, 01633 .store = set_chn_scale, 01634 }, 01635 #if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) 01636 { 01637 .name = "chn_range", 01638 .show = get_chn_range, 01639 .store = set_chn_range, 01640 }, 01641 { 01642 .name = "offset", 01643 .show = get_chn_offset, 01644 .store = set_chn_offset, 01645 }, 01646 { 01647 .name = "chn_phase offset", 01648 .show = get_chn_phase_offset, 01649 .store = set_chn_phase_offset, 01650 }, 01651 { 01652 .name = "temperature", 01653 .show = get_chn_temperature, 01654 .store = set_chn_temperature, 01655 }, 01656 { 01657 .name = "vref", 01658 .show = get_chn_vref, 01659 .store = set_chn_vref, 01660 }, 01661 { 01662 .name = "vdrive", 01663 .show = get_chn_vdrive, 01664 .store = set_chn_vdrive, 01665 }, 01666 { 01667 .name = "ALDO", 01668 .show = get_chn_aldo, 01669 .store = set_chn_aldo, 01670 }, 01671 { 01672 .name = "DLDO", 01673 .show = get_chn_dldo, 01674 .store = set_chn_dldo, 01675 }, 01676 { 01677 .name = "open_circuit_detect_manual", 01678 .show = get_chn_open_circuit_detect_manual, 01679 .store = set_chn_open_circuit_detect_manual, 01680 }, 01681 { 01682 .name = "open_circuit_detect_auto", 01683 .show = get_chn_open_circuit_detect_auto, 01684 .store = set_chn_open_circuit_detect_auto, 01685 }, 01686 { 01687 .name = "calibrate_adc_offset", 01688 .show = get_chn_calibrate_adc_offset, 01689 .store = set_chn_calibrate_adc_offset, 01690 }, 01691 { 01692 .name = "calibrate_adc_gain", 01693 .show = get_chn_calibrate_adc_gain, 01694 .store = set_chn_calibrate_adc_gain, 01695 }, 01696 #if defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) 01697 { 01698 .name = "bandwidth", 01699 .show = get_bandwidth, 01700 .store = set_bandwidth, 01701 }, 01702 #endif 01703 #endif 01704 01705 END_ATTRIBUTES_ARRAY 01706 }; 01707 01708 /* IIOD device (global) attributes list */ 01709 static struct iio_attribute global_attributes[] = { 01710 #if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) 01711 { 01712 .name = "operating_mode", 01713 .show = get_operating_mode, 01714 .store = set_operating_mode, 01715 }, 01716 { 01717 .name = "oversampling_ratio", 01718 .show = get_oversampling, 01719 .store = set_oversampling, 01720 }, 01721 #else 01722 { 01723 .name = "power_down_mode", 01724 .show = get_power_down_mode, 01725 .store = set_power_down_mode, 01726 }, 01727 { 01728 .name = "dev_range", 01729 .show = get_range, 01730 .store = set_range, 01731 }, 01732 #endif 01733 { 01734 .name = "sampling_frequency", 01735 .show = get_sampling_frequency, 01736 .store = set_sampling_frequency, 01737 }, 01738 01739 END_ATTRIBUTES_ARRAY 01740 }; 01741 01742 /* IIOD debug attributes list */ 01743 static struct iio_attribute debug_attributes[] = { 01744 #if defined(DEV_AD7606B) || defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16) 01745 { 01746 .name = "direct_reg_access", 01747 .show = NULL, 01748 .store = NULL, 01749 }, 01750 #endif 01751 01752 END_ATTRIBUTES_ARRAY 01753 }; 01754 01755 /* IIOD channels configurations */ 01756 struct scan_type chn_scan = { 01757 .sign = 's', 01758 .realbits = CHN_STORAGE_BITS, 01759 .storagebits = CHN_STORAGE_BITS, 01760 .shift = 0, 01761 .is_big_endian = false 01762 }; 01763 01764 static struct iio_channel iio_ad7606_channels[] = { 01765 { 01766 .name = "voltage0", 01767 .ch_type = IIO_VOLTAGE, 01768 .channel = 0, 01769 .scan_index = 0, 01770 .scan_type = &chn_scan, 01771 .attributes = channel_input_attributes, 01772 .ch_out = false, 01773 .indexed = true, 01774 }, 01775 { 01776 .name = "voltage1", 01777 .ch_type = IIO_VOLTAGE, 01778 .channel = 1, 01779 .scan_index = 1, 01780 .scan_type = &chn_scan, 01781 .attributes = channel_input_attributes, 01782 .ch_out = false, 01783 .indexed = true 01784 }, 01785 { 01786 .name = "voltage2", 01787 .ch_type = IIO_VOLTAGE, 01788 .channel = 2, 01789 .scan_index = 2, 01790 .scan_type = &chn_scan, 01791 .attributes = channel_input_attributes, 01792 .ch_out = false, 01793 .indexed = true 01794 }, 01795 { 01796 .name = "voltage3", 01797 .ch_type = IIO_VOLTAGE, 01798 .channel = 3, 01799 .scan_index = 3, 01800 .scan_type = &chn_scan, 01801 .attributes = channel_input_attributes, 01802 .ch_out = false, 01803 .indexed = true 01804 }, 01805 { 01806 .name = "voltage4", 01807 .ch_type = IIO_VOLTAGE, 01808 .channel = 4, 01809 .scan_index = 4, 01810 .scan_type = &chn_scan, 01811 .attributes = channel_input_attributes, 01812 .ch_out = false, 01813 .indexed = true 01814 }, 01815 { 01816 .name = "voltage5", 01817 .ch_type = IIO_VOLTAGE, 01818 .channel = 5, 01819 .scan_index = 5, 01820 .scan_type = &chn_scan, 01821 .attributes = channel_input_attributes, 01822 .ch_out = false, 01823 .indexed = true 01824 }, 01825 { 01826 .name = "voltage6", 01827 .ch_type = IIO_VOLTAGE, 01828 .channel = 6, 01829 .scan_index = 6, 01830 .scan_type = &chn_scan, 01831 .attributes = channel_input_attributes, 01832 .ch_out = false, 01833 .indexed = true 01834 }, 01835 { 01836 .name = "voltage7", 01837 .ch_type = IIO_VOLTAGE, 01838 .channel = 7, 01839 .scan_index = 7, 01840 .scan_type = &chn_scan, 01841 .attributes = channel_input_attributes, 01842 .ch_out = false, 01843 .indexed = true 01844 } 01845 }; 01846 01847 01848 /** 01849 * @brief Init for reading/writing and parameterization of a 01850 * ad7606 IIO device 01851 * @param desc[in,out] - IIO device descriptor 01852 * @param init[in] - Configuration structure 01853 * @return SUCCESS in case of success, FAILURE otherwise 01854 */ 01855 static int32_t iio_ad7606_init(struct iio_device **desc) 01856 { 01857 struct iio_device *iio_ad7606_inst; 01858 01859 iio_ad7606_inst = calloc(1, sizeof(struct iio_device)); 01860 if (!iio_ad7606_inst) { 01861 return FAILURE; 01862 } 01863 01864 iio_ad7606_inst->num_ch = sizeof(iio_ad7606_channels) / sizeof( 01865 iio_ad7606_channels[0]); 01866 iio_ad7606_inst->channels = iio_ad7606_channels; 01867 iio_ad7606_inst->attributes = global_attributes; 01868 iio_ad7606_inst->debug_attributes = debug_attributes; 01869 01870 iio_ad7606_inst->transfer_dev_to_mem = iio_ad7606_transfer_dev_data; 01871 iio_ad7606_inst->transfer_mem_to_dev = NULL; 01872 iio_ad7606_inst->read_data = iio_ad7606_read_data; 01873 iio_ad7606_inst->write_data = NULL; 01874 iio_ad7606_inst->prepare_transfer = iio_ad7606_start_transfer; 01875 iio_ad7606_inst->end_transfer = iio_ad7606_stop_transfer; 01876 iio_ad7606_inst->debug_reg_read = debug_reg_read; 01877 iio_ad7606_inst->debug_reg_write = debug_reg_write; 01878 01879 *desc = iio_ad7606_inst; 01880 01881 return SUCCESS; 01882 } 01883 01884 01885 /** 01886 * @brief Release resources allocated for IIO device 01887 * @param desc[in] - IIO device descriptor 01888 * @return SUCCESS in case of success, FAILURE otherwise 01889 */ 01890 static int32_t iio_ad7606_remove(struct iio_desc *desc) 01891 { 01892 int32_t status; 01893 01894 if (!desc) { 01895 return FAILURE; 01896 } 01897 01898 status = iio_unregister(desc, (char *)dev_name); 01899 if (status != SUCCESS) { 01900 return FAILURE; 01901 } 01902 01903 return SUCCESS; 01904 } 01905 01906 01907 /*! 01908 * @brief Get scale factor for adc data to voltage conversion for IIO client 01909 * @param chn_range[in] - Current channel voltage range 01910 * @param chn_range_bits[in] - Channel range register bits 01911 * @return scale 01912 * @details This function samples and capture the new data when previous data 01913 * is transmitted to IIO client 01914 */ 01915 static float get_vltg_conv_scale_factor(float chn_range, polarity_e polarity) 01916 { 01917 float scale; 01918 01919 /* Get the scale factor for voltage conversion from range */ 01920 if (polarity == UNIPOLAR) { 01921 scale = (chn_range / ADC_MAX_COUNT_UNIPOLAR) * 1000; 01922 } else { 01923 scale = (chn_range / ADC_MAX_COUNT_BIPOLAR) * 1000; 01924 } 01925 01926 return scale; 01927 } 01928 01929 01930 /** 01931 * @brief Save local variables 01932 * @return none 01933 * @details This function saves the local parameters with updated device values 01934 */ 01935 static void save_local_attributes(void) 01936 { 01937 char buf[50]; 01938 struct iio_ch_info channel; 01939 01940 for (uint8_t chn = 0; chn < AD7606X_ADC_CHANNELS; chn++) { 01941 channel.ch_num = chn; 01942 01943 /* Get channel range */ 01944 (void)get_chn_range(p_ad7606_dev_inst, buf, 0, &channel, 0); 01945 01946 /* Get scale */ 01947 attr_scale_val[channel.ch_num] = get_vltg_conv_scale_factor( 01948 attr_chn_range[channel.ch_num], 01949 attr_polarity_val[channel.ch_num]); 01950 } 01951 } 01952 01953 01954 /** 01955 * @brief Initialize the IIO interface for AD7606 IIO device 01956 * @return none 01957 * @return SUCCESS in case of success, FAILURE otherwise 01958 */ 01959 int32_t ad7606_iio_initialize(void) 01960 { 01961 int32_t init_status; 01962 01963 /* IIO device descriptor */ 01964 struct iio_device *p_iio_ad7606_dev; 01965 01966 /** 01967 * IIO interface init parameters 01968 */ 01969 struct iio_init_param iio_init_params = { 01970 .phy_type = USE_UART, 01971 { 01972 &uart_init_params 01973 } 01974 }; 01975 01976 /* Initialize AD7606 device and peripheral interface */ 01977 init_status = ad7606_init(&p_ad7606_dev_inst, &ad7606_init_str); 01978 if (init_status != SUCCESS) { 01979 return init_status; 01980 } 01981 01982 /* Initialize the IIO interface */ 01983 init_status = iio_init(&p_ad7606_iio_desc, &iio_init_params); 01984 if (init_status != SUCCESS) { 01985 return init_status; 01986 } 01987 01988 /* Initialize the AD7606 IIO application interface */ 01989 init_status = iio_ad7606_init(&p_iio_ad7606_dev); 01990 if (init_status != SUCCESS) { 01991 return init_status; 01992 } 01993 01994 /* Register AD7606 IIO interface */ 01995 init_status = iio_register(p_ad7606_iio_desc, 01996 p_iio_ad7606_dev, 01997 (char *)dev_name, 01998 p_ad7606_dev_inst, 01999 NULL, 02000 NULL); 02001 if (init_status != SUCCESS) { 02002 return init_status; 02003 } 02004 02005 /* Init the system peripherals */ 02006 init_status = init_system(); 02007 if (init_status != SUCCESS) { 02008 return init_status; 02009 } 02010 02011 return init_status; 02012 } 02013 02014 02015 /** 02016 * @brief Run the AD7606 IIO event handler 02017 * @return none 02018 * @details This function monitors the new IIO client event 02019 */ 02020 void ad7606_iio_event_handler(void) 02021 { 02022 while (1) { 02023 (void)iio_step(p_ad7606_iio_desc); 02024 } 02025 }
Generated on Wed Jul 13 2022 11:55:04 by 1.7.2