Analog Devices / Mbed OS EVAL-AD717x-AD411x-IIO

Dependencies:   sdp_k1_sdram

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ad717x_iio.c Source File

ad717x_iio.c

Go to the documentation of this file.
00001 /***************************************************************************//**
00002  * @file    ad717x_iio.c
00003  * @brief   Source file for the AD717x IIO Application
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 <stdio.h>
00018 #include "ad717x_user_config.h"
00019 #include "app_config.h"
00020 #include "ad717x_iio.h"
00021 #include "ad717x.h"
00022 #include "iio.h"
00023 #include "no_os_util.h"
00024 #include "ad717x_data_capture.h"
00025 #include "no_os_error.h"
00026 
00027 /******************************************************************************/
00028 /********************* Macros and Constants Definition ************************/
00029 /******************************************************************************/
00030 
00031 /* Define ADC Resolution in Bits */
00032 #if defined (DEV_AD7177_2)
00033 #define AD717x_RESOLUTION   32
00034 #else
00035 #define AD717x_RESOLUTION   24
00036 #endif
00037 
00038 /* ADC max count (full scale value) for unipolar inputs */
00039 #define ADC_MAX_COUNT_UNIPOLAR  (uint32_t)((1 << AD717x_RESOLUTION) - 1)
00040 
00041 /* ADC max count (full scale value) for bipolar inputs */
00042 #define ADC_MAX_COUNT_BIPOLAR   (uint32_t)(1 << (AD717x_RESOLUTION-1))
00043 
00044 /* Bytes per sample (*Note: 4 bytes needed per sample for data range
00045  * of 0 to 32-bit) */
00046 #define BYTES_PER_SAMPLE    sizeof(uint32_t)
00047 
00048 /* Number of data storage bits (needed for IIO client) */
00049 #define CHN_STORAGE_BITS    (BYTES_PER_SAMPLE * 8)
00050 
00051 /* Private IDs for IIO attributes */
00052 #define AD717x_RAW_ATTR_ID      0
00053 #define AD717x_SCALE_ATTR_ID        1
00054 #define AD717x_OFFSET_ATTR_ID       2
00055 #define AD717x_SAMPLING_FREQUENCY_ID    3
00056 
00057 /* Data Buffer for burst mode data capture */
00058 #define AD717x_DATA_BUFFER_SIZE     (8192)
00059 
00060 /* Scan type definition */
00061 #define AD717x_SCAN {\
00062     .sign = 'u',\
00063     .realbits = AD717x_RESOLUTION,\
00064     .storagebits = CHN_STORAGE_BITS,\
00065     .shift = 0,\
00066     .is_big_endian = false\
00067 }
00068 
00069 /* Channel attribute definition */
00070 #define AD717x_CHANNEL(_name, _priv) {\
00071     .name = _name,\
00072     .priv = _priv,\
00073     .show = get_adc_attribute,\
00074     .store = set_adc_attribute\
00075 }
00076 
00077 /* AD717x Channel Definition */
00078 #define IIO_AD717x_CHANNEL(_idx) {\
00079     .name = "ch" # _idx,\
00080     .ch_type = IIO_VOLTAGE,\
00081     .channel = _idx,\
00082     .scan_index = _idx,\
00083     .indexed = true,\
00084     .scan_type = &ad717x_scan_type[_idx],\
00085     .ch_out = false,\
00086     .attributes = ad717x_channel_attributes,\
00087 }
00088 
00089 /******************************************************************************/
00090 /******************** Variables and User Defined Data Types *******************/
00091 /******************************************************************************/
00092 
00093 /* IIO interface descriptor */
00094 static struct iio_desc *p_ad717x_iio_desc;
00095 
00096 /* Pointer to the struct representing the AD717x IIO device */
00097 ad717x_dev *p_ad717x_dev_inst = NULL;
00098 
00099 /* Device Name */
00100 static const char dev_name[] = ACTIVE_DEVICE_NAME;
00101 
00102 /* Variable to hold the number of active channels*/
00103 uint8_t num_active_channels = 0;
00104 
00105 /* Channel scale values */
00106 static float attr_scale_val[NUMBER_OF_CHANNELS];
00107 
00108 /* Channel offset values */
00109 static int attr_offset_val[NUMBER_OF_CHANNELS];
00110 
00111 /* AD717x channel scan type */
00112 static struct scan_type ad717x_scan_type[] = {
00113     AD717x_SCAN,
00114     AD717x_SCAN,
00115     AD717x_SCAN,
00116     AD717x_SCAN,
00117 #if (NUMBER_OF_CHANNELS != 4)
00118     AD717x_SCAN,
00119     AD717x_SCAN,
00120     AD717x_SCAN,
00121     AD717x_SCAN,
00122 #if (NUMBER_OF_CHANNELS != 4) && (NUMBER_OF_CHANNELS !=8 )
00123     AD717x_SCAN,
00124     AD717x_SCAN,
00125     AD717x_SCAN,
00126     AD717x_SCAN,
00127     AD717x_SCAN,
00128     AD717x_SCAN,
00129     AD717x_SCAN,
00130     AD717x_SCAN
00131 #endif
00132 #endif
00133 };
00134 
00135 /******************************************************************************/
00136 /************************** Functions Declaration *****************************/
00137 /******************************************************************************/
00138 
00139 /******************************************************************************/
00140 /************************** Functions Definition ******************************/
00141 /******************************************************************************/
00142 
00143 /*!
00144  * @brief   Getter/Setter for the attribute value
00145  * @param   device[in]- pointer to IIO device structure
00146  * @param   buf[in]- pointer to buffer holding attribute value
00147  * @param   len[in]- length of buffer string data
00148  * @param   channel[in]- pointer to IIO channel structure
00149  * @param   id[in]- Attribute ID
00150  * @return  Number of characters read/written in case of success, negative error code otherwise
00151  */
00152 static int32_t get_adc_attribute(void *device,
00153                  char *buf,
00154                  uint32_t len,
00155                  const struct iio_ch_info *channel,
00156                  intptr_t id)
00157 {
00158     int32_t adc_raw_data = 0;
00159     int32_t adc_offset = 0;
00160 
00161     switch (id) {
00162     case AD717x_RAW_ATTR_ID:
00163         if (ad717x_single_read(device, channel->ch_num, &adc_raw_data) < 0)
00164             return -EINVAL;
00165 
00166         return sprintf(buf, "%d", adc_raw_data);
00167 
00168     case AD717x_SCALE_ATTR_ID:
00169         return sprintf(buf, "%f", attr_scale_val[channel->ch_num]);
00170 
00171     case AD717x_OFFSET_ATTR_ID:
00172         return sprintf(buf, "%d", attr_offset_val[channel->ch_num]);
00173 
00174     case AD717x_SAMPLING_FREQUENCY_ID:
00175         return sprintf(buf, "%d", AD717x_SAMPLING_RATE/NUMBER_OF_CHANNELS);
00176 
00177     default:
00178         break;
00179     }
00180 
00181     return -EINVAL;
00182 }
00183 
00184 
00185 static int32_t set_adc_attribute(void *device,
00186                  char *buf,
00187                  uint32_t len,
00188                  const struct iio_ch_info *channel,
00189                  intptr_t id)
00190 {
00191     switch (id) {
00192 
00193     /* ADC Raw, Scale, Offset factors are constant for the firmware configuration */
00194     case AD717x_RAW_ATTR_ID:
00195     case AD717x_SCALE_ATTR_ID:
00196     case AD717x_OFFSET_ATTR_ID:
00197     case AD717x_SAMPLING_FREQUENCY_ID:
00198     default:
00199         break;
00200     }
00201 
00202     return len;
00203 }
00204 
00205 /* AD717X Channel Attributes */
00206 static struct iio_attribute ad717x_channel_attributes[] = {
00207     AD717x_CHANNEL("raw", AD717x_RAW_ATTR_ID),
00208     AD717x_CHANNEL("scale", AD717x_SCALE_ATTR_ID),
00209     AD717x_CHANNEL("offset", AD717x_OFFSET_ATTR_ID),
00210     END_ATTRIBUTES_ARRAY
00211 };
00212 
00213 /* AD717x Global Attributes */
00214 static struct iio_attribute iio_ad717x_global_attributes[] = {
00215     AD717x_CHANNEL("sampling_frequency", AD717x_SAMPLING_FREQUENCY_ID),
00216     END_ATTRIBUTES_ARRAY
00217 };
00218 
00219 /* IIO Attributes */
00220 static struct iio_channel iio_adc_channels[] = {
00221     IIO_AD717x_CHANNEL(0),
00222     IIO_AD717x_CHANNEL(1),
00223     IIO_AD717x_CHANNEL(2),
00224     IIO_AD717x_CHANNEL(3),
00225 #if (NUMBER_OF_CHANNELS != 4)
00226     IIO_AD717x_CHANNEL(4),
00227     IIO_AD717x_CHANNEL(5),
00228     IIO_AD717x_CHANNEL(6),
00229     IIO_AD717x_CHANNEL(7),
00230 #if (NUMBER_OF_CHANNELS != 4) && (NUMBER_OF_CHANNELS != 8)
00231     IIO_AD717x_CHANNEL(8),
00232     IIO_AD717x_CHANNEL(9),
00233     IIO_AD717x_CHANNEL(10),
00234     IIO_AD717x_CHANNEL(11),
00235     IIO_AD717x_CHANNEL(12),
00236     IIO_AD717x_CHANNEL(13),
00237     IIO_AD717x_CHANNEL(14),
00238     IIO_AD717x_CHANNEL(15)
00239 #endif
00240 #endif
00241 };
00242 
00243 /**
00244  * @brief Read the debug register value
00245  * @param desc[in,out] - Pointer to IIO device descriptor
00246  * @param reg[in]- Address of the register to be read
00247  * @param readval[out]- Pointer to the register data variable
00248  * @return 0 in case of success, negative error code
00249  */
00250 static int32_t iio_ad717x_debug_reg_read(void *dev,
00251         uint32_t reg,
00252         uint32_t *readval)
00253 {
00254     int32_t debug_read_status; // Status check variable
00255 
00256     /* Retrieve the pointer to the requested register */
00257     ad717x_st_reg *read_register =  AD717X_GetReg(p_ad717x_dev_inst, reg);
00258     if (!read_register) {
00259         return -EINVAL;
00260     }
00261 
00262     /* Read the register data, extract the value */
00263     debug_read_status = AD717X_ReadRegister(p_ad717x_dev_inst, reg);
00264     if (debug_read_status) {
00265         return debug_read_status;
00266     }
00267     *readval = read_register->value;
00268 
00269     return 0;
00270 }
00271 
00272 
00273 /**
00274  * @brief Write value to the debug register
00275  * @param desc[in,out] Pointer to IIO device descriptor
00276  * @param reg[in] Address of the register where the data is to be written
00277  * @param write_val[out] Pointer to the register data variable
00278  * @return 0 in case of success, negative error code otherwise
00279  */
00280 static int32_t iio_ad717x_debug_reg_write(void *dev,
00281         uint32_t reg,
00282         uint32_t write_val)
00283 {
00284     int32_t debug_write_status; // Status check variable
00285     ad717x_st_reg *device_data_reg;  // Pointer to data register
00286 
00287     /* Retrieve the pointer to the requested registrer */
00288     device_data_reg = AD717X_GetReg(p_ad717x_dev_inst, reg);
00289     device_data_reg->value = write_val;
00290 
00291     /* Write value to the register */
00292     debug_write_status = AD717X_WriteRegister(p_ad717x_dev_inst, reg);
00293     if (debug_write_status) {
00294         return debug_write_status;
00295     }
00296 
00297     return 0;
00298 }
00299 
00300 
00301 /**
00302  * @brief Transfer the device data into memory (optional)
00303  * @param dev_instance[in] - IIO device instance
00304  * @param ch_mask[in] - Channels select mask
00305  * @return 0 in case of success or negative value otherwise
00306  */
00307 static int32_t iio_ad717x_pre_enable(void *dev_instance, uint32_t chn_mask)
00308 {
00309     return prepare_data_transfer(chn_mask, NUMBER_OF_CHANNELS, BYTES_PER_SAMPLE);
00310 }
00311 
00312 
00313 /**
00314  * @brief Read buffer data corresponding to AD4170 IIO device
00315  * @param iio_dev_data[in] - Pointer to IIO device data structure
00316  * @return 0 in case of success or negative value otherwise
00317  */
00318 static int32_t iio_ad717x_submit_buffer(struct iio_device_data *iio_dev_data)
00319 {
00320     int32_t ret;
00321 
00322     /* Read the samples counts equal to buffer size/block */
00323     ret = read_buffered_data(&iio_dev_data->buffer->buf->buff,
00324                  iio_dev_data->buffer->size);
00325 
00326     /* Increment the write spin count as buffer reads all 'n' samples
00327      * in one go which is also the size of buffer block for a given instance.
00328      * The read spin count is incremented from IIO library during buffer
00329      * write/offloading into transmit buffer */
00330     if (iio_dev_data->buffer->buf->write.spin_count >= UINT32_MAX) {
00331         iio_dev_data->buffer->buf->write.spin_count = 0;
00332     }
00333 
00334     iio_dev_data->buffer->buf->write.spin_count += 1;
00335 
00336     return ret;
00337 }
00338 
00339 
00340 /**
00341  * @brief Perform tasks before end of current data transfer
00342  * @param dev[in] - IIO device instance
00343  * @return 0 in case of success or negative value otherwise
00344  */
00345 static int32_t iio_ad717x_post_disable(void *dev)
00346 {
00347     return end_data_transfer();
00348 }
00349 
00350 
00351 /**
00352  * @brief Init for reading/writing and parameterization of a AD717x IIO device
00353  * @param desc[in,out] IIO device descriptor
00354  * @return 0 in case of success, negative error code otherwise
00355  */
00356 int32_t iio_ad717x_init(struct iio_device **desc)
00357 {
00358     struct iio_device *iio_ad717x_inst;  // IIO Device Descriptor for AD717x
00359 
00360     iio_ad717x_inst = calloc(1, sizeof(struct iio_device));
00361     if (!iio_ad717x_inst) {
00362         return -EINVAL;
00363     }
00364 
00365     iio_ad717x_inst->num_ch = NO_OS_ARRAY_SIZE(iio_adc_channels);
00366     iio_ad717x_inst->channels = iio_adc_channels;
00367     iio_ad717x_inst->attributes = iio_ad717x_global_attributes;
00368     iio_ad717x_inst->buffer_attributes = NULL;
00369     iio_ad717x_inst->write_dev = NULL;
00370     iio_ad717x_inst->pre_enable = iio_ad717x_pre_enable;
00371     iio_ad717x_inst->post_disable = iio_ad717x_post_disable;
00372     iio_ad717x_inst->submit = iio_ad717x_submit_buffer;
00373     iio_ad717x_inst->debug_reg_read = iio_ad717x_debug_reg_read;
00374     iio_ad717x_inst->debug_reg_write = iio_ad717x_debug_reg_write;
00375 
00376     *desc = iio_ad717x_inst;
00377 
00378     return 0;
00379 }
00380 
00381 
00382 /**
00383  * @brief Function to update scale and offset values based on user selection
00384  * @param device[in] AD717x device descriptor
00385  * @return 0 in case of success, negative error code otherwise
00386  */
00387 static int32_t ad717x_update_attr_parameters(ad717x_dev *device)
00388 {
00389     float reference_value = 0; // Variable to hold the updated reference value
00390     uint8_t i;
00391 
00392     for (i = 0; i < NUMBER_OF_CHANNELS; i++) {
00393         /* Update reference value */
00394         switch (device->setups[device->chan_map[i].setup_sel].ref_source) {
00395         case INTERNAL_REF:
00396             reference_value = AD717X_INTERNAL_REFERENCE;
00397             break;
00398         case EXTERNAL_REF:
00399             reference_value = AD717x_EXTERNAL_REFERENCE;
00400             break;
00401         case AVDD_AVSS:
00402             reference_value = AD717X_AVDD_AVSS_REFERENCE;
00403             break;
00404         default:
00405             return -EINVAL;
00406         }
00407 
00408         /* Update channel attribute parameters */
00409         if (!(device->setups[device->chan_map[i].setup_sel].bi_unipolar)) {
00410             /* Settings for Unipolar mode */
00411             attr_scale_val[i] = ((reference_value / ADC_MAX_COUNT_UNIPOLAR) * 1000) /
00412                         SCALE_FACTOR_DR;
00413             attr_offset_val[i] = 0;
00414             ad717x_scan_type[i].sign = 'u';
00415             ad717x_scan_type[i].realbits = AD717x_RESOLUTION;
00416         } else {
00417             /* Settings for Bipolar mode */
00418             attr_scale_val[i] = ((reference_value / (ADC_MAX_COUNT_BIPOLAR)) * 1000) /
00419                         SCALE_FACTOR_DR;
00420             attr_offset_val[i] = -(1 << (AD717x_RESOLUTION - 1));
00421             ad717x_scan_type[i].sign = 's';
00422             ad717x_scan_type[i].realbits = CHN_STORAGE_BITS;
00423         }
00424     }
00425 
00426     return 0;
00427 }
00428 
00429 
00430 /**
00431  * @brief   Initialize the AD717x IIO Interface
00432  * @return  0 in case of success, negative error code otherwise
00433  */
00434 int32_t ad717x_iio_initialize(void)
00435 {
00436     int32_t iio_init_status;            // Status check variable
00437     struct iio_init_param iio_init_params;      // IIO Init Parameters
00438     struct iio_device *ad717x_iio_desc;     //  aD717x IIO Descriptor
00439 
00440     /* Init the system peripheral- UART */
00441     iio_init_status = init_system();
00442     if (iio_init_status) {
00443         return iio_init_status;
00444     }
00445 
00446     /* IIO Initialization Parameters */
00447     iio_init_params.phy_type = USE_UART;
00448     iio_init_params.nb_devs = 1;
00449 
00450     /* IIOD init parameters */
00451     struct iio_device_init iio_device_init_params = {
00452         .name = (char*)dev_name,
00453         .raw_buf = adc_data_buffer,
00454         .raw_buf_len = DATA_BUFFER_SIZE
00455     };
00456 
00457     /* Initialize AD717x device */
00458     iio_init_status = AD717X_Init(&p_ad717x_dev_inst, ad717x_init_params);
00459     if (iio_init_status) {
00460         return iio_init_status;
00461     }
00462 
00463     /* Update the ADC scale respective to the device settings */
00464     iio_init_status = ad717x_update_attr_parameters(p_ad717x_dev_inst);
00465     if (iio_init_status) {
00466         return iio_init_status;
00467     }
00468 
00469     /* Initialize the AD717x IIO Interface */
00470     iio_init_status = iio_ad717x_init(&ad717x_iio_desc);
00471     if (iio_init_status) {
00472         return iio_init_status;
00473     }
00474 
00475     /* Initialize the IIO Interface */
00476     iio_init_params.uart_desc = uart_desc;
00477     iio_device_init_params.dev = p_ad717x_dev_inst;
00478     iio_device_init_params.dev_descriptor = ad717x_iio_desc;
00479     iio_init_params.devs = &iio_device_init_params;
00480     iio_init_params.nb_trigs = 0;
00481     iio_init_status = iio_init(&p_ad717x_iio_desc, &iio_init_params);
00482     if (iio_init_status) {
00483         return iio_init_status;
00484     }
00485 
00486     return 0;
00487 }
00488 
00489 
00490 /**
00491  * @brief   Run the AD717x IIO event handler
00492  * @return  None
00493  */
00494 void ad717x_iio_event_handler(void)
00495 {
00496     (void)iio_step(p_ad717x_iio_desc);
00497 }