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
iio_ad4696.c
00001 /***************************************************************************//** 00002 * @file iio_ad4696.c 00003 * @brief Implementation of AD4696 IIO application interfaces 00004 * @details This module acts as an interface for AD4696 IIO application 00005 ******************************************************************************** 00006 * Copyright (c) 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 <math.h> 00020 00021 #include "app_config.h" 00022 #include "tinyiiod.h" 00023 #include "iio_ad4696.h" 00024 #include "adc_data_capture.h" 00025 #include "ad4696_support.h" 00026 #include "ad4696_user_config.h" 00027 #include "error.h" 00028 00029 /******************************************************************************/ 00030 /************************ Macros/Constants ************************************/ 00031 /******************************************************************************/ 00032 00033 /* ADC Raw to Voltage conversion default scale factor for IIO client */ 00034 #if defined(PSEUDO_BIPOLAR_MODE) 00035 /* Device supports pseudo-bipolar mode only with INX- = Vref / 2 */ 00036 #define DEFAULT_SCALE (((DEFAULT_VREF / 2) / ADC_MAX_COUNT_BIPOLAR) * 1000) 00037 #else 00038 #define DEFAULT_SCALE ((DEFAULT_VREF / ADC_MAX_COUNT_UNIPOLAR) * 1000) 00039 #endif 00040 00041 /* Bytes per sample. This count should divide the total 256 bytes into 'n' equivalent 00042 * ADC samples as IIO library requests only 256bytes of data at a time in a given 00043 * data read query. 00044 * For 1 to 8-bit ADC, bytes per sample = 1 (2^0) 00045 * For 9 to 16-bit ADC, bytes per sample = 2 (2^1) 00046 * For 17 to 32-bit ADC, bytes per sample = 4 (2^2) 00047 **/ 00048 #define BYTES_PER_SAMPLE sizeof(uint16_t) // For ADC resolution of 16-bits 00049 00050 /* Number of data storage bits (needed for IIO client to plot ADC data) */ 00051 #define CHN_STORAGE_BITS (BYTES_PER_SAMPLE * 8) 00052 00053 /* Private IDs for IIO attributes */ 00054 #define IIO_RAW_ATTR_ID 0 00055 #define IIO_SCALE_ATTR_ID 1 00056 #define IIO_OFFSET_ATTR_ID 2 00057 00058 /******************************************************************************/ 00059 /*************************** Types Declarations *******************************/ 00060 /******************************************************************************/ 00061 00062 /* Pointer to the struct representing the AD4696 IIO device */ 00063 struct ad469x_dev *p_ad4696_dev = NULL; 00064 00065 /* IIO interface descriptor */ 00066 static struct iio_desc *p_ad4696_iio_desc; 00067 00068 /* Device name */ 00069 static const char dev_name [] = ACTIVE_DEVICE_NAME; 00070 00071 /* Scale value per channel */ 00072 static float attr_scale_val[NO_OF_CHANNELS] = { 00073 DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, 00074 DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, 00075 DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, 00076 DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE, DEFAULT_SCALE 00077 }; 00078 00079 /* Flag to trigger new data capture */ 00080 static bool adc_data_capture_started = false; 00081 00082 /******************************************************************************/ 00083 /************************ Functions Definitions *******************************/ 00084 /******************************************************************************/ 00085 00086 /*! 00087 * @brief Getter/Setter for the raw, offset and scale attribute value 00088 * @param device- pointer to IIO device structure 00089 * @param buf- pointer to buffer holding attribute value 00090 * @param len- length of buffer string data 00091 * @param channel- pointer to IIO channel structure 00092 * @param id- Attribute ID 00093 * @return Number of characters read/written 00094 */ 00095 static ssize_t get_adc_raw(void *device, 00096 char *buf, 00097 size_t len, 00098 const struct iio_ch_info *channel, 00099 intptr_t id) 00100 { 00101 static uint32_t adc_data_raw = 0; 00102 int32_t offset = 0; 00103 00104 switch (id) { 00105 case IIO_RAW_ATTR_ID: 00106 /* Capture the raw adc data */ 00107 if (read_single_sample((uint32_t)channel->ch_num, &adc_data_raw) != FAILURE) { 00108 return (ssize_t) sprintf(buf, "%d", adc_data_raw); 00109 } 00110 break; 00111 00112 case IIO_SCALE_ATTR_ID: 00113 return (ssize_t) sprintf(buf, "%f", attr_scale_val[channel->ch_num]); 00114 break; 00115 00116 case IIO_OFFSET_ATTR_ID: 00117 #if defined(PSEUDO_BIPOLAR_MODE) 00118 if (adc_data_raw >= ADC_MAX_COUNT_BIPOLAR) { 00119 offset = -ADC_MAX_COUNT_UNIPOLAR ; 00120 } 00121 else { 00122 offset = 0; 00123 } 00124 #endif 00125 return (ssize_t) sprintf(buf, "%d", offset); 00126 break; 00127 00128 default: 00129 break; 00130 } 00131 00132 return -EINVAL; 00133 } 00134 00135 static ssize_t set_adc_raw(void *device, 00136 char *buf, 00137 size_t len, 00138 const struct iio_ch_info *channel, 00139 intptr_t id) 00140 { 00141 /* ADC raw value, offset factor and scale factor are fixed for given configurations set 00142 * in the firmware */ 00143 return len; 00144 } 00145 00146 /*! 00147 * @brief Getter/Setter for the sampling frequency attribute value 00148 * @param device- pointer to IIO device structure 00149 * @param buf- pointer to buffer holding attribute value 00150 * @param len- length of buffer string data 00151 * @param channel- pointer to IIO channel structure 00152 * @return Number of characters read/written 00153 * @Note This attribute is used to define the timeout period in IIO 00154 * client during data capture. 00155 * Timeout = (number of requested samples * (1/sampling frequency)) + 1sec 00156 * e.g. if sampling frequency = 50SPS and requested samples = 400 00157 * Timeout = (400 * 0.02) + 1 = 9sec 00158 */ 00159 ssize_t get_sampling_frequency(void *device, 00160 char *buf, 00161 size_t len, 00162 const struct iio_ch_info *channel, 00163 intptr_t id) 00164 { 00165 return (ssize_t) sprintf(buf, "%d", SAMPLING_RATE); 00166 } 00167 00168 ssize_t set_sampling_frequency(void *device, 00169 char *buf, 00170 size_t len, 00171 const struct iio_ch_info *channel, 00172 intptr_t id) 00173 { 00174 /* Sampling frequency determines the IIO client timeout. It is defined in the 00175 * software and not allowed to change externally */ 00176 return -EINVAL; 00177 } 00178 00179 /*! 00180 * @brief Read the debug register value 00181 * @param dev- Pointer to IIO device instance 00182 * @param reg- Register address to read from 00183 * @param readval- Pointer to variable to read data into 00184 * @return SUCCESS in case of success, negative value otherwise 00185 */ 00186 int32_t debug_reg_read(void *dev, uint32_t reg, uint8_t *readval) 00187 { 00188 /* Read the data from device */ 00189 if (reg <= NUM_OF_REGISTERS) { 00190 if (ad469x_spi_reg_read(dev, reg, readval) == SUCCESS) { 00191 return SUCCESS; 00192 } 00193 } 00194 00195 return FAILURE; 00196 } 00197 00198 /*! 00199 * @brief Write into the debug register 00200 * @param dev- Pointer to IIO device instance 00201 * @param reg- Register address to write into 00202 * @param writeval- Register value to write 00203 * @return SUCCESS in case of success, negative value otherwise 00204 */ 00205 int32_t debug_reg_write(void *dev, uint32_t reg, uint32_t writeval) 00206 { 00207 if (reg <= NUM_OF_REGISTERS) { 00208 if (ad469x_spi_reg_write(dev, reg, writeval) == SUCCESS) { 00209 return SUCCESS; 00210 } 00211 } 00212 00213 return FAILURE; 00214 } 00215 00216 /** 00217 * @brief Read buffer data corresponding to AD4696 IIO device 00218 * @param dev_instance[in] - IIO device instance 00219 * @param pbuf[out] - Pointer to output data buffer 00220 * @param offset[in] - Data buffer offset 00221 * @param bytes_count[in] - Number of bytes to read 00222 * @param ch_mask[in] - Channels select mask 00223 * @return SUCCESS in case of success or negative value otherwise 00224 */ 00225 static ssize_t iio_ad4696_read_data(void *dev_instance, 00226 char *pbuf, 00227 size_t offset, 00228 size_t bytes_count, 00229 uint32_t ch_mask) 00230 { 00231 if (adc_data_capture_started == false) { 00232 start_data_capture(ch_mask, AD469x_CHANNEL_NO); 00233 adc_data_capture_started = true; 00234 } 00235 00236 /* Read the buffered data */ 00237 return (ssize_t)read_buffered_data(pbuf, bytes_count, offset, ch_mask, 00238 BYTES_PER_SAMPLE); 00239 00240 } 00241 00242 /** 00243 * @brief Transfer the device data into memory (optional) 00244 * @param dev_instance[in] - IIO device instance 00245 * @param bytes_count[in] - Number of bytes to read 00246 * @param ch_mask[in] - Channels select mask 00247 * @return SUCCESS in case of success or negative value otherwise 00248 */ 00249 static ssize_t iio_ad4696_transfer_dev_data(void *dev_instance, 00250 size_t bytes_count, uint32_t ch_mask) 00251 { 00252 store_requested_samples_count(bytes_count, BYTES_PER_SAMPLE); 00253 return SUCCESS; 00254 } 00255 00256 /** 00257 * @brief Perform tasks before new data transfer 00258 * @param dev_instance[in] - IIO device instance 00259 * @param ch_mask[in] - Channels select mask 00260 * @return SUCCESS in case of success or negative value otherwise 00261 */ 00262 static int32_t iio_ad4696_start_transfer(void *dev_instance, uint32_t ch_mask) 00263 { 00264 return SUCCESS; 00265 } 00266 00267 00268 /** 00269 * @brief Perform tasks before end of current data transfer 00270 * @param dev_instance[in] - IIO device instance 00271 * @return SUCCESS in case of success or negative value otherwise 00272 */ 00273 static int32_t iio_ad4696_stop_transfer(void *dev) 00274 { 00275 adc_data_capture_started = false; 00276 stop_data_capture(); 00277 00278 return SUCCESS; 00279 } 00280 00281 /********************************************************* 00282 * IIO Attributes and Structures 00283 ********************************************************/ 00284 00285 /* IIOD channels attributes list */ 00286 struct iio_attribute channel_input_attributes[] = { 00287 { 00288 .name = "raw", 00289 .show = get_adc_raw, 00290 .store = set_adc_raw, 00291 .priv = IIO_RAW_ATTR_ID 00292 }, 00293 { 00294 .name = "scale", 00295 .show = get_adc_raw, 00296 .store = set_adc_raw, 00297 .priv = IIO_SCALE_ATTR_ID 00298 }, 00299 { 00300 .name = "offset", 00301 .show = get_adc_raw, 00302 .store = set_adc_raw, 00303 .priv = IIO_OFFSET_ATTR_ID 00304 }, 00305 00306 END_ATTRIBUTES_ARRAY 00307 }; 00308 00309 /* IIOD device (global) attributes list */ 00310 static struct iio_attribute global_attributes[] = { 00311 { 00312 .name = "sampling_frequency", 00313 .show = get_sampling_frequency, 00314 .store = set_sampling_frequency, 00315 }, 00316 00317 END_ATTRIBUTES_ARRAY 00318 }; 00319 00320 /* IIOD debug attributes list */ 00321 static struct iio_attribute debug_attributes[] = { 00322 { 00323 .name = "direct_reg_access", 00324 .show = NULL, 00325 .store = NULL, 00326 }, 00327 00328 END_ATTRIBUTES_ARRAY 00329 }; 00330 00331 /* IIOD channels configurations */ 00332 struct scan_type chn_scan = { 00333 #if defined(PSEUDO_BIPOLAR_MODE) 00334 .sign = 's', 00335 #else 00336 .sign = 'u', 00337 #endif 00338 .realbits = CHN_STORAGE_BITS, 00339 .storagebits = CHN_STORAGE_BITS, 00340 .shift = 0, 00341 .is_big_endian = false 00342 }; 00343 static struct iio_channel iio_ad4696_channels[] = { 00344 { 00345 .name = "voltage0", 00346 .ch_type = IIO_VOLTAGE, 00347 .channel = 0, 00348 .scan_index = 0, 00349 .scan_type = &chn_scan, 00350 .attributes = channel_input_attributes, 00351 .ch_out = false, 00352 .indexed = true, 00353 }, 00354 { 00355 .name = "voltage1", 00356 .ch_type = IIO_VOLTAGE, 00357 .channel = 1, 00358 .scan_index = 1, 00359 .scan_type = &chn_scan, 00360 .attributes = channel_input_attributes, 00361 .ch_out = false, 00362 .indexed = true 00363 }, 00364 { 00365 .name = "voltage2", 00366 .ch_type = IIO_VOLTAGE, 00367 .channel = 2, 00368 .scan_index = 2, 00369 .scan_type = &chn_scan, 00370 .attributes = channel_input_attributes, 00371 .ch_out = false, 00372 .indexed = true 00373 }, 00374 { 00375 .name = "voltage3", 00376 .ch_type = IIO_VOLTAGE, 00377 .channel = 3, 00378 .scan_index = 3, 00379 .scan_type = &chn_scan, 00380 .attributes = channel_input_attributes, 00381 .ch_out = false, 00382 .indexed = true 00383 }, 00384 { 00385 .name = "voltage4", 00386 .ch_type = IIO_VOLTAGE, 00387 .channel = 4, 00388 .scan_index = 4, 00389 .scan_type = &chn_scan, 00390 .attributes = channel_input_attributes, 00391 .ch_out = false, 00392 .indexed = true 00393 }, 00394 { 00395 .name = "voltage5", 00396 .ch_type = IIO_VOLTAGE, 00397 .channel = 5, 00398 .scan_index = 5, 00399 .scan_type = &chn_scan, 00400 .attributes = channel_input_attributes, 00401 .ch_out = false, 00402 .indexed = true 00403 }, 00404 { 00405 .name = "voltage6", 00406 .ch_type = IIO_VOLTAGE, 00407 .channel = 6, 00408 .scan_index = 6, 00409 .scan_type = &chn_scan, 00410 .attributes = channel_input_attributes, 00411 .ch_out = false, 00412 .indexed = true 00413 }, 00414 { 00415 .name = "voltage7", 00416 .ch_type = IIO_VOLTAGE, 00417 .channel = 7, 00418 .scan_index = 7, 00419 .scan_type = &chn_scan, 00420 .attributes = channel_input_attributes, 00421 .ch_out = false, 00422 .indexed = true 00423 }, 00424 { 00425 .name = "voltage8", 00426 .ch_type = IIO_VOLTAGE, 00427 .channel = 8, 00428 .scan_index = 8, 00429 .scan_type = &chn_scan, 00430 .attributes = channel_input_attributes, 00431 .ch_out = false, 00432 .indexed = true, 00433 }, 00434 { 00435 .name = "voltage9", 00436 .ch_type = IIO_VOLTAGE, 00437 .channel = 9, 00438 .scan_index = 9, 00439 .scan_type = &chn_scan, 00440 .attributes = channel_input_attributes, 00441 .ch_out = false, 00442 .indexed = true 00443 }, 00444 { 00445 .name = "voltage10", 00446 .ch_type = IIO_VOLTAGE, 00447 .channel = 10, 00448 .scan_index = 10, 00449 .scan_type = &chn_scan, 00450 .attributes = channel_input_attributes, 00451 .ch_out = false, 00452 .indexed = true 00453 }, 00454 { 00455 .name = "voltage11", 00456 .ch_type = IIO_VOLTAGE, 00457 .channel = 11, 00458 .scan_index = 11, 00459 .scan_type = &chn_scan, 00460 .attributes = channel_input_attributes, 00461 .ch_out = false, 00462 .indexed = true 00463 }, 00464 { 00465 .name = "voltage12", 00466 .ch_type = IIO_VOLTAGE, 00467 .channel = 12, 00468 .scan_index = 12, 00469 .scan_type = &chn_scan, 00470 .attributes = channel_input_attributes, 00471 .ch_out = false, 00472 .indexed = true 00473 }, 00474 { 00475 .name = "voltage13", 00476 .ch_type = IIO_VOLTAGE, 00477 .channel = 13, 00478 .scan_index = 13, 00479 .scan_type = &chn_scan, 00480 .attributes = channel_input_attributes, 00481 .ch_out = false, 00482 .indexed = true 00483 }, 00484 { 00485 .name = "voltage14", 00486 .ch_type = IIO_VOLTAGE, 00487 .channel = 14, 00488 .scan_index = 14, 00489 .scan_type = &chn_scan, 00490 .attributes = channel_input_attributes, 00491 .ch_out = false, 00492 .indexed = true 00493 }, 00494 { 00495 .name = "voltage15", 00496 .ch_type = IIO_VOLTAGE, 00497 .channel = 15, 00498 .scan_index = 15, 00499 .scan_type = &chn_scan, 00500 .attributes = channel_input_attributes, 00501 .ch_out = false, 00502 .indexed = true 00503 }, 00504 }; 00505 00506 /** 00507 * @brief Init for reading/writing and parameterization of a 00508 * ad4696 IIO device 00509 * @param desc[in,out] - IIO device descriptor 00510 * @return SUCCESS in case of success, FAILURE otherwise 00511 */ 00512 static int32_t iio_ad4696_init(struct iio_device **desc) 00513 { 00514 struct iio_device *iio_ad4696_inst; 00515 00516 iio_ad4696_inst = calloc(1, sizeof(struct iio_device)); 00517 if (!iio_ad4696_inst) { 00518 return FAILURE; 00519 } 00520 00521 iio_ad4696_inst->num_ch = sizeof(iio_ad4696_channels) / sizeof( 00522 iio_ad4696_channels[0]); 00523 iio_ad4696_inst->channels = iio_ad4696_channels; 00524 iio_ad4696_inst->attributes = global_attributes; 00525 iio_ad4696_inst->debug_attributes = debug_attributes; 00526 00527 iio_ad4696_inst->transfer_dev_to_mem = iio_ad4696_transfer_dev_data; 00528 iio_ad4696_inst->transfer_mem_to_dev = NULL; 00529 iio_ad4696_inst->read_data = iio_ad4696_read_data; 00530 iio_ad4696_inst->write_data = NULL; 00531 iio_ad4696_inst->prepare_transfer = iio_ad4696_start_transfer; 00532 iio_ad4696_inst->end_transfer = iio_ad4696_stop_transfer; 00533 iio_ad4696_inst->debug_reg_read = debug_reg_read; 00534 iio_ad4696_inst->debug_reg_write = debug_reg_write; 00535 00536 *desc = iio_ad4696_inst; 00537 00538 return SUCCESS; 00539 } 00540 00541 /** 00542 * @brief Release resources allocated for IIO device 00543 * @param desc[in] - IIO device descriptor 00544 * @return SUCCESS in case of success, FAILURE otherwise 00545 */ 00546 static int32_t iio_ad4696_remove(struct iio_desc *desc) 00547 { 00548 int32_t status; 00549 00550 if (!desc) { 00551 return FAILURE; 00552 } 00553 00554 status = iio_unregister(desc, (char *)dev_name); 00555 if (status != SUCCESS) { 00556 return FAILURE; 00557 } 00558 00559 return SUCCESS; 00560 } 00561 00562 00563 /** 00564 * @brief Initialize the IIO interface for AD4696 IIO device 00565 * @return SUCCESS in case of success, FAILURE otherwise 00566 */ 00567 int32_t ad4696_iio_initialize(void) 00568 { 00569 int32_t init_status; 00570 00571 /* IIO device descriptor */ 00572 struct iio_device *p_iio_ad4696_dev; 00573 00574 /* IIO interface init parameter */ 00575 struct iio_init_param iio_init_params = { 00576 .phy_type = USE_UART, 00577 { 00578 &uart_init_params 00579 } 00580 }; 00581 00582 /* Initialize AD4696 device and peripheral interface */ 00583 init_status = ad469x_init(&p_ad4696_dev, &ad4696_init_str); 00584 if (init_status != SUCCESS) { 00585 return init_status; 00586 } 00587 00588 /* Initialize the IIO interface */ 00589 init_status = iio_init(&p_ad4696_iio_desc, &iio_init_params); 00590 if (init_status != SUCCESS) { 00591 return init_status; 00592 } 00593 00594 /* Register and initialize the AD4696 device into IIO interface */ 00595 init_status = iio_ad4696_init(&p_iio_ad4696_dev); 00596 if (init_status != SUCCESS) { 00597 return init_status; 00598 } 00599 00600 /* Register AD4696 IIO interface */ 00601 init_status = iio_register(p_ad4696_iio_desc, p_iio_ad4696_dev, 00602 (char *)dev_name, p_ad4696_dev, NULL, 00603 NULL); 00604 if (init_status != SUCCESS) { 00605 return init_status; 00606 } 00607 00608 /* Init the system peripherals */ 00609 init_status = init_system(); 00610 if (init_status != SUCCESS) { 00611 return init_status; 00612 } 00613 00614 /* To enable manual trigger mode for operation */ 00615 init_status = ad4696_enable_manual_trigger_mode(p_ad4696_dev); 00616 if (init_status != SUCCESS) { 00617 return init_status; 00618 } 00619 00620 return SUCCESS; 00621 } 00622 00623 /** 00624 * @brief Run the AD4696 IIO event handler 00625 * @return none 00626 * @details This function monitors the new IIO client event 00627 */ 00628 void ad4696_iio_event_handler(void) 00629 { 00630 while(1) { 00631 (void)iio_step(p_ad4696_iio_desc); 00632 } 00633 }
Generated on Tue Jul 12 2022 15:35:46 by
