IIO firmware for the AD4110

Dependencies:   tempsensors sdp_k1_sdram

Committer:
Janani Sunil
Date:
Wed Jul 27 17:04:15 2022 +0530
Revision:
0:6ca37a8f8ba9
Initial implementation for AD4110 IIO Firmware

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Janani Sunil 0:6ca37a8f8ba9 1 /***************************************************************************//**
Janani Sunil 0:6ca37a8f8ba9 2 * @file ad4110_data_capture.c
Janani Sunil 0:6ca37a8f8ba9 3 * @brief Source file for AD4110 Data capture
Janani Sunil 0:6ca37a8f8ba9 4 ********************************************************************************
Janani Sunil 0:6ca37a8f8ba9 5 * Copyright (c) 2022 Analog Devices, Inc.
Janani Sunil 0:6ca37a8f8ba9 6 * All rights reserved.
Janani Sunil 0:6ca37a8f8ba9 7 *
Janani Sunil 0:6ca37a8f8ba9 8 * This software is proprietary to Analog Devices, Inc. and its licensors.
Janani Sunil 0:6ca37a8f8ba9 9 * By using this software you agree to the terms of the associated
Janani Sunil 0:6ca37a8f8ba9 10 * Analog Devices Software License Agreement.
Janani Sunil 0:6ca37a8f8ba9 11 *******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 12
Janani Sunil 0:6ca37a8f8ba9 13 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 14 /***************************** Include Files **********************************/
Janani Sunil 0:6ca37a8f8ba9 15 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 16
Janani Sunil 0:6ca37a8f8ba9 17 #include <string.h>
Janani Sunil 0:6ca37a8f8ba9 18 #include "ad4110_data_capture.h"
Janani Sunil 0:6ca37a8f8ba9 19 #include "ad4110_iio.h"
Janani Sunil 0:6ca37a8f8ba9 20 #include "ad4110.h"
Janani Sunil 0:6ca37a8f8ba9 21 #include "no_os_error.h"
Janani Sunil 0:6ca37a8f8ba9 22 #include "app_config.h"
Janani Sunil 0:6ca37a8f8ba9 23
Janani Sunil 0:6ca37a8f8ba9 24 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 25 /********************* Macros and Constants Definition ************************/
Janani Sunil 0:6ca37a8f8ba9 26 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 27
Janani Sunil 0:6ca37a8f8ba9 28 /* Timeout count to avoid stuck into potential infinite loop while checking
Janani Sunil 0:6ca37a8f8ba9 29 * for new data into an acquisition buffer. The actual timeout factor is determined
Janani Sunil 0:6ca37a8f8ba9 30 * through 'sampling_frequency' attribute of IIO app, but this period here makes sure
Janani Sunil 0:6ca37a8f8ba9 31 * we are not stuck into a forever loop in case data capture is interrupted
Janani Sunil 0:6ca37a8f8ba9 32 * or failed in between.
Janani Sunil 0:6ca37a8f8ba9 33 * Note: This timeout factor is dependent upon the MCU clock frequency. Below timeout
Janani Sunil 0:6ca37a8f8ba9 34 * is tested for SDP-K1 platform @180Mhz default core clock */
Janani Sunil 0:6ca37a8f8ba9 35 #define BUF_READ_TIMEOUT 0xffffffff
Janani Sunil 0:6ca37a8f8ba9 36
Janani Sunil 0:6ca37a8f8ba9 37 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 38 /******************** Variables and User Defined Data Types *******************/
Janani Sunil 0:6ca37a8f8ba9 39 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 40
Janani Sunil 0:6ca37a8f8ba9 41 /*
Janani Sunil 0:6ca37a8f8ba9 42 *@enum acq_buffer_state_e
Janani Sunil 0:6ca37a8f8ba9 43 *@details Data acquisition buffer states
Janani Sunil 0:6ca37a8f8ba9 44 **/
Janani Sunil 0:6ca37a8f8ba9 45 typedef enum {
Janani Sunil 0:6ca37a8f8ba9 46 BUF_AVAILABLE,
Janani Sunil 0:6ca37a8f8ba9 47 BUF_EMPTY,
Janani Sunil 0:6ca37a8f8ba9 48 BUF_FULL
Janani Sunil 0:6ca37a8f8ba9 49 } acq_buffer_state_e;
Janani Sunil 0:6ca37a8f8ba9 50
Janani Sunil 0:6ca37a8f8ba9 51 /*
Janani Sunil 0:6ca37a8f8ba9 52 *@struct acq_buf_t
Janani Sunil 0:6ca37a8f8ba9 53 *@details Data acquisition buffer parameters
Janani Sunil 0:6ca37a8f8ba9 54 **/
Janani Sunil 0:6ca37a8f8ba9 55 typedef struct {
Janani Sunil 0:6ca37a8f8ba9 56 acq_buffer_state_e state; // Buffer state
Janani Sunil 0:6ca37a8f8ba9 57 uint32_t wr_indx; // Buffer write index (incremented per sample read)
Janani Sunil 0:6ca37a8f8ba9 58 uint32_t rd_indx; // Buffer read index (incremented per sample read)
Janani Sunil 0:6ca37a8f8ba9 59 int8_t *wr_pdata; // Data buffer write pointer
Janani Sunil 0:6ca37a8f8ba9 60 int8_t *rd_pdata; // Data buffer read pointer
Janani Sunil 0:6ca37a8f8ba9 61 bool reindex_buffer; // Reindex buffer to 0th channel
Janani Sunil 0:6ca37a8f8ba9 62 } acq_buf_t;
Janani Sunil 0:6ca37a8f8ba9 63
Janani Sunil 0:6ca37a8f8ba9 64 /* ADC data acquisition buffers */
Janani Sunil 0:6ca37a8f8ba9 65 static volatile acq_buf_t acq_buffer;
Janani Sunil 0:6ca37a8f8ba9 66
Janani Sunil 0:6ca37a8f8ba9 67 /* Number of samples requested by IIO client */
Janani Sunil 0:6ca37a8f8ba9 68 static volatile uint32_t num_of_requested_samples = 0;
Janani Sunil 0:6ca37a8f8ba9 69
Janani Sunil 0:6ca37a8f8ba9 70 /* Number of active channels */
Janani Sunil 0:6ca37a8f8ba9 71 static volatile uint8_t num_of_active_channels;
Janani Sunil 0:6ca37a8f8ba9 72
Janani Sunil 0:6ca37a8f8ba9 73 /* ADC sample/raw data size in bytes */
Janani Sunil 0:6ca37a8f8ba9 74 static volatile uint8_t sample_size_in_bytes;
Janani Sunil 0:6ca37a8f8ba9 75
Janani Sunil 0:6ca37a8f8ba9 76 /* ADC data buffer */
Janani Sunil 0:6ca37a8f8ba9 77 #if !defined(USE_SDRAM_CAPTURE_BUFFER)
Janani Sunil 0:6ca37a8f8ba9 78 int8_t adc_data_buffer[DATA_BUFFER_SIZE] = { 0 };
Janani Sunil 0:6ca37a8f8ba9 79 #endif
Janani Sunil 0:6ca37a8f8ba9 80
Janani Sunil 0:6ca37a8f8ba9 81 /* List of input channels to be captured */
Janani Sunil 0:6ca37a8f8ba9 82 static volatile uint8_t input_channels[AD4110_NUM_CHANNELS];
Janani Sunil 0:6ca37a8f8ba9 83
Janani Sunil 0:6ca37a8f8ba9 84 /* Flag to indicate data capture status */
Janani Sunil 0:6ca37a8f8ba9 85 static volatile bool start_cont_data_capture = false;
Janani Sunil 0:6ca37a8f8ba9 86
Janani Sunil 0:6ca37a8f8ba9 87 /* Max available buffer size (after considering the data alignment with IIO buffer) */
Janani Sunil 0:6ca37a8f8ba9 88 static volatile uint32_t max_buffer_sz;
Janani Sunil 0:6ca37a8f8ba9 89
Janani Sunil 0:6ca37a8f8ba9 90 /* Current active channel index */
Janani Sunil 0:6ca37a8f8ba9 91 static volatile uint8_t chn_indx;
Janani Sunil 0:6ca37a8f8ba9 92
Janani Sunil 0:6ca37a8f8ba9 93 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 94 /************************** Functions Declaration *****************************/
Janani Sunil 0:6ca37a8f8ba9 95 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 96
Janani Sunil 0:6ca37a8f8ba9 97 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 98 /************************** Functions Definition ******************************/
Janani Sunil 0:6ca37a8f8ba9 99 /******************************************************************************/
Janani Sunil 0:6ca37a8f8ba9 100
Janani Sunil 0:6ca37a8f8ba9 101 /*!
Janani Sunil 0:6ca37a8f8ba9 102 * @brief Reset the data capture specific variables
Janani Sunil 0:6ca37a8f8ba9 103 * @return none
Janani Sunil 0:6ca37a8f8ba9 104 */
Janani Sunil 0:6ca37a8f8ba9 105 static void reset_data_capture(void)
Janani Sunil 0:6ca37a8f8ba9 106 {
Janani Sunil 0:6ca37a8f8ba9 107 /* Reset data capture flags */
Janani Sunil 0:6ca37a8f8ba9 108 num_of_active_channels = 0;
Janani Sunil 0:6ca37a8f8ba9 109 start_cont_data_capture = false;
Janani Sunil 0:6ca37a8f8ba9 110
Janani Sunil 0:6ca37a8f8ba9 111 /* Reset acquisition buffer states and clear old data */
Janani Sunil 0:6ca37a8f8ba9 112 acq_buffer.state = BUF_EMPTY;
Janani Sunil 0:6ca37a8f8ba9 113 acq_buffer.wr_indx = 0;
Janani Sunil 0:6ca37a8f8ba9 114 acq_buffer.rd_indx = 0;
Janani Sunil 0:6ca37a8f8ba9 115 acq_buffer.reindex_buffer = false;
Janani Sunil 0:6ca37a8f8ba9 116
Janani Sunil 0:6ca37a8f8ba9 117 acq_buffer.wr_pdata = adc_data_buffer;
Janani Sunil 0:6ca37a8f8ba9 118 acq_buffer.rd_pdata = adc_data_buffer;
Janani Sunil 0:6ca37a8f8ba9 119 max_buffer_sz = DATA_BUFFER_SIZE;
Janani Sunil 0:6ca37a8f8ba9 120 }
Janani Sunil 0:6ca37a8f8ba9 121
Janani Sunil 0:6ca37a8f8ba9 122
Janani Sunil 0:6ca37a8f8ba9 123 /*!
Janani Sunil 0:6ca37a8f8ba9 124 * @brief Trigger a data capture in continuous/burst mode
Janani Sunil 0:6ca37a8f8ba9 125 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 126 */
Janani Sunil 0:6ca37a8f8ba9 127 static int32_t adc_start_data_capture(void)
Janani Sunil 0:6ca37a8f8ba9 128 {
Janani Sunil 0:6ca37a8f8ba9 129 return ad4110_set_adc_mode(ad4110_dev_inst, AD4110_CONTINOUS_CONV_MODE);
Janani Sunil 0:6ca37a8f8ba9 130 }
Janani Sunil 0:6ca37a8f8ba9 131
Janani Sunil 0:6ca37a8f8ba9 132
Janani Sunil 0:6ca37a8f8ba9 133 /*!
Janani Sunil 0:6ca37a8f8ba9 134 * @brief Stop a data capture operation
Janani Sunil 0:6ca37a8f8ba9 135 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 136 */
Janani Sunil 0:6ca37a8f8ba9 137 static int32_t adc_stop_data_capture(void)
Janani Sunil 0:6ca37a8f8ba9 138 {
Janani Sunil 0:6ca37a8f8ba9 139 return ad4110_set_adc_mode(ad4110_dev_inst, AD4110_STANDBY_MODE);
Janani Sunil 0:6ca37a8f8ba9 140 }
Janani Sunil 0:6ca37a8f8ba9 141
Janani Sunil 0:6ca37a8f8ba9 142
Janani Sunil 0:6ca37a8f8ba9 143 /*!
Janani Sunil 0:6ca37a8f8ba9 144 * @brief Function to prepare the data ADC capture for new READBUFF
Janani Sunil 0:6ca37a8f8ba9 145 * request from IIO client (for active channels)
Janani Sunil 0:6ca37a8f8ba9 146 * @param chn_mask[in] - Channels to enable for data capturing
Janani Sunil 0:6ca37a8f8ba9 147 * @param num_of_chns[in] - ADC channel count
Janani Sunil 0:6ca37a8f8ba9 148 * @param sample_size[in] - Sample size in bytes
Janani Sunil 0:6ca37a8f8ba9 149 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 150 */
Janani Sunil 0:6ca37a8f8ba9 151 int32_t prepare_data_transfer(uint32_t ch_mask, uint8_t num_of_chns,
Janani Sunil 0:6ca37a8f8ba9 152 uint8_t sample_size)
Janani Sunil 0:6ca37a8f8ba9 153 {
Janani Sunil 0:6ca37a8f8ba9 154 int32_t ret;
Janani Sunil 0:6ca37a8f8ba9 155 uint8_t ch_id;
Janani Sunil 0:6ca37a8f8ba9 156 uint8_t mask = 0x1;
Janani Sunil 0:6ca37a8f8ba9 157
Janani Sunil 0:6ca37a8f8ba9 158 /* Reset the data capture module */
Janani Sunil 0:6ca37a8f8ba9 159 reset_data_capture();
Janani Sunil 0:6ca37a8f8ba9 160
Janani Sunil 0:6ca37a8f8ba9 161 sample_size_in_bytes = sample_size;
Janani Sunil 0:6ca37a8f8ba9 162
Janani Sunil 0:6ca37a8f8ba9 163 /* Enable Active channels requested and Disable the remaining */
Janani Sunil 0:6ca37a8f8ba9 164 for (ch_id = 0;
Janani Sunil 0:6ca37a8f8ba9 165 ch_id < num_of_chns; ch_id++) {
Janani Sunil 0:6ca37a8f8ba9 166 if (ch_mask & mask) {
Janani Sunil 0:6ca37a8f8ba9 167 ret = ad4110_set_channel_status(ad4110_dev_inst, ch_id, true);
Janani Sunil 0:6ca37a8f8ba9 168 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 169 return ret;
Janani Sunil 0:6ca37a8f8ba9 170 }
Janani Sunil 0:6ca37a8f8ba9 171 num_of_requested_samples++;
Janani Sunil 0:6ca37a8f8ba9 172 } else {
Janani Sunil 0:6ca37a8f8ba9 173 ret = ad4110_set_channel_status(ad4110_dev_inst, ch_id, false);
Janani Sunil 0:6ca37a8f8ba9 174 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 175 return ret;
Janani Sunil 0:6ca37a8f8ba9 176 }
Janani Sunil 0:6ca37a8f8ba9 177 }
Janani Sunil 0:6ca37a8f8ba9 178 mask <<= 1;
Janani Sunil 0:6ca37a8f8ba9 179 }
Janani Sunil 0:6ca37a8f8ba9 180
Janani Sunil 0:6ca37a8f8ba9 181 /* Trigger continuous data capture */
Janani Sunil 0:6ca37a8f8ba9 182 #if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE)
Janani Sunil 0:6ca37a8f8ba9 183 ret = adc_start_data_capture();
Janani Sunil 0:6ca37a8f8ba9 184 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 185 return ret;
Janani Sunil 0:6ca37a8f8ba9 186 }
Janani Sunil 0:6ca37a8f8ba9 187
Janani Sunil 0:6ca37a8f8ba9 188 acq_buffer.state = BUF_AVAILABLE;
Janani Sunil 0:6ca37a8f8ba9 189 start_cont_data_capture = true;
Janani Sunil 0:6ca37a8f8ba9 190
Janani Sunil 0:6ca37a8f8ba9 191 /* Pull the cs line low to detect the EOC bit during data capture */
Janani Sunil 0:6ca37a8f8ba9 192 ret = no_os_gpio_set_value(csb_gpio, NO_OS_GPIO_LOW);
Janani Sunil 0:6ca37a8f8ba9 193 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 194 return ret;
Janani Sunil 0:6ca37a8f8ba9 195 }
Janani Sunil 0:6ca37a8f8ba9 196
Janani Sunil 0:6ca37a8f8ba9 197 ret = no_os_irq_enable(external_int_desc, IRQ_INT_ID);
Janani Sunil 0:6ca37a8f8ba9 198 if(ret) {
Janani Sunil 0:6ca37a8f8ba9 199 return ret;
Janani Sunil 0:6ca37a8f8ba9 200 }
Janani Sunil 0:6ca37a8f8ba9 201 #endif
Janani Sunil 0:6ca37a8f8ba9 202
Janani Sunil 0:6ca37a8f8ba9 203 return 0;
Janani Sunil 0:6ca37a8f8ba9 204 }
Janani Sunil 0:6ca37a8f8ba9 205
Janani Sunil 0:6ca37a8f8ba9 206
Janani Sunil 0:6ca37a8f8ba9 207 /*!
Janani Sunil 0:6ca37a8f8ba9 208 * @brief Function to end data capture
Janani Sunil 0:6ca37a8f8ba9 209 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 210 */
Janani Sunil 0:6ca37a8f8ba9 211 int32_t end_data_transfer(void)
Janani Sunil 0:6ca37a8f8ba9 212 {
Janani Sunil 0:6ca37a8f8ba9 213 start_cont_data_capture = false;
Janani Sunil 0:6ca37a8f8ba9 214
Janani Sunil 0:6ca37a8f8ba9 215 /* Reset data capture module specific flags and variables */
Janani Sunil 0:6ca37a8f8ba9 216 reset_data_capture();
Janani Sunil 0:6ca37a8f8ba9 217
Janani Sunil 0:6ca37a8f8ba9 218 /* Stop ADC data capture */
Janani Sunil 0:6ca37a8f8ba9 219 return adc_stop_data_capture();
Janani Sunil 0:6ca37a8f8ba9 220 }
Janani Sunil 0:6ca37a8f8ba9 221
Janani Sunil 0:6ca37a8f8ba9 222
Janani Sunil 0:6ca37a8f8ba9 223 /*!
Janani Sunil 0:6ca37a8f8ba9 224 * @brief Capture requested number of ADC samples in burst mode
Janani Sunil 0:6ca37a8f8ba9 225 * @param pbuf[out] - Pointer to ADC data buffer
Janani Sunil 0:6ca37a8f8ba9 226 * @param nb_of_samples[in] - Number of samples to be read
Janani Sunil 0:6ca37a8f8ba9 227 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 228 */
Janani Sunil 0:6ca37a8f8ba9 229 static int32_t read_burst_data(int8_t *pbuf, uint32_t nb_of_samples)
Janani Sunil 0:6ca37a8f8ba9 230 {
Janani Sunil 0:6ca37a8f8ba9 231 uint32_t sample_index = 0;
Janani Sunil 0:6ca37a8f8ba9 232 uint32_t adc_raw_data = 0;
Janani Sunil 0:6ca37a8f8ba9 233 int32_t ret;
Janani Sunil 0:6ca37a8f8ba9 234
Janani Sunil 0:6ca37a8f8ba9 235 if (adc_start_data_capture()) {
Janani Sunil 0:6ca37a8f8ba9 236 return -EIO;
Janani Sunil 0:6ca37a8f8ba9 237 }
Janani Sunil 0:6ca37a8f8ba9 238
Janani Sunil 0:6ca37a8f8ba9 239 while (sample_index < nb_of_samples) {
Janani Sunil 0:6ca37a8f8ba9 240 /* Wait for the RDY Bit to go low to notify end of conversion */
Janani Sunil 0:6ca37a8f8ba9 241 ret = ad4110_wait_for_rdy_low(ad4110_dev_inst, AD4110_ADC_CONV_TIMEOUT);
Janani Sunil 0:6ca37a8f8ba9 242 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 243 return ret;
Janani Sunil 0:6ca37a8f8ba9 244 }
Janani Sunil 0:6ca37a8f8ba9 245
Janani Sunil 0:6ca37a8f8ba9 246 /* Read the converted data from the Data register */
Janani Sunil 0:6ca37a8f8ba9 247 ret = ad4110_spi_int_data_reg_read(ad4110_dev_inst, &adc_raw_data);
Janani Sunil 0:6ca37a8f8ba9 248 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 249 return ret;
Janani Sunil 0:6ca37a8f8ba9 250 }
Janani Sunil 0:6ca37a8f8ba9 251
Janani Sunil 0:6ca37a8f8ba9 252 /* Copy raw data to the buffer */
Janani Sunil 0:6ca37a8f8ba9 253 memcpy((uint8_t*)pbuf, &adc_raw_data, sample_size_in_bytes);
Janani Sunil 0:6ca37a8f8ba9 254 sample_index++;
Janani Sunil 0:6ca37a8f8ba9 255 pbuf += sample_size_in_bytes;
Janani Sunil 0:6ca37a8f8ba9 256 }
Janani Sunil 0:6ca37a8f8ba9 257
Janani Sunil 0:6ca37a8f8ba9 258 /* Stop any active conversion */
Janani Sunil 0:6ca37a8f8ba9 259 ret = adc_stop_data_capture();
Janani Sunil 0:6ca37a8f8ba9 260 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 261 return ret;
Janani Sunil 0:6ca37a8f8ba9 262 }
Janani Sunil 0:6ca37a8f8ba9 263
Janani Sunil 0:6ca37a8f8ba9 264 return 0;
Janani Sunil 0:6ca37a8f8ba9 265 }
Janani Sunil 0:6ca37a8f8ba9 266
Janani Sunil 0:6ca37a8f8ba9 267
Janani Sunil 0:6ca37a8f8ba9 268 /*!
Janani Sunil 0:6ca37a8f8ba9 269 * @brief Perform buffer read operations to read requested samples
Janani Sunil 0:6ca37a8f8ba9 270 * @param nb_of_samples[in] - Requested number of samples to read
Janani Sunil 0:6ca37a8f8ba9 271 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 272 */
Janani Sunil 0:6ca37a8f8ba9 273 static int32_t buffer_read_operations(uint32_t nb_of_samples)
Janani Sunil 0:6ca37a8f8ba9 274 {
Janani Sunil 0:6ca37a8f8ba9 275 uint32_t timeout = BUF_READ_TIMEOUT;
Janani Sunil 0:6ca37a8f8ba9 276 int32_t offset;
Janani Sunil 0:6ca37a8f8ba9 277
Janani Sunil 0:6ca37a8f8ba9 278 /* Wait until requested samples are available in the buffer to read */
Janani Sunil 0:6ca37a8f8ba9 279 do {
Janani Sunil 0:6ca37a8f8ba9 280 if (acq_buffer.wr_indx >= acq_buffer.rd_indx) {
Janani Sunil 0:6ca37a8f8ba9 281 offset = acq_buffer.wr_indx - acq_buffer.rd_indx;
Janani Sunil 0:6ca37a8f8ba9 282 } else {
Janani Sunil 0:6ca37a8f8ba9 283 offset = max_buffer_sz + (acq_buffer.wr_indx - acq_buffer.rd_indx);
Janani Sunil 0:6ca37a8f8ba9 284 }
Janani Sunil 0:6ca37a8f8ba9 285
Janani Sunil 0:6ca37a8f8ba9 286 timeout--;
Janani Sunil 0:6ca37a8f8ba9 287 } while ((offset < (int32_t)(nb_of_samples)) && (timeout > 0));
Janani Sunil 0:6ca37a8f8ba9 288
Janani Sunil 0:6ca37a8f8ba9 289 if (timeout == 0) {
Janani Sunil 0:6ca37a8f8ba9 290 /* This returns the empty buffer */
Janani Sunil 0:6ca37a8f8ba9 291 return -EIO;
Janani Sunil 0:6ca37a8f8ba9 292 }
Janani Sunil 0:6ca37a8f8ba9 293
Janani Sunil 0:6ca37a8f8ba9 294 if (acq_buffer.rd_indx >= max_buffer_sz) {
Janani Sunil 0:6ca37a8f8ba9 295 acq_buffer.rd_indx = 0;
Janani Sunil 0:6ca37a8f8ba9 296 }
Janani Sunil 0:6ca37a8f8ba9 297
Janani Sunil 0:6ca37a8f8ba9 298 return 0;
Janani Sunil 0:6ca37a8f8ba9 299 }
Janani Sunil 0:6ca37a8f8ba9 300
Janani Sunil 0:6ca37a8f8ba9 301
Janani Sunil 0:6ca37a8f8ba9 302 /*!
Janani Sunil 0:6ca37a8f8ba9 303 * @brief Perform buffer write operations such as buffer full or empty
Janani Sunil 0:6ca37a8f8ba9 304 * check, resetting buffer index and pointers, etc
Janani Sunil 0:6ca37a8f8ba9 305 * @return none
Janani Sunil 0:6ca37a8f8ba9 306 */
Janani Sunil 0:6ca37a8f8ba9 307 static void buffer_write_operations(void)
Janani Sunil 0:6ca37a8f8ba9 308 {
Janani Sunil 0:6ca37a8f8ba9 309 acq_buffer.wr_indx++;
Janani Sunil 0:6ca37a8f8ba9 310
Janani Sunil 0:6ca37a8f8ba9 311 /* Perform buffer full check and operations */
Janani Sunil 0:6ca37a8f8ba9 312 if (acq_buffer.wr_indx >= max_buffer_sz) {
Janani Sunil 0:6ca37a8f8ba9 313 if ((acq_buffer.rd_indx >= num_of_requested_samples)
Janani Sunil 0:6ca37a8f8ba9 314 && (acq_buffer.rd_indx != 0)) {
Janani Sunil 0:6ca37a8f8ba9 315 /* Reset buffer write index and write pointer when enough
Janani Sunil 0:6ca37a8f8ba9 316 * space available in the buffer to wrap to start */
Janani Sunil 0:6ca37a8f8ba9 317 acq_buffer.wr_indx = 0;
Janani Sunil 0:6ca37a8f8ba9 318
Janani Sunil 0:6ca37a8f8ba9 319 acq_buffer.wr_pdata = adc_data_buffer;
Janani Sunil 0:6ca37a8f8ba9 320 if (acq_buffer.rd_indx >= max_buffer_sz) {
Janani Sunil 0:6ca37a8f8ba9 321 /* Wrap the read index and read pointer to start of buffer
Janani Sunil 0:6ca37a8f8ba9 322 * if buffer is completely read/emptied */
Janani Sunil 0:6ca37a8f8ba9 323 acq_buffer.rd_indx = 0;
Janani Sunil 0:6ca37a8f8ba9 324 acq_buffer.rd_pdata = adc_data_buffer;
Janani Sunil 0:6ca37a8f8ba9 325 }
Janani Sunil 0:6ca37a8f8ba9 326
Janani Sunil 0:6ca37a8f8ba9 327 acq_buffer.state = BUF_AVAILABLE;
Janani Sunil 0:6ca37a8f8ba9 328 } else {
Janani Sunil 0:6ca37a8f8ba9 329 /* Wait until enough space available to wrap buffer write index
Janani Sunil 0:6ca37a8f8ba9 330 * at the start of buffer */
Janani Sunil 0:6ca37a8f8ba9 331 acq_buffer.wr_indx = max_buffer_sz;
Janani Sunil 0:6ca37a8f8ba9 332 acq_buffer.state = BUF_FULL;
Janani Sunil 0:6ca37a8f8ba9 333 acq_buffer.reindex_buffer = true;
Janani Sunil 0:6ca37a8f8ba9 334 }
Janani Sunil 0:6ca37a8f8ba9 335 }
Janani Sunil 0:6ca37a8f8ba9 336 }
Janani Sunil 0:6ca37a8f8ba9 337
Janani Sunil 0:6ca37a8f8ba9 338
Janani Sunil 0:6ca37a8f8ba9 339 /*!
Janani Sunil 0:6ca37a8f8ba9 340 * @brief Read requested number of ADC samples in continuous mode
Janani Sunil 0:6ca37a8f8ba9 341 * @param pbuf[in] - Pointer to data buffer
Janani Sunil 0:6ca37a8f8ba9 342 * @param nb_of_samples[in] - Number of samples to read
Janani Sunil 0:6ca37a8f8ba9 343 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 344 * @note The actual sample capturing happens through interrupt. This
Janani Sunil 0:6ca37a8f8ba9 345 * function tracks the buffer read pointer to read block of data
Janani Sunil 0:6ca37a8f8ba9 346 */
Janani Sunil 0:6ca37a8f8ba9 347 static int32_t read_continuous_conv_data(int8_t **pbuf, uint32_t nb_of_samples)
Janani Sunil 0:6ca37a8f8ba9 348 {
Janani Sunil 0:6ca37a8f8ba9 349 volatile int8_t *rd_addr;
Janani Sunil 0:6ca37a8f8ba9 350 int32_t ret;
Janani Sunil 0:6ca37a8f8ba9 351
Janani Sunil 0:6ca37a8f8ba9 352 /* Determine the max available buffer size based on the requested
Janani Sunil 0:6ca37a8f8ba9 353 * samples count and actual avilable buffer size. Buffer should be
Janani Sunil 0:6ca37a8f8ba9 354 * capable of holding all requested 'n' samples from previous write
Janani Sunil 0:6ca37a8f8ba9 355 * index upto to the end of buffer, as data is read linearly
Janani Sunil 0:6ca37a8f8ba9 356 * from adc buffer in IIO library.
Janani Sunil 0:6ca37a8f8ba9 357 * E.g. If actual buffer size is 2048 samples and requested samples
Janani Sunil 0:6ca37a8f8ba9 358 * are 1600, max available buffer size is actually 1600. So in given
Janani Sunil 0:6ca37a8f8ba9 359 * iteration, only 1600 samples will be stored into buffer and after
Janani Sunil 0:6ca37a8f8ba9 360 * that buffer indexes will be wrapped to a start of buffer. If index
Janani Sunil 0:6ca37a8f8ba9 361 * is not wrapped, the next 1600 requested samples won't accomodate into
Janani Sunil 0:6ca37a8f8ba9 362 * remaining 448 samples space. As buffer is read in linear fashion, the
Janani Sunil 0:6ca37a8f8ba9 363 * read index can't be wrapped to start of buffer to read remaining samples.
Janani Sunil 0:6ca37a8f8ba9 364 * So max available space in this case is 2048 but only utilized space
Janani Sunil 0:6ca37a8f8ba9 365 * will be 1600 in single read buffer request from IIO client.
Janani Sunil 0:6ca37a8f8ba9 366 **/
Janani Sunil 0:6ca37a8f8ba9 367 max_buffer_sz = ((DATA_BUFFER_SIZE / sample_size_in_bytes) /
Janani Sunil 0:6ca37a8f8ba9 368 nb_of_samples) * nb_of_samples;
Janani Sunil 0:6ca37a8f8ba9 369
Janani Sunil 0:6ca37a8f8ba9 370 ret = buffer_read_operations(nb_of_samples);
Janani Sunil 0:6ca37a8f8ba9 371 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 372 return ret;
Janani Sunil 0:6ca37a8f8ba9 373 }
Janani Sunil 0:6ca37a8f8ba9 374
Janani Sunil 0:6ca37a8f8ba9 375 /* Get the next read address */
Janani Sunil 0:6ca37a8f8ba9 376 rd_addr = (volatile int8_t *)(acq_buffer.rd_pdata + (acq_buffer.rd_indx *
Janani Sunil 0:6ca37a8f8ba9 377 sample_size_in_bytes));
Janani Sunil 0:6ca37a8f8ba9 378 acq_buffer.rd_indx += nb_of_samples;
Janani Sunil 0:6ca37a8f8ba9 379
Janani Sunil 0:6ca37a8f8ba9 380 /* Update the IIO buffer pointer to point to next read start location */
Janani Sunil 0:6ca37a8f8ba9 381 *pbuf = rd_addr;
Janani Sunil 0:6ca37a8f8ba9 382
Janani Sunil 0:6ca37a8f8ba9 383 return 0;
Janani Sunil 0:6ca37a8f8ba9 384 }
Janani Sunil 0:6ca37a8f8ba9 385
Janani Sunil 0:6ca37a8f8ba9 386
Janani Sunil 0:6ca37a8f8ba9 387 /*!
Janani Sunil 0:6ca37a8f8ba9 388 * @brief Read ADC raw data for recently sampled channel
Janani Sunil 0:6ca37a8f8ba9 389 * @param adc_data[out] - Pointer to adc data read variable
Janani Sunil 0:6ca37a8f8ba9 390 * @param input_chn[in] - Input channel
Janani Sunil 0:6ca37a8f8ba9 391 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 392 * @note This function is intended to call from the conversion end trigger
Janani Sunil 0:6ca37a8f8ba9 393 * event. Therefore, this function should just read raw ADC data
Janani Sunil 0:6ca37a8f8ba9 394 * without further monitoring conversion end event
Janani Sunil 0:6ca37a8f8ba9 395 */
Janani Sunil 0:6ca37a8f8ba9 396 static int32_t adc_read_converted_sample(uint32_t *adc_data, uint8_t input_chn)
Janani Sunil 0:6ca37a8f8ba9 397 {
Janani Sunil 0:6ca37a8f8ba9 398 int32_t ret;
Janani Sunil 0:6ca37a8f8ba9 399
Janani Sunil 0:6ca37a8f8ba9 400 if (!adc_data) {
Janani Sunil 0:6ca37a8f8ba9 401 return -EIO;
Janani Sunil 0:6ca37a8f8ba9 402 }
Janani Sunil 0:6ca37a8f8ba9 403
Janani Sunil 0:6ca37a8f8ba9 404 ret = ad4110_spi_int_data_reg_read(ad4110_dev_inst, adc_data);
Janani Sunil 0:6ca37a8f8ba9 405 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 406 return ret;
Janani Sunil 0:6ca37a8f8ba9 407 }
Janani Sunil 0:6ca37a8f8ba9 408
Janani Sunil 0:6ca37a8f8ba9 409 /* Pull the cs line low to detect the EOC bit during data capture */
Janani Sunil 0:6ca37a8f8ba9 410 ret = no_os_gpio_set_value(csb_gpio, NO_OS_GPIO_LOW);
Janani Sunil 0:6ca37a8f8ba9 411 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 412 return ret;
Janani Sunil 0:6ca37a8f8ba9 413 }
Janani Sunil 0:6ca37a8f8ba9 414
Janani Sunil 0:6ca37a8f8ba9 415 ret = no_os_irq_enable(external_int_desc, IRQ_INT_ID);
Janani Sunil 0:6ca37a8f8ba9 416 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 417 return ret;
Janani Sunil 0:6ca37a8f8ba9 418 }
Janani Sunil 0:6ca37a8f8ba9 419
Janani Sunil 0:6ca37a8f8ba9 420 return 0;
Janani Sunil 0:6ca37a8f8ba9 421 }
Janani Sunil 0:6ca37a8f8ba9 422
Janani Sunil 0:6ca37a8f8ba9 423
Janani Sunil 0:6ca37a8f8ba9 424 /*!
Janani Sunil 0:6ca37a8f8ba9 425 * @brief This is an ISR (Interrupt Service Routine) to monitor end of conversion event.
Janani Sunil 0:6ca37a8f8ba9 426 * @param ctx[in] - Callback context (unused)
Janani Sunil 0:6ca37a8f8ba9 427 * @return none
Janani Sunil 0:6ca37a8f8ba9 428 * @details This is an Interrupt callback function/ISR invoked in synchronous/asynchronous
Janani Sunil 0:6ca37a8f8ba9 429 * manner depending upon the application implementation. The conversion results
Janani Sunil 0:6ca37a8f8ba9 430 * are read into acquisition buffer and control continue to sample next channel.
Janani Sunil 0:6ca37a8f8ba9 431 * This continues until conversion is stopped (through IIO client command)
Janani Sunil 0:6ca37a8f8ba9 432 */
Janani Sunil 0:6ca37a8f8ba9 433 void data_capture_callback(void *ctx)
Janani Sunil 0:6ca37a8f8ba9 434 {
Janani Sunil 0:6ca37a8f8ba9 435 uint32_t adc_sample;
Janani Sunil 0:6ca37a8f8ba9 436 volatile uint8_t *wr_addr;
Janani Sunil 0:6ca37a8f8ba9 437
Janani Sunil 0:6ca37a8f8ba9 438 /* The callback function is triggered when the first falling edge is detected
Janani Sunil 0:6ca37a8f8ba9 439 * on the MISO pin, indicating End of Conversion. Interrupt is disabled
Janani Sunil 0:6ca37a8f8ba9 440 because any data transaction on the SPI line could be interpreted
Janani Sunil 0:6ca37a8f8ba9 441 by the MCU as a falling edge.
Janani Sunil 0:6ca37a8f8ba9 442 */
Janani Sunil 0:6ca37a8f8ba9 443
Janani Sunil 0:6ca37a8f8ba9 444 no_os_irq_disable(external_int_desc, IRQ_INT_ID);
Janani Sunil 0:6ca37a8f8ba9 445
Janani Sunil 0:6ca37a8f8ba9 446 if (start_cont_data_capture == true) {
Janani Sunil 0:6ca37a8f8ba9 447 /* Read the sample for channel which has been sampled recently */
Janani Sunil 0:6ca37a8f8ba9 448 if (adc_read_converted_sample(&adc_sample,
Janani Sunil 0:6ca37a8f8ba9 449 input_channels[chn_indx]) == 0) {
Janani Sunil 0:6ca37a8f8ba9 450 do {
Janani Sunil 0:6ca37a8f8ba9 451 if (acq_buffer.state == BUF_AVAILABLE) {
Janani Sunil 0:6ca37a8f8ba9 452 if (acq_buffer.reindex_buffer) {
Janani Sunil 0:6ca37a8f8ba9 453 /* Buffer refilling must start with first active channel data
Janani Sunil 0:6ca37a8f8ba9 454 * for IIO client to synchronize the buffered data */
Janani Sunil 0:6ca37a8f8ba9 455 if (chn_indx != 0) {
Janani Sunil 0:6ca37a8f8ba9 456 break;
Janani Sunil 0:6ca37a8f8ba9 457 }
Janani Sunil 0:6ca37a8f8ba9 458 acq_buffer.reindex_buffer = false;
Janani Sunil 0:6ca37a8f8ba9 459 }
Janani Sunil 0:6ca37a8f8ba9 460
Janani Sunil 0:6ca37a8f8ba9 461 /* Copy adc samples into acquisition buffer to transport over
Janani Sunil 0:6ca37a8f8ba9 462 * communication link */
Janani Sunil 0:6ca37a8f8ba9 463 wr_addr = (volatile uint8_t *)(acq_buffer.wr_pdata + (acq_buffer.wr_indx *
Janani Sunil 0:6ca37a8f8ba9 464 sample_size_in_bytes));
Janani Sunil 0:6ca37a8f8ba9 465 memcpy((uint8_t *)wr_addr, &adc_sample, sample_size_in_bytes);
Janani Sunil 0:6ca37a8f8ba9 466 }
Janani Sunil 0:6ca37a8f8ba9 467
Janani Sunil 0:6ca37a8f8ba9 468 /* Perform buffer write operations */
Janani Sunil 0:6ca37a8f8ba9 469 buffer_write_operations();
Janani Sunil 0:6ca37a8f8ba9 470 } while (0);
Janani Sunil 0:6ca37a8f8ba9 471
Janani Sunil 0:6ca37a8f8ba9 472 /* Track the count for recently sampled channel */
Janani Sunil 0:6ca37a8f8ba9 473 chn_indx++;
Janani Sunil 0:6ca37a8f8ba9 474 if (chn_indx >= num_of_active_channels) {
Janani Sunil 0:6ca37a8f8ba9 475 chn_indx = 0;
Janani Sunil 0:6ca37a8f8ba9 476 }
Janani Sunil 0:6ca37a8f8ba9 477 }
Janani Sunil 0:6ca37a8f8ba9 478 }
Janani Sunil 0:6ca37a8f8ba9 479 }
Janani Sunil 0:6ca37a8f8ba9 480
Janani Sunil 0:6ca37a8f8ba9 481
Janani Sunil 0:6ca37a8f8ba9 482 /*!
Janani Sunil 0:6ca37a8f8ba9 483 * @brief Function to read the ADC buffered raw data requested by IIO client
Janani Sunil 0:6ca37a8f8ba9 484 * @param pbuf[in] - Pointer to data buffer
Janani Sunil 0:6ca37a8f8ba9 485 * @param nb_of_bytes[in] - Number of bytes to read
Janani Sunil 0:6ca37a8f8ba9 486 * @return 0 in case of success, negative error code otherwise
Janani Sunil 0:6ca37a8f8ba9 487 */
Janani Sunil 0:6ca37a8f8ba9 488 int32_t read_buffered_data(int8_t **pbuf, uint32_t nb_of_bytes)
Janani Sunil 0:6ca37a8f8ba9 489 {
Janani Sunil 0:6ca37a8f8ba9 490 int32_t ret;
Janani Sunil 0:6ca37a8f8ba9 491 num_of_requested_samples = nb_of_bytes / sample_size_in_bytes;
Janani Sunil 0:6ca37a8f8ba9 492
Janani Sunil 0:6ca37a8f8ba9 493 #if (DATA_CAPTURE_MODE == BURST_DATA_CAPTURE)
Janani Sunil 0:6ca37a8f8ba9 494 ret = read_burst_data(*pbuf, num_of_requested_samples);
Janani Sunil 0:6ca37a8f8ba9 495 #else
Janani Sunil 0:6ca37a8f8ba9 496 ret = read_continuous_conv_data(pbuf, num_of_requested_samples);
Janani Sunil 0:6ca37a8f8ba9 497 #endif
Janani Sunil 0:6ca37a8f8ba9 498 if (ret) {
Janani Sunil 0:6ca37a8f8ba9 499 return ret;
Janani Sunil 0:6ca37a8f8ba9 500 }
Janani Sunil 0:6ca37a8f8ba9 501
Janani Sunil 0:6ca37a8f8ba9 502 return 0;
Janani Sunil 0:6ca37a8f8ba9 503 }