Example Program for EVAL-AD7606
Dependencies: platform_drivers
app/ad7606_data_capture.c@1:819ac9aa5667, 2020-10-05 (annotated)
- Committer:
- mahphalke
- Date:
- Mon Oct 05 13:45:15 2020 +0530
- Revision:
- 1:819ac9aa5667
- Child:
- 3:83b3133f544a
AD7606 IIO Application- Initial Revision
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mahphalke |
1:819ac9aa5667 | 1 | /***************************************************************************//** |
mahphalke |
1:819ac9aa5667 | 2 | * @file ad7606_data_capture.c |
mahphalke |
1:819ac9aa5667 | 3 | * @brief Data capture interface for AD7606 IIO application |
mahphalke |
1:819ac9aa5667 | 4 | * @details This module handles the AD7606 data capturing |
mahphalke |
1:819ac9aa5667 | 5 | ******************************************************************************** |
mahphalke |
1:819ac9aa5667 | 6 | * Copyright (c) 2020 Analog Devices, Inc. |
mahphalke |
1:819ac9aa5667 | 7 | * |
mahphalke |
1:819ac9aa5667 | 8 | * All rights reserved. |
mahphalke |
1:819ac9aa5667 | 9 | * |
mahphalke |
1:819ac9aa5667 | 10 | * This software is proprietary to Analog Devices, Inc. and its licensors. |
mahphalke |
1:819ac9aa5667 | 11 | * By using this software you agree to the terms of the associated |
mahphalke |
1:819ac9aa5667 | 12 | * Analog Devices Software License Agreement. |
mahphalke |
1:819ac9aa5667 | 13 | *******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 14 | |
mahphalke |
1:819ac9aa5667 | 15 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 16 | /***************************** Include Files **********************************/ |
mahphalke |
1:819ac9aa5667 | 17 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 18 | |
mahphalke |
1:819ac9aa5667 | 19 | #include <string.h> |
mahphalke |
1:819ac9aa5667 | 20 | #include <stdlib.h> |
mahphalke |
1:819ac9aa5667 | 21 | |
mahphalke |
1:819ac9aa5667 | 22 | #include "app_config.h" |
mahphalke |
1:819ac9aa5667 | 23 | #include "ad7606_data_capture.h" |
mahphalke |
1:819ac9aa5667 | 24 | #include "ad7606_support.h" |
mahphalke |
1:819ac9aa5667 | 25 | #include "gpio_extra.h" |
mahphalke |
1:819ac9aa5667 | 26 | |
mahphalke |
1:819ac9aa5667 | 27 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 28 | /********************** Macros and Constants Definition ***********************/ |
mahphalke |
1:819ac9aa5667 | 29 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 30 | |
mahphalke |
1:819ac9aa5667 | 31 | #if (AD7606X_ADC_RESOLUTION > 16) |
mahphalke |
1:819ac9aa5667 | 32 | #define BYTES_PER_SAMPLE sizeof(uint32_t) |
mahphalke |
1:819ac9aa5667 | 33 | #else |
mahphalke |
1:819ac9aa5667 | 34 | #define BYTES_PER_SAMPLE sizeof(uint16_t) |
mahphalke |
1:819ac9aa5667 | 35 | #endif |
mahphalke |
1:819ac9aa5667 | 36 | |
mahphalke |
1:819ac9aa5667 | 37 | /* Max size of the acquisition buffer (in terms of samples) */ |
mahphalke |
1:819ac9aa5667 | 38 | #define DATA_BUFFER_SIZE (8192) |
mahphalke |
1:819ac9aa5667 | 39 | |
mahphalke |
1:819ac9aa5667 | 40 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 41 | /********************** Variables and User Defined Data Types *****************/ |
mahphalke |
1:819ac9aa5667 | 42 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 43 | |
mahphalke |
1:819ac9aa5667 | 44 | /* Device instance for background adc conversion callback */ |
mahphalke |
1:819ac9aa5667 | 45 | static volatile struct ad7606_dev *dev = NULL; |
mahphalke |
1:819ac9aa5667 | 46 | |
mahphalke |
1:819ac9aa5667 | 47 | /* |
mahphalke |
1:819ac9aa5667 | 48 | *@enum acq_buffer_state_e |
mahphalke |
1:819ac9aa5667 | 49 | *@details Enum holding the data acquisition buffer states |
mahphalke |
1:819ac9aa5667 | 50 | **/ |
mahphalke |
1:819ac9aa5667 | 51 | typedef enum { |
mahphalke |
1:819ac9aa5667 | 52 | BUF_EMPTY, |
mahphalke |
1:819ac9aa5667 | 53 | BUF_AVAILABLE, |
mahphalke |
1:819ac9aa5667 | 54 | BUF_FULL |
mahphalke |
1:819ac9aa5667 | 55 | } acq_buffer_state_e; |
mahphalke |
1:819ac9aa5667 | 56 | |
mahphalke |
1:819ac9aa5667 | 57 | /* |
mahphalke |
1:819ac9aa5667 | 58 | *@struct acq_buf_t |
mahphalke |
1:819ac9aa5667 | 59 | *@details Structure holding the data acquisition buffer parameters |
mahphalke |
1:819ac9aa5667 | 60 | **/ |
mahphalke |
1:819ac9aa5667 | 61 | typedef struct { |
mahphalke |
1:819ac9aa5667 | 62 | acq_buffer_state_e state; // buffer state |
mahphalke |
1:819ac9aa5667 | 63 | uint32_t rd_indx; // buffer read index |
mahphalke |
1:819ac9aa5667 | 64 | uint32_t wr_indx; // buffer write index |
mahphalke |
1:819ac9aa5667 | 65 | uint32_t align_cnt; // buffer alignment counter |
mahphalke |
1:819ac9aa5667 | 66 | #if (AD7606X_ADC_RESOLUTION > 16) |
mahphalke |
1:819ac9aa5667 | 67 | uint32_t data[DATA_BUFFER_SIZE]; |
mahphalke |
1:819ac9aa5667 | 68 | #else |
mahphalke |
1:819ac9aa5667 | 69 | uint16_t data[DATA_BUFFER_SIZE]; |
mahphalke |
1:819ac9aa5667 | 70 | #endif |
mahphalke |
1:819ac9aa5667 | 71 | } acq_buf_t; |
mahphalke |
1:819ac9aa5667 | 72 | |
mahphalke |
1:819ac9aa5667 | 73 | /* ADC data acquisition buffers */ |
mahphalke |
1:819ac9aa5667 | 74 | static volatile acq_buf_t acq_buffer; |
mahphalke |
1:819ac9aa5667 | 75 | |
mahphalke |
1:819ac9aa5667 | 76 | /* Flag to indicate background data capture status */ |
mahphalke |
1:819ac9aa5667 | 77 | static volatile bool start_adc_data_capture = false; |
mahphalke |
1:819ac9aa5667 | 78 | |
mahphalke |
1:819ac9aa5667 | 79 | /* Active channels to be captured */ |
mahphalke |
1:819ac9aa5667 | 80 | static volatile uint32_t active_channels = 0; |
mahphalke |
1:819ac9aa5667 | 81 | |
mahphalke |
1:819ac9aa5667 | 82 | /* Number of active channels */ |
mahphalke |
1:819ac9aa5667 | 83 | static uint8_t num_of_active_channels = 0; |
mahphalke |
1:819ac9aa5667 | 84 | |
mahphalke |
1:819ac9aa5667 | 85 | /* Minimum number of bytes to be read from device over digital interface */ |
mahphalke |
1:819ac9aa5667 | 86 | static volatile uint8_t min_bytes_to_read = 0; |
mahphalke |
1:819ac9aa5667 | 87 | |
mahphalke |
1:819ac9aa5667 | 88 | /* Number of channels requested for read into acquisition buffer */ |
mahphalke |
1:819ac9aa5667 | 89 | static volatile uint8_t chn_read_cnt = 0; |
mahphalke |
1:819ac9aa5667 | 90 | |
mahphalke |
1:819ac9aa5667 | 91 | /* Number of samples requested by IIO client */ |
mahphalke |
1:819ac9aa5667 | 92 | static uint16_t num_of_samples = 0; |
mahphalke |
1:819ac9aa5667 | 93 | |
mahphalke |
1:819ac9aa5667 | 94 | /* Max available size of buffer */ |
mahphalke |
1:819ac9aa5667 | 95 | static uint16_t max_available_buffer_size = 0; |
mahphalke |
1:819ac9aa5667 | 96 | |
mahphalke |
1:819ac9aa5667 | 97 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 98 | /************************ Functions Declarations ******************************/ |
mahphalke |
1:819ac9aa5667 | 99 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 100 | |
mahphalke |
1:819ac9aa5667 | 101 | static void adjust_buffer_offset(uint8_t *arr_indx, uint8_t *offset_end, |
mahphalke |
1:819ac9aa5667 | 102 | uint8_t *mask); |
mahphalke |
1:819ac9aa5667 | 103 | |
mahphalke |
1:819ac9aa5667 | 104 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 105 | /************************ Functions Definitions *******************************/ |
mahphalke |
1:819ac9aa5667 | 106 | /******************************************************************************/ |
mahphalke |
1:819ac9aa5667 | 107 | |
mahphalke |
1:819ac9aa5667 | 108 | /*! |
mahphalke |
1:819ac9aa5667 | 109 | * @brief Function to init the data capture for AD7606 device |
mahphalke |
1:819ac9aa5667 | 110 | * @param device[in]- Device instance |
mahphalke |
1:819ac9aa5667 | 111 | * @return none |
mahphalke |
1:819ac9aa5667 | 112 | */ |
mahphalke |
1:819ac9aa5667 | 113 | int32_t iio_data_capture_init(struct ad7606_dev *device) |
mahphalke |
1:819ac9aa5667 | 114 | { |
mahphalke |
1:819ac9aa5667 | 115 | /* Save the device structure for background conversion */ |
mahphalke |
1:819ac9aa5667 | 116 | dev = malloc(sizeof(struct ad7606_dev *)); |
mahphalke |
1:819ac9aa5667 | 117 | if (!dev) { |
mahphalke |
1:819ac9aa5667 | 118 | return FAILURE; |
mahphalke |
1:819ac9aa5667 | 119 | } |
mahphalke |
1:819ac9aa5667 | 120 | |
mahphalke |
1:819ac9aa5667 | 121 | memcpy(&dev, &device, sizeof(dev)); |
mahphalke |
1:819ac9aa5667 | 122 | |
mahphalke |
1:819ac9aa5667 | 123 | return SUCCESS; |
mahphalke |
1:819ac9aa5667 | 124 | } |
mahphalke |
1:819ac9aa5667 | 125 | |
mahphalke |
1:819ac9aa5667 | 126 | |
mahphalke |
1:819ac9aa5667 | 127 | /*! |
mahphalke |
1:819ac9aa5667 | 128 | * @brief Function to read the ADC raw data for single channel |
mahphalke |
1:819ac9aa5667 | 129 | * @param device[in]- Device instance |
mahphalke |
1:819ac9aa5667 | 130 | * @param chn[in] - Input channel |
mahphalke |
1:819ac9aa5667 | 131 | * @return adc raw data/sample |
mahphalke |
1:819ac9aa5667 | 132 | */ |
mahphalke |
1:819ac9aa5667 | 133 | int32_t single_data_read(void *device, uint8_t chn, polarity_e polarity) |
mahphalke |
1:819ac9aa5667 | 134 | { |
mahphalke |
1:819ac9aa5667 | 135 | int32_t adc_data = 0; |
mahphalke |
1:819ac9aa5667 | 136 | uint32_t adc_raw[AD7606X_ADC_RESOLUTION] = { 0 }; |
mahphalke |
1:819ac9aa5667 | 137 | |
mahphalke |
1:819ac9aa5667 | 138 | if (ad7606_read(device, adc_raw) != SUCCESS) { |
mahphalke |
1:819ac9aa5667 | 139 | adc_raw[chn] = 0; |
mahphalke |
1:819ac9aa5667 | 140 | } |
mahphalke |
1:819ac9aa5667 | 141 | |
mahphalke |
1:819ac9aa5667 | 142 | if (polarity == BIPOLAR) { |
mahphalke |
1:819ac9aa5667 | 143 | /* Check for negative adc value for bipolar inputs */ |
mahphalke |
1:819ac9aa5667 | 144 | if (adc_raw[chn] >= ADC_MAX_COUNT_BIPOLAR) { |
mahphalke |
1:819ac9aa5667 | 145 | /* Take the 2s complement for the negative counts (>full scale value) */ |
mahphalke |
1:819ac9aa5667 | 146 | adc_data = ADC_MAX_COUNT_UNIPOLAR - adc_raw[chn]; |
mahphalke |
1:819ac9aa5667 | 147 | adc_data = 0 - adc_data; |
mahphalke |
1:819ac9aa5667 | 148 | } else { |
mahphalke |
1:819ac9aa5667 | 149 | adc_data = adc_raw[chn]; |
mahphalke |
1:819ac9aa5667 | 150 | } |
mahphalke |
1:819ac9aa5667 | 151 | } else { |
mahphalke |
1:819ac9aa5667 | 152 | adc_data = adc_raw[chn]; |
mahphalke |
1:819ac9aa5667 | 153 | } |
mahphalke |
1:819ac9aa5667 | 154 | |
mahphalke |
1:819ac9aa5667 | 155 | return adc_data; |
mahphalke |
1:819ac9aa5667 | 156 | } |
mahphalke |
1:819ac9aa5667 | 157 | |
mahphalke |
1:819ac9aa5667 | 158 | |
mahphalke |
1:819ac9aa5667 | 159 | /*! |
mahphalke |
1:819ac9aa5667 | 160 | * @brief Function to store the number of requested samples from IIO client |
mahphalke |
1:819ac9aa5667 | 161 | * @param bytes[in] - Number of bytes corresponding to requested samples |
mahphalke |
1:819ac9aa5667 | 162 | * @return none |
mahphalke |
1:819ac9aa5667 | 163 | */ |
mahphalke |
1:819ac9aa5667 | 164 | void store_requested_samples_count(size_t bytes) |
mahphalke |
1:819ac9aa5667 | 165 | { |
mahphalke |
1:819ac9aa5667 | 166 | /* This gets the number of samples requested by IIO client for all active channels */ |
mahphalke |
1:819ac9aa5667 | 167 | num_of_samples = bytes / BYTES_PER_SAMPLE; |
mahphalke |
1:819ac9aa5667 | 168 | |
mahphalke |
1:819ac9aa5667 | 169 | /* Get the actual available size of buffer by aligning with number of requested samples. |
mahphalke |
1:819ac9aa5667 | 170 | * e.g. if requested samples are 1050, the max available size of buffer is: |
mahphalke |
1:819ac9aa5667 | 171 | * available size = (8192 / 1050) * 1050 = 7 * 1050 = 7350. |
mahphalke |
1:819ac9aa5667 | 172 | * The max samples to be requested should always be less than half the max size of buffer |
mahphalke |
1:819ac9aa5667 | 173 | * (in this case: 8192 / 2 = 4096). |
mahphalke |
1:819ac9aa5667 | 174 | * */ |
mahphalke |
1:819ac9aa5667 | 175 | max_available_buffer_size = ((DATA_BUFFER_SIZE / num_of_samples) * |
mahphalke |
1:819ac9aa5667 | 176 | num_of_samples); |
mahphalke |
1:819ac9aa5667 | 177 | } |
mahphalke |
1:819ac9aa5667 | 178 | |
mahphalke |
1:819ac9aa5667 | 179 | |
mahphalke |
1:819ac9aa5667 | 180 | /*! |
mahphalke |
1:819ac9aa5667 | 181 | * @brief Function to read new samples into buffer without timeout IIO request |
mahphalke |
1:819ac9aa5667 | 182 | * @param input_buffer[in] - Input data acquisition buffer |
mahphalke |
1:819ac9aa5667 | 183 | * @param output_buffer[in, out] - Output data buffer |
mahphalke |
1:819ac9aa5667 | 184 | * @param samples_to_read[in] - Number of samples to read |
mahphalke |
1:819ac9aa5667 | 185 | * @return none |
mahphalke |
1:819ac9aa5667 | 186 | */ |
mahphalke |
1:819ac9aa5667 | 187 | static void wait_and_read_new_samples(volatile acq_buf_t *input_buffer, |
mahphalke |
1:819ac9aa5667 | 188 | char *output_buffer, |
mahphalke |
1:819ac9aa5667 | 189 | size_t samples_to_read) |
mahphalke |
1:819ac9aa5667 | 190 | { |
mahphalke |
1:819ac9aa5667 | 191 | int32_t buff_rd_wr_indx_offset; // Offset b/w buffer read and write indexes |
mahphalke |
1:819ac9aa5667 | 192 | uint32_t timeout = 5000000; // To avoid IIO data request timeout |
mahphalke |
1:819ac9aa5667 | 193 | size_t bytes = samples_to_read * BYTES_PER_SAMPLE; |
mahphalke |
1:819ac9aa5667 | 194 | |
mahphalke |
1:819ac9aa5667 | 195 | /* Copy the bytes into buffer provided there is enough offset b/w read and write counts. |
mahphalke |
1:819ac9aa5667 | 196 | * If there is overlap b/w read and write indexes (read is faster than write), empty buffer |
mahphalke |
1:819ac9aa5667 | 197 | * should be returned to IIO client to avoid IIO request timeout */ |
mahphalke |
1:819ac9aa5667 | 198 | do { |
mahphalke |
1:819ac9aa5667 | 199 | buff_rd_wr_indx_offset = (int32_t)input_buffer->wr_indx - |
mahphalke |
1:819ac9aa5667 | 200 | (int32_t)input_buffer->rd_indx; |
mahphalke |
1:819ac9aa5667 | 201 | timeout--; |
mahphalke |
1:819ac9aa5667 | 202 | } while (((buff_rd_wr_indx_offset < (int32_t)(samples_to_read)) |
mahphalke |
1:819ac9aa5667 | 203 | || (input_buffer->wr_indx < input_buffer->rd_indx)) && (timeout > 0)); |
mahphalke |
1:819ac9aa5667 | 204 | |
mahphalke |
1:819ac9aa5667 | 205 | if ((timeout == 0) || (input_buffer->wr_indx <= 0)) { |
mahphalke |
1:819ac9aa5667 | 206 | /* This returns the empty buffer */ |
mahphalke |
1:819ac9aa5667 | 207 | return; |
mahphalke |
1:819ac9aa5667 | 208 | } |
mahphalke |
1:819ac9aa5667 | 209 | |
mahphalke |
1:819ac9aa5667 | 210 | memcpy(output_buffer, |
mahphalke |
1:819ac9aa5667 | 211 | (void const *)&input_buffer->data[input_buffer->rd_indx], |
mahphalke |
1:819ac9aa5667 | 212 | bytes); |
mahphalke |
1:819ac9aa5667 | 213 | input_buffer->rd_indx += samples_to_read; |
mahphalke |
1:819ac9aa5667 | 214 | } |
mahphalke |
1:819ac9aa5667 | 215 | |
mahphalke |
1:819ac9aa5667 | 216 | |
mahphalke |
1:819ac9aa5667 | 217 | /*! |
mahphalke |
1:819ac9aa5667 | 218 | * @brief Function to read and align the ADC buffered raw data |
mahphalke |
1:819ac9aa5667 | 219 | * @param device[in]- Device instance |
mahphalke |
1:819ac9aa5667 | 220 | * @param pbuf[out] - Buffer to load ADC raw data |
mahphalke |
1:819ac9aa5667 | 221 | * @param bytes[in] - Number of bytes to be read |
mahphalke |
1:819ac9aa5667 | 222 | * @param active_chns_mask[in] - Active channels mask |
mahphalke |
1:819ac9aa5667 | 223 | * @return Number of bytes read |
mahphalke |
1:819ac9aa5667 | 224 | */ |
mahphalke |
1:819ac9aa5667 | 225 | size_t buffered_data_read(char *pbuf, size_t bytes, size_t offset, |
mahphalke |
1:819ac9aa5667 | 226 | uint32_t active_chns_mask) |
mahphalke |
1:819ac9aa5667 | 227 | { |
mahphalke |
1:819ac9aa5667 | 228 | size_t samples_to_read = bytes / BYTES_PER_SAMPLE; // Bytes to sample conversion |
mahphalke |
1:819ac9aa5667 | 229 | |
mahphalke |
1:819ac9aa5667 | 230 | /* Make sure requested samples size is less than ADC buffer size. Return constant |
mahphalke |
1:819ac9aa5667 | 231 | * value to avoid IIO client getting timed-out */ |
mahphalke |
1:819ac9aa5667 | 232 | if (num_of_samples >= max_available_buffer_size) { |
mahphalke |
1:819ac9aa5667 | 233 | memset(pbuf, 1, bytes); |
mahphalke |
1:819ac9aa5667 | 234 | return bytes; |
mahphalke |
1:819ac9aa5667 | 235 | } |
mahphalke |
1:819ac9aa5667 | 236 | |
mahphalke |
1:819ac9aa5667 | 237 | wait_and_read_new_samples(&acq_buffer, pbuf, samples_to_read); |
mahphalke |
1:819ac9aa5667 | 238 | |
mahphalke |
1:819ac9aa5667 | 239 | /* Make buffer available again once read completely */ |
mahphalke |
1:819ac9aa5667 | 240 | if (acq_buffer.rd_indx >= max_available_buffer_size) { |
mahphalke |
1:819ac9aa5667 | 241 | acq_buffer.rd_indx = 0; |
mahphalke |
1:819ac9aa5667 | 242 | acq_buffer.wr_indx = 0; |
mahphalke |
1:819ac9aa5667 | 243 | acq_buffer.align_cnt = 0; |
mahphalke |
1:819ac9aa5667 | 244 | acq_buffer.state = BUF_AVAILABLE; |
mahphalke |
1:819ac9aa5667 | 245 | } |
mahphalke |
1:819ac9aa5667 | 246 | |
mahphalke |
1:819ac9aa5667 | 247 | return bytes; |
mahphalke |
1:819ac9aa5667 | 248 | } |
mahphalke |
1:819ac9aa5667 | 249 | |
mahphalke |
1:819ac9aa5667 | 250 | |
mahphalke |
1:819ac9aa5667 | 251 | /*! |
mahphalke |
1:819ac9aa5667 | 252 | * @brief Function to perform background ADC conversion and data capture |
mahphalke |
1:819ac9aa5667 | 253 | * @return none |
mahphalke |
1:819ac9aa5667 | 254 | * @details This is an External Interrupt callback function/ISR, which is tied up to |
mahphalke |
1:819ac9aa5667 | 255 | * falling edge trigger of BUSY pin. It is trigered when previous data |
mahphalke |
1:819ac9aa5667 | 256 | * conversion is over and BUSY line goes low. Upon trigger, conversion |
mahphalke |
1:819ac9aa5667 | 257 | * results are read into acquisition buffer and next conversion is triggered. |
mahphalke |
1:819ac9aa5667 | 258 | * This continues until background conversion is stopped. |
mahphalke |
1:819ac9aa5667 | 259 | */ |
mahphalke |
1:819ac9aa5667 | 260 | void do_conversion_callback(void) |
mahphalke |
1:819ac9aa5667 | 261 | { |
mahphalke |
1:819ac9aa5667 | 262 | #if (AD7606X_ADC_RESOLUTION == 18) |
mahphalke |
1:819ac9aa5667 | 263 | uint8_t arr_indx = 0; |
mahphalke |
1:819ac9aa5667 | 264 | uint8_t offset_end = 2; |
mahphalke |
1:819ac9aa5667 | 265 | uint8_t mask = 0xff; |
mahphalke |
1:819ac9aa5667 | 266 | #else |
mahphalke |
1:819ac9aa5667 | 267 | uint8_t mask = 0x01; |
mahphalke |
1:819ac9aa5667 | 268 | #endif |
mahphalke |
1:819ac9aa5667 | 269 | |
mahphalke |
1:819ac9aa5667 | 270 | if (start_adc_data_capture == true) { |
mahphalke |
1:819ac9aa5667 | 271 | |
mahphalke |
1:819ac9aa5667 | 272 | /* Read the conversion result for required number of bytes */ |
mahphalke |
1:819ac9aa5667 | 273 | if (ad7606_read_conversion_data(dev, min_bytes_to_read) == SUCCESS) { |
mahphalke |
1:819ac9aa5667 | 274 | |
mahphalke |
1:819ac9aa5667 | 275 | /* Extract the data based on the active channels selected in IIO client. |
mahphalke |
1:819ac9aa5667 | 276 | * Note: The extraction of data based on active channel needs |
mahphalke |
1:819ac9aa5667 | 277 | * to be done since its not possible to capture individual |
mahphalke |
1:819ac9aa5667 | 278 | * channel in AD7606 devices */ |
mahphalke |
1:819ac9aa5667 | 279 | for (uint8_t chn = 0; chn < chn_read_cnt; chn++) { |
mahphalke |
1:819ac9aa5667 | 280 | if (active_channels & mask) { |
mahphalke |
1:819ac9aa5667 | 281 | if (acq_buffer.state == BUF_AVAILABLE) { |
mahphalke |
1:819ac9aa5667 | 282 | #if (AD7606X_ADC_RESOLUTION == 18) |
mahphalke |
1:819ac9aa5667 | 283 | /* For AD7606C device (18-bit resolution) */ |
mahphalke |
1:819ac9aa5667 | 284 | acq_buffer.data[acq_buffer.wr_indx++] = |
mahphalke |
1:819ac9aa5667 | 285 | (((uint32_t)(dev->data[arr_indx] & mask) << 16) | // MSB |
mahphalke |
1:819ac9aa5667 | 286 | ((uint32_t)dev->data[arr_indx + 1] << 8) | |
mahphalke |
1:819ac9aa5667 | 287 | ((uint32_t)(dev->data[arr_indx + 2] >> (8 - offset_end)))); // LSB |
mahphalke |
1:819ac9aa5667 | 288 | #else |
mahphalke |
1:819ac9aa5667 | 289 | |
mahphalke |
1:819ac9aa5667 | 290 | acq_buffer.data[acq_buffer.wr_indx++] = |
mahphalke |
1:819ac9aa5667 | 291 | (uint16_t)(((uint16_t)dev->data[chn << 1] << 8) | // MSB |
mahphalke |
1:819ac9aa5667 | 292 | dev->data[(chn << 1) + 1]); // LSB |
mahphalke |
1:819ac9aa5667 | 293 | #endif |
mahphalke |
1:819ac9aa5667 | 294 | |
mahphalke |
1:819ac9aa5667 | 295 | acq_buffer.align_cnt++; |
mahphalke |
1:819ac9aa5667 | 296 | |
mahphalke |
1:819ac9aa5667 | 297 | /* Monitor primary buffer full state */ |
mahphalke |
1:819ac9aa5667 | 298 | if (acq_buffer.wr_indx >= max_available_buffer_size) { |
mahphalke |
1:819ac9aa5667 | 299 | acq_buffer.state = BUF_FULL; |
mahphalke |
1:819ac9aa5667 | 300 | |
mahphalke |
1:819ac9aa5667 | 301 | /* This aligns the buffer to first active channel once all requested samples are transmitted */ |
mahphalke |
1:819ac9aa5667 | 302 | if (acq_buffer.align_cnt >= num_of_samples) { |
mahphalke |
1:819ac9aa5667 | 303 | acq_buffer.align_cnt = 0; |
mahphalke |
1:819ac9aa5667 | 304 | } |
mahphalke |
1:819ac9aa5667 | 305 | #if (AD7606X_ADC_RESOLUTION == 18) |
mahphalke |
1:819ac9aa5667 | 306 | adjust_buffer_offset(&arr_indx, &offset_end, &mask); |
mahphalke |
1:819ac9aa5667 | 307 | #endif |
mahphalke |
1:819ac9aa5667 | 308 | mask <<= 1; |
mahphalke |
1:819ac9aa5667 | 309 | continue; |
mahphalke |
1:819ac9aa5667 | 310 | } |
mahphalke |
1:819ac9aa5667 | 311 | |
mahphalke |
1:819ac9aa5667 | 312 | /* This aligns the buffer to first active channel once all requested samples are transmitted */ |
mahphalke |
1:819ac9aa5667 | 313 | if (acq_buffer.align_cnt >= num_of_samples) { |
mahphalke |
1:819ac9aa5667 | 314 | acq_buffer.align_cnt = 0; |
mahphalke |
1:819ac9aa5667 | 315 | break; |
mahphalke |
1:819ac9aa5667 | 316 | } |
mahphalke |
1:819ac9aa5667 | 317 | } |
mahphalke |
1:819ac9aa5667 | 318 | } |
mahphalke |
1:819ac9aa5667 | 319 | |
mahphalke |
1:819ac9aa5667 | 320 | #if (AD7606X_ADC_RESOLUTION == 18) |
mahphalke |
1:819ac9aa5667 | 321 | adjust_buffer_offset(&arr_indx, &offset_end, &mask); |
mahphalke |
1:819ac9aa5667 | 322 | #endif |
mahphalke |
1:819ac9aa5667 | 323 | |
mahphalke |
1:819ac9aa5667 | 324 | mask <<= 1; |
mahphalke |
1:819ac9aa5667 | 325 | } |
mahphalke |
1:819ac9aa5667 | 326 | |
mahphalke |
1:819ac9aa5667 | 327 | /* Trigger next conversion */ |
mahphalke |
1:819ac9aa5667 | 328 | if (ad7606_convst(dev) != SUCCESS) { |
mahphalke |
1:819ac9aa5667 | 329 | start_adc_data_capture = false; |
mahphalke |
1:819ac9aa5667 | 330 | } |
mahphalke |
1:819ac9aa5667 | 331 | } else { |
mahphalke |
1:819ac9aa5667 | 332 | start_adc_data_capture = false; |
mahphalke |
1:819ac9aa5667 | 333 | } |
mahphalke |
1:819ac9aa5667 | 334 | } |
mahphalke |
1:819ac9aa5667 | 335 | } |
mahphalke |
1:819ac9aa5667 | 336 | |
mahphalke |
1:819ac9aa5667 | 337 | |
mahphalke |
1:819ac9aa5667 | 338 | /*! |
mahphalke |
1:819ac9aa5667 | 339 | * @brief Function to trigger bakground ADC conversion for new READBUFF |
mahphalke |
1:819ac9aa5667 | 340 | * request from IIO client (for active channels) |
mahphalke |
1:819ac9aa5667 | 341 | * @return Conversion start status |
mahphalke |
1:819ac9aa5667 | 342 | */ |
mahphalke |
1:819ac9aa5667 | 343 | void start_background_data_capture(uint32_t ch_mask, size_t bytes_count) |
mahphalke |
1:819ac9aa5667 | 344 | { |
mahphalke |
1:819ac9aa5667 | 345 | uint8_t mask = 0x1; |
mahphalke |
1:819ac9aa5667 | 346 | |
mahphalke |
1:819ac9aa5667 | 347 | /* Make sure requested samples size is less than ADC buffer size */ |
mahphalke |
1:819ac9aa5667 | 348 | if (num_of_samples >= max_available_buffer_size) |
mahphalke |
1:819ac9aa5667 | 349 | return; |
mahphalke |
1:819ac9aa5667 | 350 | |
mahphalke |
1:819ac9aa5667 | 351 | active_channels = ch_mask; |
mahphalke |
1:819ac9aa5667 | 352 | |
mahphalke |
1:819ac9aa5667 | 353 | stop_background_data_capture(); |
mahphalke |
1:819ac9aa5667 | 354 | |
mahphalke |
1:819ac9aa5667 | 355 | /* Find the minimum number of bytes to be read from device during |
mahphalke |
1:819ac9aa5667 | 356 | * background conversion (Reading all bytes/channels adds extra overhead, |
mahphalke |
1:819ac9aa5667 | 357 | * so restrict the minimum reads to whatever is possible). |
mahphalke |
1:819ac9aa5667 | 358 | * Note: This happens only at the start of buffer read request. */ |
mahphalke |
1:819ac9aa5667 | 359 | for (uint8_t chn = 1, indx = 0; chn <= AD7606X_ADC_CHANNELS; chn++, indx++) { |
mahphalke |
1:819ac9aa5667 | 360 | if (ch_mask & mask) { |
mahphalke |
1:819ac9aa5667 | 361 | /* 1 sample = 2 or 4 bytes */ |
mahphalke |
1:819ac9aa5667 | 362 | min_bytes_to_read = chn * BYTES_PER_SAMPLE; |
mahphalke |
1:819ac9aa5667 | 363 | if (min_bytes_to_read > AD7606X_ADC_RESOLUTION) { |
mahphalke |
1:819ac9aa5667 | 364 | min_bytes_to_read = AD7606X_ADC_RESOLUTION; |
mahphalke |
1:819ac9aa5667 | 365 | } |
mahphalke |
1:819ac9aa5667 | 366 | |
mahphalke |
1:819ac9aa5667 | 367 | /* Get the count for number of samples to be stored into acquisition buffer */ |
mahphalke |
1:819ac9aa5667 | 368 | chn_read_cnt = chn; |
mahphalke |
1:819ac9aa5667 | 369 | num_of_active_channels++; |
mahphalke |
1:819ac9aa5667 | 370 | } |
mahphalke |
1:819ac9aa5667 | 371 | |
mahphalke |
1:819ac9aa5667 | 372 | mask <<= 1; |
mahphalke |
1:819ac9aa5667 | 373 | } |
mahphalke |
1:819ac9aa5667 | 374 | |
mahphalke |
1:819ac9aa5667 | 375 | /* Make primary acquisition buffer available and start conversion */ |
mahphalke |
1:819ac9aa5667 | 376 | acq_buffer.state = BUF_AVAILABLE; |
mahphalke |
1:819ac9aa5667 | 377 | if (ad7606_convst(dev) == SUCCESS) { |
mahphalke |
1:819ac9aa5667 | 378 | start_adc_data_capture = true; |
mahphalke |
1:819ac9aa5667 | 379 | } else { |
mahphalke |
1:819ac9aa5667 | 380 | start_adc_data_capture = false; |
mahphalke |
1:819ac9aa5667 | 381 | } |
mahphalke |
1:819ac9aa5667 | 382 | } |
mahphalke |
1:819ac9aa5667 | 383 | |
mahphalke |
1:819ac9aa5667 | 384 | |
mahphalke |
1:819ac9aa5667 | 385 | /*! |
mahphalke |
1:819ac9aa5667 | 386 | * @brief Function to stop background ADC data capture |
mahphalke |
1:819ac9aa5667 | 387 | * @return none |
mahphalke |
1:819ac9aa5667 | 388 | */ |
mahphalke |
1:819ac9aa5667 | 389 | void stop_background_data_capture(void) |
mahphalke |
1:819ac9aa5667 | 390 | { |
mahphalke |
1:819ac9aa5667 | 391 | /* Reset data capture flags */ |
mahphalke |
1:819ac9aa5667 | 392 | start_adc_data_capture = false; |
mahphalke |
1:819ac9aa5667 | 393 | num_of_active_channels = 0; |
mahphalke |
1:819ac9aa5667 | 394 | min_bytes_to_read = 0; |
mahphalke |
1:819ac9aa5667 | 395 | chn_read_cnt = 0; |
mahphalke |
1:819ac9aa5667 | 396 | |
mahphalke |
1:819ac9aa5667 | 397 | /* Reset acquisition buffer states and clear old data */ |
mahphalke |
1:819ac9aa5667 | 398 | acq_buffer.state = BUF_EMPTY; |
mahphalke |
1:819ac9aa5667 | 399 | |
mahphalke |
1:819ac9aa5667 | 400 | memset((void *)acq_buffer.data, 0, sizeof(acq_buffer.data)); |
mahphalke |
1:819ac9aa5667 | 401 | |
mahphalke |
1:819ac9aa5667 | 402 | acq_buffer.wr_indx = 0; |
mahphalke |
1:819ac9aa5667 | 403 | acq_buffer.rd_indx = 0; |
mahphalke |
1:819ac9aa5667 | 404 | acq_buffer.align_cnt = 0; |
mahphalke |
1:819ac9aa5667 | 405 | } |
mahphalke |
1:819ac9aa5667 | 406 | |
mahphalke |
1:819ac9aa5667 | 407 | |
mahphalke |
1:819ac9aa5667 | 408 | /*! |
mahphalke |
1:819ac9aa5667 | 409 | * @brief Function to adjust the data buffer offset |
mahphalke |
1:819ac9aa5667 | 410 | * @param *arr_indx[in, out]- Array index |
mahphalke |
1:819ac9aa5667 | 411 | * @param *offset_end[out] - offset to extract LSB from 18-bit data |
mahphalke |
1:819ac9aa5667 | 412 | * @param *mask[out] - channel select mask |
mahphalke |
1:819ac9aa5667 | 413 | * @return none |
mahphalke |
1:819ac9aa5667 | 414 | */ |
mahphalke |
1:819ac9aa5667 | 415 | static void adjust_buffer_offset(uint8_t *arr_indx, uint8_t *offset_end, |
mahphalke |
1:819ac9aa5667 | 416 | uint8_t *mask) |
mahphalke |
1:819ac9aa5667 | 417 | { |
mahphalke |
1:819ac9aa5667 | 418 | *arr_indx += 2; |
mahphalke |
1:819ac9aa5667 | 419 | |
mahphalke |
1:819ac9aa5667 | 420 | /* Track array to reach at the middle (9 bytes apart) to change the offsets */ |
mahphalke |
1:819ac9aa5667 | 421 | if (*arr_indx == ((AD7606X_ADC_RESOLUTION / 2) - 1)) { |
mahphalke |
1:819ac9aa5667 | 422 | (*arr_indx)++; |
mahphalke |
1:819ac9aa5667 | 423 | *offset_end = 2; |
mahphalke |
1:819ac9aa5667 | 424 | *mask = 0xff; |
mahphalke |
1:819ac9aa5667 | 425 | } else { |
mahphalke |
1:819ac9aa5667 | 426 | *mask = (0xff >> *offset_end); |
mahphalke |
1:819ac9aa5667 | 427 | *offset_end += 2; |
mahphalke |
1:819ac9aa5667 | 428 | } |
mahphalke |
1:819ac9aa5667 | 429 | } |