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.
ad7689_iio.c
00001 /***************************************************************************//** 00002 * @file ad7689_iio.c 00003 * @brief Implementation of AD7689 IIO application interfaces 00004 ******************************************************************************** 00005 * Copyright (c) 2021-22 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 #include <stdio.h> 00019 #include <string.h> 00020 #include <errno.h> 00021 00022 #include "ad7689_iio.h" 00023 #include "app_config.h" 00024 #include "ad7689_user_config.h" 00025 #include "ad7689_data_capture.h" 00026 #include "no_os_error.h" 00027 00028 /******************************************************************************/ 00029 /********************* Macros and Constants Definition ************************/ 00030 /******************************************************************************/ 00031 00032 /* ADC Raw to Voltage conversion default scale factor for IIO client */ 00033 #if defined(BIPOLAR) 00034 /* Device supports only pseudo-bipolar mode. INX- = Vref / 2 */ 00035 #define ADC_DEFAULT_SCALE (((ADC_DEFAULT_REF_VOLTAGE / 2) / ADC_MAX_COUNT_BIPOLAR) * 1000) 00036 #else 00037 #define ADC_DEFAULT_SCALE ((ADC_DEFAULT_REF_VOLTAGE / ADC_MAX_COUNT_UNIPOLAR) * 1000) 00038 #endif 00039 00040 /* The output of temperature sensor is always unipolar (streight-binary) */ 00041 #define TEMPERATURE_SENSITIVITY 0.283 // 283mv 00042 #define ROOM_TEMPERATURE 25.0 00043 #define TEMPERATURE_CONV_SCALE (ROOM_TEMPERATURE / TEMPERATURE_SENSITIVITY) * \ 00044 ((ADC_DEFAULT_REF_VOLTAGE / ADC_MAX_COUNT_UNIPOLAR) * 1000) 00045 00046 /* Bytes per sample. This count should divide the total 256 bytes into 'n' equivalent 00047 * ADC samples as IIO library requests only 256bytes of data at a time in a given 00048 * data read query. 00049 * For 1 to 8-bit ADC, bytes per sample = 1 (2^0) 00050 * For 9 to 16-bit ADC, bytes per sample = 2 (2^1) 00051 * For 17 to 32-bit ADC, bytes per sample = 4 (2^2) 00052 **/ 00053 #define BYTES_PER_SAMPLE sizeof(uint16_t) // For ADC resolution of 16-bits 00054 00055 /* Number of data storage bits (needed for IIO client to plot ADC data) */ 00056 #define CHN_STORAGE_BITS (BYTES_PER_SAMPLE * 8) 00057 00058 /* Private IDs for IIO attributes */ 00059 #define IIO_RAW_ATTR_ID 0 00060 #define IIO_SCALE_ATTR_ID 1 00061 #define IIO_OFFSET_ATTR_ID 2 00062 00063 /******************************************************************************/ 00064 /******************** Variables and User Defined Data Types *******************/ 00065 /******************************************************************************/ 00066 00067 /* IIO interface descriptor */ 00068 static struct iio_desc *p_ad7689_iio_desc; 00069 00070 /* Device name */ 00071 static const char dev_name[] = ACTIVE_DEVICE_NAME; 00072 00073 /* Pointer to the struct representing the AD7689 IIO device */ 00074 struct ad7689_dev *p_ad7689_dev_inst = NULL; 00075 00076 /* Device attributes with default values */ 00077 00078 /* Scale attribute value per channel */ 00079 static float attr_scale_val[ADC_CHN_COUNT] = { 00080 ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, 00081 #if !defined(DEV_AD7682) 00082 ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, ADC_DEFAULT_SCALE, 00083 #endif 00084 TEMPERATURE_CONV_SCALE 00085 }; 00086 00087 /* AD7689 current configuration */ 00088 struct ad7689_config ad7689_current_config; 00089 00090 /******************************************************************************/ 00091 /************************** Functions Declarations ****************************/ 00092 /******************************************************************************/ 00093 00094 /******************************************************************************/ 00095 /************************ Functions Definitions *******************************/ 00096 /******************************************************************************/ 00097 00098 /*! 00099 * @brief Getter/Setter for the sampling frequency attribute value 00100 * @param device- pointer to IIO device structure 00101 * @param buf- pointer to buffer holding attribute value 00102 * @param len- length of buffer string data 00103 * @param channel- pointer to IIO channel structure 00104 * @param id- Attribute ID (optional) 00105 * @return Number of characters read/written 00106 * @Note This attribute is used to define the timeout period in IIO 00107 * client during data capture. 00108 * Timeout = (number of requested samples * (1/sampling frequency)) + 1sec 00109 * e.g. if sampling frequency = 60KSPS and requested samples = 400 00110 * Timeout = (400 * (1/60000)) + 1 = 1.0067sec = ~1sec 00111 */ 00112 static int get_sampling_frequency(void *device, 00113 char *buf, 00114 uint32_t len, 00115 const struct iio_ch_info *channel, 00116 intptr_t id) 00117 { 00118 return sprintf(buf, "%d", SAMPLING_RATE); 00119 } 00120 00121 static int set_sampling_frequency(void *device, 00122 char *buf, 00123 uint32_t len, 00124 const struct iio_ch_info *channel, 00125 intptr_t id) 00126 { 00127 /* sampling frequency is read-only attribute */ 00128 return len; 00129 } 00130 00131 00132 /*! 00133 * @brief Getter/Setter for the raw, offset and scale attribute value 00134 * @param device- pointer to IIO device structure 00135 * @param buf- pointer to buffer holding attribute value 00136 * @param len- length of buffer string data 00137 * @param channel- pointer to IIO channel structure 00138 * @param id- Attribute ID (optional) 00139 * @return Number of characters read/written 00140 */ 00141 static int get_adc_raw(void *device, 00142 char *buf, 00143 uint32_t len, 00144 const struct iio_ch_info *channel, 00145 intptr_t id) 00146 { 00147 static uint32_t adc_data_raw = 0; 00148 int32_t offset = 0; 00149 int32_t ret; 00150 00151 switch (id) { 00152 case IIO_RAW_ATTR_ID: 00153 /* Capture the raw adc data */ 00154 ret = read_single_sample((uint8_t)channel->ch_num, &adc_data_raw); 00155 if (ret) { 00156 return sprintf(buf, " %s", "Error"); 00157 } 00158 return sprintf(buf, "%d", adc_data_raw); 00159 00160 case IIO_SCALE_ATTR_ID: 00161 return sprintf(buf, "%g", attr_scale_val[channel->ch_num]); 00162 00163 case IIO_OFFSET_ATTR_ID: 00164 #if defined(BIPOLAR) 00165 if (channel->ch_num == TEMPERATURE_CHN) { 00166 offset = 0; 00167 } else { 00168 if (adc_data_raw >= ADC_MAX_COUNT_BIPOLAR) { 00169 offset = -ADC_MAX_COUNT_UNIPOLAR; 00170 } else { 00171 offset = 0; 00172 } 00173 } 00174 #endif 00175 return sprintf(buf, "%d", offset); 00176 00177 default: 00178 break; 00179 } 00180 00181 return len; 00182 } 00183 00184 static int set_adc_raw(void *device, 00185 char *buf, 00186 uint32_t len, 00187 const struct iio_ch_info *channel, 00188 intptr_t id) 00189 { 00190 /* ADC raw, offset and scale are read-only attributes */ 00191 return len; 00192 } 00193 00194 /** 00195 * @brief Read buffer data corresponding to AD4170 IIO device 00196 * @param iio_dev_data[in] - Pointer to IIO device data structure 00197 * @return 0 in case of success, negative error code otherwise 00198 */ 00199 static int32_t iio_ad7689_submit_buffer(struct iio_device_data *iio_dev_data) 00200 { 00201 uint32_t ret; 00202 00203 /* Read the samples counts equal to buffer size/block */ 00204 ret = read_buffered_data(&iio_dev_data->buffer->buf->buff, 00205 iio_dev_data->buffer->size); 00206 00207 /* Increment the write spin count as buffer reads all 'n' samples 00208 * in one go which is also the size of buffer block for a given instance. 00209 * The read spin count is incremented from IIO library during buffer 00210 * write/offloading into transmit buffer */ 00211 if (iio_dev_data->buffer->buf->write.spin_count >= UINT32_MAX) { 00212 iio_dev_data->buffer->buf->write.spin_count = 0; 00213 } 00214 00215 iio_dev_data->buffer->buf->write.spin_count += 1; 00216 00217 return ret; 00218 } 00219 00220 /** 00221 * @brief Transfer the device data into memory (optional) 00222 * @param dev_instance[in] - IIO device instance 00223 * @param ch_mask[in] - Channels select mask 00224 * @return 0 in case of success, negative error code otherwise 00225 */ 00226 static int32_t iio_ad7689_prepare_transfer(void *dev_instance, 00227 uint32_t ch_mask) 00228 { 00229 return prepare_data_transfer(ch_mask, ADC_CHN_COUNT, BYTES_PER_SAMPLE); 00230 } 00231 00232 /** 00233 * @brief Perform tasks before end of current data transfer 00234 * @param dev[in] - IIO device instance 00235 * @return 0 in case of success, negative error code otherwise 00236 */ 00237 static int32_t iio_ad7689_end_transfer(void *dev) 00238 { 00239 return end_data_transfer(); 00240 } 00241 00242 /********************************************************* 00243 * IIO Attributes and Structures 00244 ********************************************************/ 00245 00246 /* IIOD channels attributes list */ 00247 struct iio_attribute channel_input_attributes[] = { 00248 { 00249 .name = "raw", 00250 .show = get_adc_raw, 00251 .store = set_adc_raw, 00252 .priv = IIO_RAW_ATTR_ID 00253 }, 00254 { 00255 .name = "scale", 00256 .show = get_adc_raw, 00257 .store = set_adc_raw, 00258 .priv = IIO_SCALE_ATTR_ID 00259 }, 00260 { 00261 .name = "offset", 00262 .show = get_adc_raw, 00263 .store = set_adc_raw, 00264 .priv = IIO_OFFSET_ATTR_ID 00265 }, 00266 00267 END_ATTRIBUTES_ARRAY 00268 }; 00269 00270 /* IIOD context attributes list */ 00271 static struct iio_context_attribute iio_context_attributes[] = { 00272 { 00273 .name = "hw_mezzanine", 00274 .value = HW_MEZZANINE_NAME 00275 }, 00276 { 00277 .name = "hw_carrier", 00278 .value = HW_CARRIER_NAME 00279 }, 00280 { 00281 .name = "hw_name", 00282 .value = HW_NAME 00283 }, 00284 END_ATTRIBUTES_ARRAY 00285 }; 00286 00287 /* IIOD device (global) attributes list */ 00288 static struct iio_attribute global_attributes[] = { 00289 { 00290 .name = "sampling_frequency", 00291 .show = get_sampling_frequency, 00292 .store = set_sampling_frequency, 00293 }, 00294 00295 END_ATTRIBUTES_ARRAY 00296 }; 00297 00298 /* IIOD channels configurations */ 00299 struct scan_type chn_scan = { 00300 #if defined(BIPOLAR) 00301 .sign = 's', 00302 #else 00303 .sign = 'u', 00304 #endif 00305 .realbits = CHN_STORAGE_BITS, 00306 .storagebits = CHN_STORAGE_BITS, 00307 .shift = 0, 00308 .is_big_endian = false 00309 }; 00310 00311 static struct iio_channel iio_ad7689_channels[] = { 00312 { 00313 .name = "voltage0", 00314 .ch_type = IIO_VOLTAGE, 00315 .channel = 0, 00316 .scan_index = 0, 00317 .scan_type = &chn_scan, 00318 .attributes = channel_input_attributes, 00319 .ch_out = false, 00320 .indexed = true, 00321 }, 00322 { 00323 .name = "voltage1", 00324 .ch_type = IIO_VOLTAGE, 00325 .channel = 1, 00326 .scan_index = 1, 00327 .scan_type = &chn_scan, 00328 .attributes = channel_input_attributes, 00329 .ch_out = false, 00330 .indexed = true 00331 }, 00332 { 00333 .name = "voltage2", 00334 .ch_type = IIO_VOLTAGE, 00335 .channel = 2, 00336 .scan_index = 2, 00337 .scan_type = &chn_scan, 00338 .attributes = channel_input_attributes, 00339 .ch_out = false, 00340 .indexed = true 00341 }, 00342 { 00343 .name = "voltage3", 00344 .ch_type = IIO_VOLTAGE, 00345 .channel = 3, 00346 .scan_index = 3, 00347 .scan_type = &chn_scan, 00348 .attributes = channel_input_attributes, 00349 .ch_out = false, 00350 .indexed = true 00351 }, 00352 #if !defined(DEV_AD7682) 00353 { 00354 .name = "voltage4", 00355 .ch_type = IIO_VOLTAGE, 00356 .channel = 4, 00357 .scan_index = 4, 00358 .scan_type = &chn_scan, 00359 .attributes = channel_input_attributes, 00360 .ch_out = false, 00361 .indexed = true 00362 }, 00363 { 00364 .name = "voltage5", 00365 .ch_type = IIO_VOLTAGE, 00366 .channel = 5, 00367 .scan_index = 5, 00368 .scan_type = &chn_scan, 00369 .attributes = channel_input_attributes, 00370 .ch_out = false, 00371 .indexed = true 00372 }, 00373 { 00374 .name = "voltage6", 00375 .ch_type = IIO_VOLTAGE, 00376 .channel = 6, 00377 .scan_index = 6, 00378 .scan_type = &chn_scan, 00379 .attributes = channel_input_attributes, 00380 .ch_out = false, 00381 .indexed = true 00382 }, 00383 { 00384 .name = "voltage7", 00385 .ch_type = IIO_VOLTAGE, 00386 .channel = 7, 00387 .scan_index = 7, 00388 .scan_type = &chn_scan, 00389 .attributes = channel_input_attributes, 00390 .ch_out = false, 00391 .indexed = true 00392 }, 00393 #endif 00394 { 00395 .name = "temperature", 00396 .ch_type = IIO_TEMP, 00397 #if !defined(DEV_AD7682) 00398 .channel = 8, 00399 .scan_index = 8, 00400 #else 00401 .channel = 4, 00402 .scan_index = 4, 00403 #endif 00404 .scan_type = &chn_scan, 00405 .attributes = channel_input_attributes, 00406 .ch_out = false, 00407 .indexed = true 00408 }, 00409 }; 00410 00411 00412 /** 00413 * @brief Init for reading/writing and parameterization of a 00414 * ad7689 IIO device 00415 * @param desc[in,out] - IIO device descriptor 00416 * @return 0 in case of success, negative error code otherwise 00417 */ 00418 static int32_t iio_ad7689_init(struct iio_device **desc) 00419 { 00420 struct iio_device *iio_ad7689_inst; 00421 00422 iio_ad7689_inst = calloc(1, sizeof(struct iio_device)); 00423 if (!iio_ad7689_inst) { 00424 return -EINVAL; 00425 } 00426 00427 iio_ad7689_inst->num_ch = sizeof(iio_ad7689_channels) / sizeof( 00428 iio_ad7689_channels[0]); 00429 iio_ad7689_inst->channels = iio_ad7689_channels; 00430 iio_ad7689_inst->attributes = global_attributes; 00431 iio_ad7689_inst->context_attributes = iio_context_attributes; 00432 00433 iio_ad7689_inst->submit = iio_ad7689_submit_buffer; 00434 iio_ad7689_inst->pre_enable = iio_ad7689_prepare_transfer; 00435 iio_ad7689_inst->post_disable = iio_ad7689_end_transfer; 00436 00437 iio_ad7689_inst->debug_reg_read = NULL; 00438 iio_ad7689_inst->debug_reg_write = NULL; 00439 00440 *desc = iio_ad7689_inst; 00441 00442 return 0; 00443 } 00444 00445 /** 00446 * @brief Initialize the IIO interface for AD7689 IIO device 00447 * @return none 00448 * @return 0 in case of success, negative error code otherwise 00449 */ 00450 int32_t ad7689_iio_initialize(void) 00451 { 00452 int32_t init_status; 00453 00454 /* IIO device descriptor */ 00455 struct iio_device *p_iio_ad7689_dev; 00456 00457 /* IIO interface init parameters */ 00458 struct iio_init_param iio_init_params = { 00459 .phy_type = USE_UART, 00460 .nb_devs = 1, 00461 }; 00462 00463 /* IIOD init parameters */ 00464 struct iio_device_init iio_device_init_params = { 00465 .name = (char *)dev_name, 00466 .raw_buf = adc_data_buffer, 00467 .raw_buf_len = DATA_BUFFER_SIZE 00468 }; 00469 00470 /* Init the system peripherals */ 00471 init_status = init_system(); 00472 if (init_status) { 00473 return init_status; 00474 } 00475 00476 /* Initialize AD7689 device and peripheral interface */ 00477 init_status = ad7689_init(&p_ad7689_dev_inst, &ad7689_init_params); 00478 if (init_status) { 00479 return init_status; 00480 } 00481 00482 /* Initialize the AD7689 IIO application interface */ 00483 init_status = iio_ad7689_init(&p_iio_ad7689_dev); 00484 if (init_status) { 00485 return init_status; 00486 } 00487 00488 /* Initialize the IIO interface */ 00489 iio_init_params.uart_desc = uart_desc; 00490 iio_device_init_params.dev = p_ad7689_dev_inst; 00491 iio_device_init_params.dev_descriptor = p_iio_ad7689_dev; 00492 iio_init_params.devs = &iio_device_init_params; 00493 init_status = iio_init(&p_ad7689_iio_desc, &iio_init_params); 00494 if (init_status) { 00495 return init_status; 00496 } 00497 00498 /* Load the init config into current configuration */ 00499 memcpy(&ad7689_current_config, &ad7689_init_params.config, 00500 sizeof(ad7689_current_config)); 00501 00502 return 0; 00503 } 00504 00505 /** 00506 * @brief Run the AD7689 IIO event handler 00507 * @return none 00508 * @details This function monitors the new IIO client event 00509 */ 00510 void ad7689_iio_event_handler(void) 00511 { 00512 (void)iio_step(p_ad7689_iio_desc); 00513 }
Generated on Fri Jul 15 2022 12:01:57 by
1.7.2