Forked repo of Platform Drivers- Analog Devices
adc_data_capture.c@18:5ae03a197e59, 2021-08-02 (annotated)
- Committer:
- mahphalke
- Date:
- Mon Aug 02 16:03:08 2021 +0530
- Revision:
- 18:5ae03a197e59
- Parent:
- 17:af1f2416dd26
Modified the ADC data capture module to remove dependancy on type of ADC and it's specific operations
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mahphalke |
17:af1f2416dd26 | 1 | /***************************************************************************//** |
mahphalke |
17:af1f2416dd26 | 2 | * @file adc_data_capture.c |
mahphalke |
17:af1f2416dd26 | 3 | * @brief ADC common data capture interface for IIO based applications |
mahphalke |
17:af1f2416dd26 | 4 | * @details This module handles the ADC data capturing for IIO client |
mahphalke |
17:af1f2416dd26 | 5 | ******************************************************************************** |
mahphalke |
17:af1f2416dd26 | 6 | * Copyright (c) 2021 Analog Devices, Inc. |
mahphalke |
17:af1f2416dd26 | 7 | * All rights reserved. |
mahphalke |
17:af1f2416dd26 | 8 | * |
mahphalke |
17:af1f2416dd26 | 9 | * This software is proprietary to Analog Devices, Inc. and its licensors. |
mahphalke |
17:af1f2416dd26 | 10 | * By using this software you agree to the terms of the associated |
mahphalke |
17:af1f2416dd26 | 11 | * Analog Devices Software License Agreement. |
mahphalke |
17:af1f2416dd26 | 12 | *******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 13 | |
mahphalke |
17:af1f2416dd26 | 14 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 15 | /***************************** Include Files **********************************/ |
mahphalke |
17:af1f2416dd26 | 16 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 17 | |
mahphalke |
17:af1f2416dd26 | 18 | #include <stdint.h> |
mahphalke |
17:af1f2416dd26 | 19 | #include <stdbool.h> |
mahphalke |
17:af1f2416dd26 | 20 | #include <string.h> |
mahphalke |
17:af1f2416dd26 | 21 | |
mahphalke |
17:af1f2416dd26 | 22 | #include "adc_data_capture.h" |
mahphalke |
17:af1f2416dd26 | 23 | #include "error.h" |
mahphalke |
17:af1f2416dd26 | 24 | |
mahphalke |
17:af1f2416dd26 | 25 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 26 | /********************** Macros and Constants Definition ***********************/ |
mahphalke |
17:af1f2416dd26 | 27 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 28 | |
mahphalke |
18:5ae03a197e59 | 29 | /* Max available channels for continuous data capture. Actual number of channels |
mahphalke |
18:5ae03a197e59 | 30 | * to be captured are supplied from an application */ |
mahphalke |
18:5ae03a197e59 | 31 | #define MAX_AVAILABLE_CHANNELS (16) |
mahphalke |
17:af1f2416dd26 | 32 | |
mahphalke |
18:5ae03a197e59 | 33 | /* Max size of the acquisition buffer (in terms of bytes) */ |
mahphalke |
18:5ae03a197e59 | 34 | #define DATA_BUFFER_SIZE (32768) // 32Kbytes |
mahphalke |
17:af1f2416dd26 | 35 | |
mahphalke |
17:af1f2416dd26 | 36 | /* Timeout count to avoid stuck into potential infinite loop while checking |
mahphalke |
17:af1f2416dd26 | 37 | * for new data into an acquisition buffer. The actual timeout factor is determined |
mahphalke |
18:5ae03a197e59 | 38 | * through 'sampling_frequency' attribute of IIO app, but this period here makes sure |
mahphalke |
18:5ae03a197e59 | 39 | * we are not stuck into a forever loop in case data capture is interrupted |
mahphalke |
18:5ae03a197e59 | 40 | * or failed in between. |
mahphalke |
18:5ae03a197e59 | 41 | * Note: This timeout factor is dependent upon the MCU clock frequency. Below timeout |
mahphalke |
18:5ae03a197e59 | 42 | * is tested for SDP-K1 platform @180Mhz default core clock */ |
mahphalke |
17:af1f2416dd26 | 43 | #define BUF_READ_TIMEOUT (100000000) |
mahphalke |
17:af1f2416dd26 | 44 | |
mahphalke |
17:af1f2416dd26 | 45 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 46 | /********************** Variables and User Defined Data Types *****************/ |
mahphalke |
17:af1f2416dd26 | 47 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 48 | |
mahphalke |
18:5ae03a197e59 | 49 | /* Extern declaration for device specific data capture operations structure |
mahphalke |
18:5ae03a197e59 | 50 | * (actual definition should be present in an application) */ |
mahphalke |
17:af1f2416dd26 | 51 | extern struct data_capture_ops data_capture_ops; |
mahphalke |
17:af1f2416dd26 | 52 | |
mahphalke |
17:af1f2416dd26 | 53 | /* |
mahphalke |
17:af1f2416dd26 | 54 | *@enum acq_buffer_state_e |
mahphalke |
17:af1f2416dd26 | 55 | *@details Enum holding the data acquisition buffer states |
mahphalke |
17:af1f2416dd26 | 56 | **/ |
mahphalke |
17:af1f2416dd26 | 57 | typedef enum { |
mahphalke |
17:af1f2416dd26 | 58 | BUF_AVAILABLE, |
mahphalke |
17:af1f2416dd26 | 59 | BUF_EMPTY, |
mahphalke |
17:af1f2416dd26 | 60 | BUF_FULL |
mahphalke |
17:af1f2416dd26 | 61 | } acq_buffer_state_e; |
mahphalke |
17:af1f2416dd26 | 62 | |
mahphalke |
17:af1f2416dd26 | 63 | /* |
mahphalke |
17:af1f2416dd26 | 64 | *@struct acq_buf_t |
mahphalke |
17:af1f2416dd26 | 65 | *@details Structure holding the data acquisition buffer parameters |
mahphalke |
17:af1f2416dd26 | 66 | **/ |
mahphalke |
17:af1f2416dd26 | 67 | typedef struct { |
mahphalke |
18:5ae03a197e59 | 68 | acq_buffer_state_e state; // Buffer state |
mahphalke |
18:5ae03a197e59 | 69 | bool refill_buffer; // Flag to start refilling acquisition buffer |
mahphalke |
18:5ae03a197e59 | 70 | uint32_t rd_indx; // Buffer read index (incremented per sample transmit) |
mahphalke |
18:5ae03a197e59 | 71 | uint32_t wr_indx; // Buffer write index (incremented per sample read) |
mahphalke |
18:5ae03a197e59 | 72 | uint8_t sample_size; // ADC sample/raw data size received from application |
mahphalke |
18:5ae03a197e59 | 73 | uint8_t chn_indx; // ADC channel index into acquisition buffer |
mahphalke |
18:5ae03a197e59 | 74 | uint8_t active_chn[MAX_AVAILABLE_CHANNELS]; // Active channel number sequence |
mahphalke |
18:5ae03a197e59 | 75 | uint8_t data[DATA_BUFFER_SIZE]; // buffer data (adc raw values) |
mahphalke |
18:5ae03a197e59 | 76 | uint8_t *pdata; // Pointer to data buffer |
mahphalke |
17:af1f2416dd26 | 77 | } acq_buf_t; |
mahphalke |
17:af1f2416dd26 | 78 | |
mahphalke |
17:af1f2416dd26 | 79 | /* ADC data acquisition buffers */ |
mahphalke |
17:af1f2416dd26 | 80 | static volatile acq_buf_t acq_buffer; |
mahphalke |
17:af1f2416dd26 | 81 | |
mahphalke |
17:af1f2416dd26 | 82 | /* Flag to indicate data capture status */ |
mahphalke |
17:af1f2416dd26 | 83 | static volatile bool start_adc_data_capture = false; |
mahphalke |
17:af1f2416dd26 | 84 | |
mahphalke |
17:af1f2416dd26 | 85 | /* Number of active channels in any data buffer read request */ |
mahphalke |
17:af1f2416dd26 | 86 | static volatile uint8_t num_of_active_channels = 0; |
mahphalke |
17:af1f2416dd26 | 87 | |
mahphalke |
17:af1f2416dd26 | 88 | /* Count to track number of actual samples requested by IIO client */ |
mahphalke |
17:af1f2416dd26 | 89 | static volatile uint16_t num_of_requested_samples = 0; |
mahphalke |
17:af1f2416dd26 | 90 | |
mahphalke |
18:5ae03a197e59 | 91 | /* Channel alignment offset */ |
mahphalke |
18:5ae03a197e59 | 92 | static volatile uint8_t chn_alignment_offset = 0; |
mahphalke |
18:5ae03a197e59 | 93 | |
mahphalke |
17:af1f2416dd26 | 94 | /* Actual or max available size of acquisition buffer */ |
mahphalke |
17:af1f2416dd26 | 95 | static volatile uint16_t max_available_buffer_size = 0; |
mahphalke |
17:af1f2416dd26 | 96 | |
mahphalke |
17:af1f2416dd26 | 97 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 98 | /************************ Functions Declarations ******************************/ |
mahphalke |
17:af1f2416dd26 | 99 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 100 | |
mahphalke |
17:af1f2416dd26 | 101 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 102 | /************************ Functions Definitions *******************************/ |
mahphalke |
17:af1f2416dd26 | 103 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 104 | |
mahphalke |
17:af1f2416dd26 | 105 | /*! |
mahphalke |
18:5ae03a197e59 | 106 | * @brief Function to read the single ADC sample (raw data) for input channel |
mahphalke |
17:af1f2416dd26 | 107 | * @param input_chn[in] - Input channel to sample and read data for |
mahphalke |
17:af1f2416dd26 | 108 | * @param raw_data[in, out]- ADC raw data |
mahphalke |
17:af1f2416dd26 | 109 | * @return SUCCESS in case of success, FAILURE otherwise |
mahphalke |
17:af1f2416dd26 | 110 | */ |
mahphalke |
18:5ae03a197e59 | 111 | int32_t read_single_sample(uint8_t input_chn, uint32_t *raw_data) |
mahphalke |
17:af1f2416dd26 | 112 | { |
mahphalke |
17:af1f2416dd26 | 113 | uint32_t read_adc_data = 0; |
mahphalke |
17:af1f2416dd26 | 114 | int32_t status = SUCCESS; |
mahphalke |
17:af1f2416dd26 | 115 | |
mahphalke |
17:af1f2416dd26 | 116 | do { |
mahphalke |
18:5ae03a197e59 | 117 | /* Perform operations required before single sample conversion read */ |
mahphalke |
18:5ae03a197e59 | 118 | if (data_capture_ops.single_sample_read_start_ops) { |
mahphalke |
18:5ae03a197e59 | 119 | if (data_capture_ops.single_sample_read_start_ops(input_chn) != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 120 | status = FAILURE; |
mahphalke |
17:af1f2416dd26 | 121 | break; |
mahphalke |
17:af1f2416dd26 | 122 | } |
mahphalke |
17:af1f2416dd26 | 123 | } |
mahphalke |
17:af1f2416dd26 | 124 | |
mahphalke |
18:5ae03a197e59 | 125 | /* Perform ADC conversion and read the converted sample after EOC */ |
mahphalke |
18:5ae03a197e59 | 126 | if (data_capture_ops.perform_conv_and_read_sample(&read_adc_data, input_chn) != |
mahphalke |
17:af1f2416dd26 | 127 | SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 128 | status = FAILURE; |
mahphalke |
17:af1f2416dd26 | 129 | break; |
mahphalke |
17:af1f2416dd26 | 130 | } |
mahphalke |
17:af1f2416dd26 | 131 | } while (0); |
mahphalke |
17:af1f2416dd26 | 132 | |
mahphalke |
18:5ae03a197e59 | 133 | /* Perform operations required post single sample conversion read */ |
mahphalke |
18:5ae03a197e59 | 134 | if (data_capture_ops.single_sample_read_stop_ops) { |
mahphalke |
18:5ae03a197e59 | 135 | if (data_capture_ops.single_sample_read_stop_ops(input_chn) != SUCCESS) { |
mahphalke |
18:5ae03a197e59 | 136 | status = FAILURE; |
mahphalke |
18:5ae03a197e59 | 137 | } |
mahphalke |
17:af1f2416dd26 | 138 | } |
mahphalke |
17:af1f2416dd26 | 139 | |
mahphalke |
17:af1f2416dd26 | 140 | *raw_data = read_adc_data; |
mahphalke |
17:af1f2416dd26 | 141 | return status; |
mahphalke |
17:af1f2416dd26 | 142 | } |
mahphalke |
17:af1f2416dd26 | 143 | |
mahphalke |
17:af1f2416dd26 | 144 | |
mahphalke |
17:af1f2416dd26 | 145 | /*! |
mahphalke |
18:5ae03a197e59 | 146 | * @brief Function to store the number of actul requested ADC samples from IIO client |
mahphalke |
17:af1f2416dd26 | 147 | * @param bytes[in] - Number of bytes corresponding to requested samples |
mahphalke |
17:af1f2416dd26 | 148 | * @param sample_size_in_bytes[in] - Size of each sample in bytes (eqv to ADC resolution) |
mahphalke |
17:af1f2416dd26 | 149 | * @return none |
mahphalke |
18:5ae03a197e59 | 150 | * @note The information about sample and buffer size is required for continuous |
mahphalke |
18:5ae03a197e59 | 151 | * data acquisition |
mahphalke |
17:af1f2416dd26 | 152 | */ |
mahphalke |
17:af1f2416dd26 | 153 | void store_requested_samples_count(size_t bytes, uint8_t sample_size_in_bytes) |
mahphalke |
17:af1f2416dd26 | 154 | { |
mahphalke |
17:af1f2416dd26 | 155 | /* This gets the number of samples requested by IIO client for all active channels */ |
mahphalke |
17:af1f2416dd26 | 156 | num_of_requested_samples = bytes / sample_size_in_bytes; |
mahphalke |
17:af1f2416dd26 | 157 | |
mahphalke |
18:5ae03a197e59 | 158 | /* Store the ADC sample size */ |
mahphalke |
18:5ae03a197e59 | 159 | acq_buffer.sample_size = sample_size_in_bytes; |
mahphalke |
18:5ae03a197e59 | 160 | |
mahphalke |
17:af1f2416dd26 | 161 | /* Get the actual available size of buffer by aligning with number of requested samples. |
mahphalke |
18:5ae03a197e59 | 162 | * e.g. if requested samples are 400 and sample size is 2 bytes, the max available |
mahphalke |
18:5ae03a197e59 | 163 | * size of buffer is: available size = ((32768 / 2) / 400) * 400 = 40 * 400 = 16000. |
mahphalke |
17:af1f2416dd26 | 164 | * The max samples to be requested should always be less than half the max size of buffer |
mahphalke |
18:5ae03a197e59 | 165 | * (in this case: (32768/2) / 2 = 8192). |
mahphalke |
17:af1f2416dd26 | 166 | * */ |
mahphalke |
18:5ae03a197e59 | 167 | max_available_buffer_size = ((DATA_BUFFER_SIZE / sample_size_in_bytes) / |
mahphalke |
18:5ae03a197e59 | 168 | num_of_requested_samples) * num_of_requested_samples; |
mahphalke |
17:af1f2416dd26 | 169 | } |
mahphalke |
17:af1f2416dd26 | 170 | |
mahphalke |
17:af1f2416dd26 | 171 | |
mahphalke |
17:af1f2416dd26 | 172 | /*! |
mahphalke |
18:5ae03a197e59 | 173 | * @brief Function to read acquired samples into buffer without IIO request timeout |
mahphalke |
17:af1f2416dd26 | 174 | * @param input_buffer[in] - Input data acquisition buffer |
mahphalke |
17:af1f2416dd26 | 175 | * @param output_buffer[in, out] - Output data buffer |
mahphalke |
17:af1f2416dd26 | 176 | * @param samples_to_read[in] - Number of samples to read |
mahphalke |
17:af1f2416dd26 | 177 | * @param sample_size_in_bytes[in] - Size of each sample in bytes (eqv to ADC resolution) |
mahphalke |
17:af1f2416dd26 | 178 | * @return none |
mahphalke |
17:af1f2416dd26 | 179 | */ |
mahphalke |
18:5ae03a197e59 | 180 | static void read_acquired_samples(char *output_buffer, |
mahphalke |
18:5ae03a197e59 | 181 | size_t samples_to_read, |
mahphalke |
18:5ae03a197e59 | 182 | uint8_t sample_size_in_bytes) |
mahphalke |
17:af1f2416dd26 | 183 | { |
mahphalke |
18:5ae03a197e59 | 184 | int32_t buff_rd_wr_indx_offset; // Offset b/w buffer read and write indexes |
mahphalke |
18:5ae03a197e59 | 185 | uint32_t timeout = BUF_READ_TIMEOUT; // Buffer new data read timeout count |
mahphalke |
17:af1f2416dd26 | 186 | size_t bytes = samples_to_read * sample_size_in_bytes; |
mahphalke |
17:af1f2416dd26 | 187 | |
mahphalke |
17:af1f2416dd26 | 188 | /* Copy the bytes into buffer provided there is enough offset b/w read and write counts. |
mahphalke |
17:af1f2416dd26 | 189 | * If there is overlap b/w read and write indexes (read is faster than write), empty buffer |
mahphalke |
17:af1f2416dd26 | 190 | * should be returned to IIO client to avoid IIO request timeout */ |
mahphalke |
17:af1f2416dd26 | 191 | do { |
mahphalke |
17:af1f2416dd26 | 192 | buff_rd_wr_indx_offset = (acq_buffer.wr_indx - acq_buffer.rd_indx); |
mahphalke |
17:af1f2416dd26 | 193 | timeout--; |
mahphalke |
17:af1f2416dd26 | 194 | } while (((buff_rd_wr_indx_offset < (int32_t)(samples_to_read)) |
mahphalke |
17:af1f2416dd26 | 195 | || (acq_buffer.wr_indx < acq_buffer.rd_indx)) && (timeout > 0) |
mahphalke |
17:af1f2416dd26 | 196 | && start_adc_data_capture); |
mahphalke |
17:af1f2416dd26 | 197 | |
mahphalke |
17:af1f2416dd26 | 198 | if ((timeout == 0) || (acq_buffer.wr_indx <= 0)) { |
mahphalke |
17:af1f2416dd26 | 199 | /* This returns the empty buffer */ |
mahphalke |
17:af1f2416dd26 | 200 | return; |
mahphalke |
17:af1f2416dd26 | 201 | } |
mahphalke |
17:af1f2416dd26 | 202 | |
mahphalke |
17:af1f2416dd26 | 203 | memcpy(output_buffer, |
mahphalke |
18:5ae03a197e59 | 204 | (void const *)&acq_buffer.data[acq_buffer.rd_indx * sample_size_in_bytes], |
mahphalke |
17:af1f2416dd26 | 205 | bytes); |
mahphalke |
17:af1f2416dd26 | 206 | acq_buffer.rd_indx += samples_to_read; |
mahphalke |
17:af1f2416dd26 | 207 | } |
mahphalke |
17:af1f2416dd26 | 208 | |
mahphalke |
17:af1f2416dd26 | 209 | |
mahphalke |
17:af1f2416dd26 | 210 | /*! |
mahphalke |
17:af1f2416dd26 | 211 | * @brief Function to read and align the ADC buffered raw data |
mahphalke |
17:af1f2416dd26 | 212 | * @param device[in]- Device instance |
mahphalke |
17:af1f2416dd26 | 213 | * @param pbuf[out] - Buffer to load ADC raw data |
mahphalke |
17:af1f2416dd26 | 214 | * @param bytes[in] - Number of bytes to be read |
mahphalke |
17:af1f2416dd26 | 215 | * @param active_chns_mask[in] - Active channels mask |
mahphalke |
17:af1f2416dd26 | 216 | * @return Number of bytes read |
mahphalke |
17:af1f2416dd26 | 217 | */ |
mahphalke |
18:5ae03a197e59 | 218 | size_t read_buffered_data(char *pbuf, |
mahphalke |
18:5ae03a197e59 | 219 | size_t bytes, |
mahphalke |
18:5ae03a197e59 | 220 | size_t offset, |
mahphalke |
18:5ae03a197e59 | 221 | uint32_t active_chns_mask, |
mahphalke |
18:5ae03a197e59 | 222 | uint8_t sample_size_in_bytes) |
mahphalke |
17:af1f2416dd26 | 223 | { |
mahphalke |
17:af1f2416dd26 | 224 | size_t samples_to_read = bytes / |
mahphalke |
18:5ae03a197e59 | 225 | sample_size_in_bytes; // Bytes to sample conversion |
mahphalke |
17:af1f2416dd26 | 226 | |
mahphalke |
17:af1f2416dd26 | 227 | /* Make sure requested samples size is less than ADC buffer size. Return constant |
mahphalke |
17:af1f2416dd26 | 228 | * value to avoid IIO client getting timed-out */ |
mahphalke |
18:5ae03a197e59 | 229 | if(num_of_requested_samples >= max_available_buffer_size) { |
mahphalke |
17:af1f2416dd26 | 230 | memset(pbuf, 1, bytes); |
mahphalke |
17:af1f2416dd26 | 231 | return bytes; |
mahphalke |
17:af1f2416dd26 | 232 | } |
mahphalke |
17:af1f2416dd26 | 233 | |
mahphalke |
18:5ae03a197e59 | 234 | /* Increment read counter to point to next acquired data of 1st active channel */ |
mahphalke |
18:5ae03a197e59 | 235 | if ((offset == 0) && (acq_buffer.rd_indx > 0)) { |
mahphalke |
18:5ae03a197e59 | 236 | acq_buffer.rd_indx += chn_alignment_offset; |
mahphalke |
18:5ae03a197e59 | 237 | } |
mahphalke |
17:af1f2416dd26 | 238 | |
mahphalke |
18:5ae03a197e59 | 239 | read_acquired_samples(pbuf, samples_to_read, sample_size_in_bytes); |
mahphalke |
18:5ae03a197e59 | 240 | |
mahphalke |
18:5ae03a197e59 | 241 | /* Make buffer available again once it is read/transmited completely */ |
mahphalke |
17:af1f2416dd26 | 242 | if (acq_buffer.rd_indx >= max_available_buffer_size) { |
mahphalke |
17:af1f2416dd26 | 243 | acq_buffer.rd_indx = 0; |
mahphalke |
17:af1f2416dd26 | 244 | acq_buffer.wr_indx = 0; |
mahphalke |
18:5ae03a197e59 | 245 | acq_buffer.pdata = acq_buffer.data; |
mahphalke |
17:af1f2416dd26 | 246 | acq_buffer.state = BUF_AVAILABLE; |
mahphalke |
18:5ae03a197e59 | 247 | acq_buffer.refill_buffer = true; |
mahphalke |
17:af1f2416dd26 | 248 | } |
mahphalke |
17:af1f2416dd26 | 249 | |
mahphalke |
17:af1f2416dd26 | 250 | return bytes; |
mahphalke |
17:af1f2416dd26 | 251 | } |
mahphalke |
17:af1f2416dd26 | 252 | |
mahphalke |
17:af1f2416dd26 | 253 | |
mahphalke |
17:af1f2416dd26 | 254 | /*! |
mahphalke |
17:af1f2416dd26 | 255 | * @brief This is an ISR (Interrupt Service Routine) to monitor end of conversion event. |
mahphalke |
17:af1f2416dd26 | 256 | * @param *ctx[in] - Callback context (unused) |
mahphalke |
17:af1f2416dd26 | 257 | * @param event[in] - Callback event (unused) |
mahphalke |
17:af1f2416dd26 | 258 | * @param extra[in] - Callback extra (unused) |
mahphalke |
17:af1f2416dd26 | 259 | * @return none |
mahphalke |
17:af1f2416dd26 | 260 | * @details This is an Interrupt callback function/ISR invoked in synchronous/asynchronous |
mahphalke |
17:af1f2416dd26 | 261 | * manner depending upon the application implementation. The conversion results |
mahphalke |
17:af1f2416dd26 | 262 | * are read into acquisition buffer and control continue to sample next channel. |
mahphalke |
17:af1f2416dd26 | 263 | * This continues until conversion is stopped (through IIO client command) |
mahphalke |
18:5ae03a197e59 | 264 | * @note This function also handles the logic to align the first channel data after |
mahphalke |
17:af1f2416dd26 | 265 | * every 'n' sample transmission. This is required to visualize data properly |
mahphalke |
18:5ae03a197e59 | 266 | * on IIO client application. |
mahphalke |
17:af1f2416dd26 | 267 | */ |
mahphalke |
17:af1f2416dd26 | 268 | void data_capture_callback(void *ctx, uint32_t event, void *extra) |
mahphalke |
17:af1f2416dd26 | 269 | { |
mahphalke |
17:af1f2416dd26 | 270 | uint32_t adc_sample; |
mahphalke |
17:af1f2416dd26 | 271 | |
mahphalke |
17:af1f2416dd26 | 272 | if (start_adc_data_capture == true) { |
mahphalke |
18:5ae03a197e59 | 273 | /* Read the sample(s) for channel(s) which has/have been sampled recently and |
mahphalke |
18:5ae03a197e59 | 274 | * get the number of samples read count */ |
mahphalke |
18:5ae03a197e59 | 275 | if (data_capture_ops.read_converted_sample(&adc_sample, |
mahphalke |
18:5ae03a197e59 | 276 | acq_buffer.active_chn[acq_buffer.chn_indx]) != FAILURE) { |
mahphalke |
18:5ae03a197e59 | 277 | do { |
mahphalke |
18:5ae03a197e59 | 278 | if (acq_buffer.state == BUF_AVAILABLE) { |
mahphalke |
18:5ae03a197e59 | 279 | if (acq_buffer.refill_buffer) { |
mahphalke |
18:5ae03a197e59 | 280 | /* Buffer refilling must start with first active channel data |
mahphalke |
18:5ae03a197e59 | 281 | * for IIO client to synchronize the buffered data */ |
mahphalke |
18:5ae03a197e59 | 282 | if (acq_buffer.chn_indx != 0) { |
mahphalke |
18:5ae03a197e59 | 283 | break; |
mahphalke |
18:5ae03a197e59 | 284 | } |
mahphalke |
18:5ae03a197e59 | 285 | acq_buffer.refill_buffer = false; |
mahphalke |
18:5ae03a197e59 | 286 | } |
mahphalke |
17:af1f2416dd26 | 287 | |
mahphalke |
18:5ae03a197e59 | 288 | /* Copy adc samples into acquisition buffer to transport over |
mahphalke |
18:5ae03a197e59 | 289 | * communication link */ |
mahphalke |
18:5ae03a197e59 | 290 | memcpy(acq_buffer.pdata, &adc_sample, acq_buffer.sample_size); |
mahphalke |
18:5ae03a197e59 | 291 | acq_buffer.pdata += acq_buffer.sample_size; |
mahphalke |
17:af1f2416dd26 | 292 | |
mahphalke |
18:5ae03a197e59 | 293 | /* Check for acquisition buffer full condition */ |
mahphalke |
18:5ae03a197e59 | 294 | acq_buffer.wr_indx++; |
mahphalke |
18:5ae03a197e59 | 295 | if (acq_buffer.wr_indx >= max_available_buffer_size) { |
mahphalke |
18:5ae03a197e59 | 296 | acq_buffer.state = BUF_FULL; |
mahphalke |
18:5ae03a197e59 | 297 | } |
mahphalke |
17:af1f2416dd26 | 298 | } |
mahphalke |
18:5ae03a197e59 | 299 | } while (0); |
mahphalke |
17:af1f2416dd26 | 300 | |
mahphalke |
18:5ae03a197e59 | 301 | /* Keep tracking channel index as it is needed to refill the buffer |
mahphalke |
18:5ae03a197e59 | 302 | * starting with first channel data */ |
mahphalke |
18:5ae03a197e59 | 303 | acq_buffer.chn_indx++; |
mahphalke |
18:5ae03a197e59 | 304 | if (acq_buffer.chn_indx >= num_of_active_channels) { |
mahphalke |
18:5ae03a197e59 | 305 | acq_buffer.chn_indx = 0; |
mahphalke |
17:af1f2416dd26 | 306 | } |
mahphalke |
18:5ae03a197e59 | 307 | } |
mahphalke |
17:af1f2416dd26 | 308 | |
mahphalke |
17:af1f2416dd26 | 309 | /* Trigger next continuous conversion (optional or device dependent) */ |
mahphalke |
18:5ae03a197e59 | 310 | if (data_capture_ops.trigger_next_conversion) { |
mahphalke |
18:5ae03a197e59 | 311 | data_capture_ops.trigger_next_conversion(); |
mahphalke |
17:af1f2416dd26 | 312 | } |
mahphalke |
17:af1f2416dd26 | 313 | } |
mahphalke |
17:af1f2416dd26 | 314 | } |
mahphalke |
17:af1f2416dd26 | 315 | |
mahphalke |
17:af1f2416dd26 | 316 | |
mahphalke |
17:af1f2416dd26 | 317 | /*! |
mahphalke |
17:af1f2416dd26 | 318 | * @brief Reset the data capture specific variables |
mahphalke |
17:af1f2416dd26 | 319 | * @return none |
mahphalke |
17:af1f2416dd26 | 320 | */ |
mahphalke |
17:af1f2416dd26 | 321 | static void reset_data_capture(void) |
mahphalke |
17:af1f2416dd26 | 322 | { |
mahphalke |
17:af1f2416dd26 | 323 | /* Reset data capture flags */ |
mahphalke |
17:af1f2416dd26 | 324 | start_adc_data_capture = false; |
mahphalke |
17:af1f2416dd26 | 325 | num_of_active_channels = 0; |
mahphalke |
17:af1f2416dd26 | 326 | |
mahphalke |
17:af1f2416dd26 | 327 | /* Reset acquisition buffer states and clear old data */ |
mahphalke |
17:af1f2416dd26 | 328 | acq_buffer.state = BUF_EMPTY; |
mahphalke |
17:af1f2416dd26 | 329 | |
mahphalke |
17:af1f2416dd26 | 330 | acq_buffer.wr_indx = 0; |
mahphalke |
17:af1f2416dd26 | 331 | acq_buffer.rd_indx = 0; |
mahphalke |
18:5ae03a197e59 | 332 | acq_buffer.chn_indx = 0; |
mahphalke |
18:5ae03a197e59 | 333 | acq_buffer.refill_buffer = false; |
mahphalke |
18:5ae03a197e59 | 334 | acq_buffer.pdata = acq_buffer.data; |
mahphalke |
17:af1f2416dd26 | 335 | } |
mahphalke |
17:af1f2416dd26 | 336 | |
mahphalke |
17:af1f2416dd26 | 337 | |
mahphalke |
17:af1f2416dd26 | 338 | /*! |
mahphalke |
17:af1f2416dd26 | 339 | * @brief Function to trigger ADC conversion for new READBUFF |
mahphalke |
17:af1f2416dd26 | 340 | * request from IIO client (for active channels) |
mahphalke |
17:af1f2416dd26 | 341 | * @param ch_mask[in] - Channels to enable for data capturing |
mahphalke |
17:af1f2416dd26 | 342 | * @param num_of_chns[in] - ADC channel count |
mahphalke |
17:af1f2416dd26 | 343 | * @return none |
mahphalke |
17:af1f2416dd26 | 344 | */ |
mahphalke |
17:af1f2416dd26 | 345 | void start_data_capture(uint32_t ch_mask, uint8_t num_of_chns) |
mahphalke |
17:af1f2416dd26 | 346 | { |
mahphalke |
17:af1f2416dd26 | 347 | uint32_t mask = 0x1; |
mahphalke |
18:5ae03a197e59 | 348 | uint8_t index = 0; |
mahphalke |
17:af1f2416dd26 | 349 | |
mahphalke |
18:5ae03a197e59 | 350 | /* Make sure requested samples size is less than max available buffer size */ |
mahphalke |
17:af1f2416dd26 | 351 | if (num_of_requested_samples >= max_available_buffer_size) { |
mahphalke |
17:af1f2416dd26 | 352 | return; |
mahphalke |
17:af1f2416dd26 | 353 | } |
mahphalke |
17:af1f2416dd26 | 354 | |
mahphalke |
18:5ae03a197e59 | 355 | /* Reset data capture module specific flags and variables */ |
mahphalke |
17:af1f2416dd26 | 356 | reset_data_capture(); |
mahphalke |
17:af1f2416dd26 | 357 | |
mahphalke |
18:5ae03a197e59 | 358 | /* Count active channels based on channel mask set in the IIO client */ |
mahphalke |
17:af1f2416dd26 | 359 | for (uint8_t chn = 0; chn < num_of_chns; chn++) { |
mahphalke |
17:af1f2416dd26 | 360 | if (ch_mask & mask) { |
mahphalke |
18:5ae03a197e59 | 361 | acq_buffer.active_chn[index++] = chn; |
mahphalke |
17:af1f2416dd26 | 362 | num_of_active_channels++; |
mahphalke |
17:af1f2416dd26 | 363 | } |
mahphalke |
17:af1f2416dd26 | 364 | |
mahphalke |
17:af1f2416dd26 | 365 | mask <<= 1; |
mahphalke |
17:af1f2416dd26 | 366 | } |
mahphalke |
17:af1f2416dd26 | 367 | |
mahphalke |
18:5ae03a197e59 | 368 | /* Note: As shown below, after nth sample read, next sample must be for the first |
mahphalke |
18:5ae03a197e59 | 369 | * channel present in the list of enabled channels */ |
mahphalke |
18:5ae03a197e59 | 370 | /*+-----------------------+-------------------------+---------------------------+ |
mahphalke |
18:5ae03a197e59 | 371 | *| 0 | 1 | 2 | ------| n | 0 | 1 | 2 | --------| n | 0 | 1 | 2 |-----------| l | |
mahphalke |
18:5ae03a197e59 | 372 | *+-^-------------------^-+-^---------------------^-+-^-----------------------^-+ |
mahphalke |
18:5ae03a197e59 | 373 | * | | | | | | |
mahphalke |
18:5ae03a197e59 | 374 | * 1st chn data nth data 1st chn data nth data 1st chn data last data |
mahphalke |
18:5ae03a197e59 | 375 | * n = number of requested samples. l = last data (channel unknown) |
mahphalke |
18:5ae03a197e59 | 376 | * To achieve this, offset value is determined based on the requested samples count |
mahphalke |
18:5ae03a197e59 | 377 | * and number of active channels. The read index is then incremented by offset value |
mahphalke |
18:5ae03a197e59 | 378 | * to read the data for first enabled channel by mapping into acquisition buffer. |
mahphalke |
18:5ae03a197e59 | 379 | **/ |
mahphalke |
18:5ae03a197e59 | 380 | if (num_of_requested_samples % num_of_active_channels) { |
mahphalke |
18:5ae03a197e59 | 381 | chn_alignment_offset = (num_of_requested_samples - ((num_of_requested_samples / |
mahphalke |
18:5ae03a197e59 | 382 | num_of_active_channels) * num_of_active_channels)) + 1; |
mahphalke |
18:5ae03a197e59 | 383 | } else { |
mahphalke |
18:5ae03a197e59 | 384 | chn_alignment_offset = 0; |
mahphalke |
18:5ae03a197e59 | 385 | } |
mahphalke |
18:5ae03a197e59 | 386 | |
mahphalke |
18:5ae03a197e59 | 387 | /* Make acquisition buffer available and start continuous conversion */ |
mahphalke |
17:af1f2416dd26 | 388 | acq_buffer.state = BUF_AVAILABLE; |
mahphalke |
18:5ae03a197e59 | 389 | if (data_capture_ops.continuous_sample_read_start_ops) { |
mahphalke |
18:5ae03a197e59 | 390 | if (data_capture_ops.continuous_sample_read_start_ops(ch_mask) != FAILURE) { |
mahphalke |
18:5ae03a197e59 | 391 | start_adc_data_capture = true; |
mahphalke |
18:5ae03a197e59 | 392 | } |
mahphalke |
18:5ae03a197e59 | 393 | } else { |
mahphalke |
17:af1f2416dd26 | 394 | start_adc_data_capture = true; |
mahphalke |
17:af1f2416dd26 | 395 | } |
mahphalke |
17:af1f2416dd26 | 396 | } |
mahphalke |
17:af1f2416dd26 | 397 | |
mahphalke |
17:af1f2416dd26 | 398 | |
mahphalke |
17:af1f2416dd26 | 399 | /*! |
mahphalke |
17:af1f2416dd26 | 400 | * @brief Function to stop ADC data capture |
mahphalke |
17:af1f2416dd26 | 401 | * @return none |
mahphalke |
17:af1f2416dd26 | 402 | */ |
mahphalke |
17:af1f2416dd26 | 403 | void stop_data_capture(void) |
mahphalke |
17:af1f2416dd26 | 404 | { |
mahphalke |
17:af1f2416dd26 | 405 | start_adc_data_capture = false; |
mahphalke |
17:af1f2416dd26 | 406 | |
mahphalke |
18:5ae03a197e59 | 407 | /* Enable operations required post continuous sample read */ |
mahphalke |
18:5ae03a197e59 | 408 | if (data_capture_ops.continuous_sample_read_stop_ops) { |
mahphalke |
18:5ae03a197e59 | 409 | data_capture_ops.continuous_sample_read_stop_ops(); |
mahphalke |
17:af1f2416dd26 | 410 | } |
mahphalke |
17:af1f2416dd26 | 411 | |
mahphalke |
18:5ae03a197e59 | 412 | /* Reset data capture module specific flags and variables */ |
mahphalke |
17:af1f2416dd26 | 413 | reset_data_capture(); |
mahphalke |
17:af1f2416dd26 | 414 | } |