Forked repository for pushing changes
adc_data_capture.c@17:af1f2416dd26, 2021-07-13 (annotated)
- Committer:
- mahphalke
- Date:
- Tue Jul 13 13:58:07 2021 +0530
- Revision:
- 17:af1f2416dd26
- Child:
- 18:5ae03a197e59
Restructured the directory- Removed inc/ and src/ folders and moved all source/header files at root
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 |
17:af1f2416dd26 | 29 | /* IIO buffer request size in bytes */ |
mahphalke |
17:af1f2416dd26 | 30 | #define IIO_BUF_READ_REQUEST_SIZE (256) |
mahphalke |
17:af1f2416dd26 | 31 | |
mahphalke |
17:af1f2416dd26 | 32 | /* Max size of the acquisition buffer (in terms of samples) */ |
mahphalke |
17:af1f2416dd26 | 33 | #define DATA_BUFFER_SIZE (8192) |
mahphalke |
17:af1f2416dd26 | 34 | |
mahphalke |
17:af1f2416dd26 | 35 | /* Timeout count to avoid stuck into potential infinite loop while checking |
mahphalke |
17:af1f2416dd26 | 36 | * for new data into an acquisition buffer. The actual timeout factor is determined |
mahphalke |
17:af1f2416dd26 | 37 | * through 'sampling_frequency' attribute, but this period here makes sure |
mahphalke |
17:af1f2416dd26 | 38 | * we are not stuck into a loop forever in case data capture interrupted |
mahphalke |
17:af1f2416dd26 | 39 | * or failed in between */ |
mahphalke |
17:af1f2416dd26 | 40 | #define BUF_READ_TIMEOUT (100000000) |
mahphalke |
17:af1f2416dd26 | 41 | |
mahphalke |
17:af1f2416dd26 | 42 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 43 | /********************** Variables and User Defined Data Types *****************/ |
mahphalke |
17:af1f2416dd26 | 44 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 45 | |
mahphalke |
17:af1f2416dd26 | 46 | /* Extern declaration for data capture operations structure variable */ |
mahphalke |
17:af1f2416dd26 | 47 | extern struct data_capture_ops data_capture_ops; |
mahphalke |
17:af1f2416dd26 | 48 | |
mahphalke |
17:af1f2416dd26 | 49 | /* |
mahphalke |
17:af1f2416dd26 | 50 | *@enum acq_buffer_state_e |
mahphalke |
17:af1f2416dd26 | 51 | *@details Enum holding the data acquisition buffer states |
mahphalke |
17:af1f2416dd26 | 52 | **/ |
mahphalke |
17:af1f2416dd26 | 53 | typedef enum { |
mahphalke |
17:af1f2416dd26 | 54 | BUF_AVAILABLE, |
mahphalke |
17:af1f2416dd26 | 55 | BUF_EMPTY, |
mahphalke |
17:af1f2416dd26 | 56 | BUF_FULL |
mahphalke |
17:af1f2416dd26 | 57 | } acq_buffer_state_e; |
mahphalke |
17:af1f2416dd26 | 58 | |
mahphalke |
17:af1f2416dd26 | 59 | /* |
mahphalke |
17:af1f2416dd26 | 60 | *@struct acq_buf_t |
mahphalke |
17:af1f2416dd26 | 61 | *@details Structure holding the data acquisition buffer parameters |
mahphalke |
17:af1f2416dd26 | 62 | **/ |
mahphalke |
17:af1f2416dd26 | 63 | typedef struct { |
mahphalke |
17:af1f2416dd26 | 64 | acq_buffer_state_e state; // buffer state |
mahphalke |
17:af1f2416dd26 | 65 | uint32_t rd_indx; // buffer read index |
mahphalke |
17:af1f2416dd26 | 66 | uint32_t wr_indx; // buffer write index |
mahphalke |
17:af1f2416dd26 | 67 | uint32_t sample_cnt; // buffer data/sample counter |
mahphalke |
17:af1f2416dd26 | 68 | uint32_t data[DATA_BUFFER_SIZE]; // buffer data (adc raw values) |
mahphalke |
17:af1f2416dd26 | 69 | } acq_buf_t; |
mahphalke |
17:af1f2416dd26 | 70 | |
mahphalke |
17:af1f2416dd26 | 71 | /* ADC data acquisition buffers */ |
mahphalke |
17:af1f2416dd26 | 72 | static volatile acq_buf_t acq_buffer; |
mahphalke |
17:af1f2416dd26 | 73 | |
mahphalke |
17:af1f2416dd26 | 74 | /* Flag to indicate data capture status */ |
mahphalke |
17:af1f2416dd26 | 75 | static volatile bool start_adc_data_capture = false; |
mahphalke |
17:af1f2416dd26 | 76 | |
mahphalke |
17:af1f2416dd26 | 77 | /* Number of active channels in any data buffer read request */ |
mahphalke |
17:af1f2416dd26 | 78 | static volatile uint8_t num_of_active_channels = 0; |
mahphalke |
17:af1f2416dd26 | 79 | |
mahphalke |
17:af1f2416dd26 | 80 | /* Channel data alignment variables */ |
mahphalke |
17:af1f2416dd26 | 81 | static volatile uint8_t buff_chn_indx = 0; |
mahphalke |
17:af1f2416dd26 | 82 | static volatile bool do_chn_alignment = false; |
mahphalke |
17:af1f2416dd26 | 83 | |
mahphalke |
17:af1f2416dd26 | 84 | /* Count to track number of actual samples requested by IIO client */ |
mahphalke |
17:af1f2416dd26 | 85 | static volatile uint16_t num_of_requested_samples = 0; |
mahphalke |
17:af1f2416dd26 | 86 | |
mahphalke |
17:af1f2416dd26 | 87 | /* Actual or max available size of acquisition buffer */ |
mahphalke |
17:af1f2416dd26 | 88 | static volatile uint16_t max_available_buffer_size = 0; |
mahphalke |
17:af1f2416dd26 | 89 | |
mahphalke |
17:af1f2416dd26 | 90 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 91 | /************************ Functions Declarations ******************************/ |
mahphalke |
17:af1f2416dd26 | 92 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 93 | |
mahphalke |
17:af1f2416dd26 | 94 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 95 | /************************ Functions Definitions *******************************/ |
mahphalke |
17:af1f2416dd26 | 96 | /******************************************************************************/ |
mahphalke |
17:af1f2416dd26 | 97 | |
mahphalke |
17:af1f2416dd26 | 98 | /*! |
mahphalke |
17:af1f2416dd26 | 99 | * @brief Function to read the ADC raw data for single channel |
mahphalke |
17:af1f2416dd26 | 100 | * @param input_chn[in] - Input channel to sample and read data for |
mahphalke |
17:af1f2416dd26 | 101 | * @param raw_data[in, out]- ADC raw data |
mahphalke |
17:af1f2416dd26 | 102 | * @return SUCCESS in case of success, FAILURE otherwise |
mahphalke |
17:af1f2416dd26 | 103 | */ |
mahphalke |
17:af1f2416dd26 | 104 | int32_t single_data_read(uint8_t input_chn, uint32_t *raw_data) |
mahphalke |
17:af1f2416dd26 | 105 | { |
mahphalke |
17:af1f2416dd26 | 106 | uint32_t read_adc_data = 0; |
mahphalke |
17:af1f2416dd26 | 107 | int32_t status = SUCCESS; |
mahphalke |
17:af1f2416dd26 | 108 | |
mahphalke |
17:af1f2416dd26 | 109 | do { |
mahphalke |
17:af1f2416dd26 | 110 | if (data_capture_ops.save_prev_active_chns) { |
mahphalke |
17:af1f2416dd26 | 111 | /* Save previously active channels */ |
mahphalke |
17:af1f2416dd26 | 112 | if (data_capture_ops.save_prev_active_chns() != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 113 | status = FAILURE; |
mahphalke |
17:af1f2416dd26 | 114 | break; |
mahphalke |
17:af1f2416dd26 | 115 | } |
mahphalke |
17:af1f2416dd26 | 116 | } |
mahphalke |
17:af1f2416dd26 | 117 | |
mahphalke |
17:af1f2416dd26 | 118 | if (data_capture_ops.disable_all_chns) { |
mahphalke |
17:af1f2416dd26 | 119 | /* Disable all channels */ |
mahphalke |
17:af1f2416dd26 | 120 | if (data_capture_ops.disable_all_chns() != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 121 | status = FAILURE; |
mahphalke |
17:af1f2416dd26 | 122 | break; |
mahphalke |
17:af1f2416dd26 | 123 | } |
mahphalke |
17:af1f2416dd26 | 124 | } |
mahphalke |
17:af1f2416dd26 | 125 | |
mahphalke |
17:af1f2416dd26 | 126 | if (data_capture_ops.enable_curr_chn) { |
mahphalke |
17:af1f2416dd26 | 127 | /* Enable user input channel */ |
mahphalke |
17:af1f2416dd26 | 128 | if (data_capture_ops.enable_curr_chn(input_chn) != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 129 | status = FAILURE; |
mahphalke |
17:af1f2416dd26 | 130 | break; |
mahphalke |
17:af1f2416dd26 | 131 | } |
mahphalke |
17:af1f2416dd26 | 132 | } |
mahphalke |
17:af1f2416dd26 | 133 | |
mahphalke |
17:af1f2416dd26 | 134 | if (data_capture_ops.enable_single_read_conversion) { |
mahphalke |
17:af1f2416dd26 | 135 | /* Enable single data read conversion */ |
mahphalke |
17:af1f2416dd26 | 136 | if (data_capture_ops.enable_single_read_conversion() != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 137 | status = FAILURE; |
mahphalke |
17:af1f2416dd26 | 138 | break; |
mahphalke |
17:af1f2416dd26 | 139 | } |
mahphalke |
17:af1f2416dd26 | 140 | } |
mahphalke |
17:af1f2416dd26 | 141 | |
mahphalke |
17:af1f2416dd26 | 142 | /* Read the data */ |
mahphalke |
17:af1f2416dd26 | 143 | if (data_capture_ops.wait_for_conv_and_read_data(&read_adc_data, input_chn) != |
mahphalke |
17:af1f2416dd26 | 144 | SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 145 | status = FAILURE; |
mahphalke |
17:af1f2416dd26 | 146 | break; |
mahphalke |
17:af1f2416dd26 | 147 | } |
mahphalke |
17:af1f2416dd26 | 148 | } while (0); |
mahphalke |
17:af1f2416dd26 | 149 | |
mahphalke |
17:af1f2416dd26 | 150 | if (data_capture_ops.restore_prev_active_chns) { |
mahphalke |
17:af1f2416dd26 | 151 | /* Enable back channels which were disabled prior to single data read */ |
mahphalke |
17:af1f2416dd26 | 152 | data_capture_ops.restore_prev_active_chns(); |
mahphalke |
17:af1f2416dd26 | 153 | } |
mahphalke |
17:af1f2416dd26 | 154 | |
mahphalke |
17:af1f2416dd26 | 155 | if (data_capture_ops.disable_conversion) { |
mahphalke |
17:af1f2416dd26 | 156 | /* Exit from conversion mode */ |
mahphalke |
17:af1f2416dd26 | 157 | data_capture_ops.disable_conversion(); |
mahphalke |
17:af1f2416dd26 | 158 | } |
mahphalke |
17:af1f2416dd26 | 159 | |
mahphalke |
17:af1f2416dd26 | 160 | *raw_data = read_adc_data; |
mahphalke |
17:af1f2416dd26 | 161 | return status; |
mahphalke |
17:af1f2416dd26 | 162 | } |
mahphalke |
17:af1f2416dd26 | 163 | |
mahphalke |
17:af1f2416dd26 | 164 | |
mahphalke |
17:af1f2416dd26 | 165 | /*! |
mahphalke |
17:af1f2416dd26 | 166 | * @brief Function to store the number of actul requested samples from IIO client |
mahphalke |
17:af1f2416dd26 | 167 | * @param bytes[in] - Number of bytes corresponding to requested samples |
mahphalke |
17:af1f2416dd26 | 168 | * @param sample_size_in_bytes[in] - Size of each sample in bytes (eqv to ADC resolution) |
mahphalke |
17:af1f2416dd26 | 169 | * @return none |
mahphalke |
17:af1f2416dd26 | 170 | */ |
mahphalke |
17:af1f2416dd26 | 171 | void store_requested_samples_count(size_t bytes, uint8_t sample_size_in_bytes) |
mahphalke |
17:af1f2416dd26 | 172 | { |
mahphalke |
17:af1f2416dd26 | 173 | /* This gets the number of samples requested by IIO client for all active channels */ |
mahphalke |
17:af1f2416dd26 | 174 | num_of_requested_samples = bytes / sample_size_in_bytes; |
mahphalke |
17:af1f2416dd26 | 175 | |
mahphalke |
17:af1f2416dd26 | 176 | /* Get the actual available size of buffer by aligning with number of requested samples. |
mahphalke |
17:af1f2416dd26 | 177 | * e.g. if requested samples are 400, the max available size of buffer is: |
mahphalke |
17:af1f2416dd26 | 178 | * available size = (2048 / 400) * 400 = 5 * 400 = 2000. |
mahphalke |
17:af1f2416dd26 | 179 | * The max samples to be requested should always be less than half the max size of buffer |
mahphalke |
17:af1f2416dd26 | 180 | * (in this case: 2048 / 2 = 1024). |
mahphalke |
17:af1f2416dd26 | 181 | * */ |
mahphalke |
17:af1f2416dd26 | 182 | max_available_buffer_size = ((DATA_BUFFER_SIZE / num_of_requested_samples) * |
mahphalke |
17:af1f2416dd26 | 183 | num_of_requested_samples); |
mahphalke |
17:af1f2416dd26 | 184 | } |
mahphalke |
17:af1f2416dd26 | 185 | |
mahphalke |
17:af1f2416dd26 | 186 | |
mahphalke |
17:af1f2416dd26 | 187 | /*! |
mahphalke |
17:af1f2416dd26 | 188 | * @brief Function to read new samples into buffer without IIO request timeout |
mahphalke |
17:af1f2416dd26 | 189 | * @param input_buffer[in] - Input data acquisition buffer |
mahphalke |
17:af1f2416dd26 | 190 | * @param output_buffer[in, out] - Output data buffer |
mahphalke |
17:af1f2416dd26 | 191 | * @param samples_to_read[in] - Number of samples to read |
mahphalke |
17:af1f2416dd26 | 192 | * @param sample_size_in_bytes[in] - Size of each sample in bytes (eqv to ADC resolution) |
mahphalke |
17:af1f2416dd26 | 193 | * @return none |
mahphalke |
17:af1f2416dd26 | 194 | */ |
mahphalke |
17:af1f2416dd26 | 195 | static void wait_and_read_new_samples(char *output_buffer, |
mahphalke |
17:af1f2416dd26 | 196 | size_t samples_to_read, |
mahphalke |
17:af1f2416dd26 | 197 | uint8_t sample_size_in_bytes) |
mahphalke |
17:af1f2416dd26 | 198 | { |
mahphalke |
17:af1f2416dd26 | 199 | int32_t buff_rd_wr_indx_offset; // Offset b/w buffer read and write indexes |
mahphalke |
17:af1f2416dd26 | 200 | uint32_t timeout = BUF_READ_TIMEOUT; // Buffer new data read timeout count |
mahphalke |
17:af1f2416dd26 | 201 | size_t bytes = samples_to_read * sample_size_in_bytes; |
mahphalke |
17:af1f2416dd26 | 202 | |
mahphalke |
17:af1f2416dd26 | 203 | /* Copy the bytes into buffer provided there is enough offset b/w read and write counts. |
mahphalke |
17:af1f2416dd26 | 204 | * If there is overlap b/w read and write indexes (read is faster than write), empty buffer |
mahphalke |
17:af1f2416dd26 | 205 | * should be returned to IIO client to avoid IIO request timeout */ |
mahphalke |
17:af1f2416dd26 | 206 | do { |
mahphalke |
17:af1f2416dd26 | 207 | buff_rd_wr_indx_offset = (acq_buffer.wr_indx - acq_buffer.rd_indx); |
mahphalke |
17:af1f2416dd26 | 208 | timeout--; |
mahphalke |
17:af1f2416dd26 | 209 | } while (((buff_rd_wr_indx_offset < (int32_t)(samples_to_read)) |
mahphalke |
17:af1f2416dd26 | 210 | || (acq_buffer.wr_indx < acq_buffer.rd_indx)) && (timeout > 0) |
mahphalke |
17:af1f2416dd26 | 211 | && start_adc_data_capture); |
mahphalke |
17:af1f2416dd26 | 212 | |
mahphalke |
17:af1f2416dd26 | 213 | if ((timeout == 0) || (acq_buffer.wr_indx <= 0)) { |
mahphalke |
17:af1f2416dd26 | 214 | /* This returns the empty buffer */ |
mahphalke |
17:af1f2416dd26 | 215 | return; |
mahphalke |
17:af1f2416dd26 | 216 | } |
mahphalke |
17:af1f2416dd26 | 217 | |
mahphalke |
17:af1f2416dd26 | 218 | memcpy(output_buffer, |
mahphalke |
17:af1f2416dd26 | 219 | (void const *)&acq_buffer.data[acq_buffer.rd_indx], |
mahphalke |
17:af1f2416dd26 | 220 | bytes); |
mahphalke |
17:af1f2416dd26 | 221 | acq_buffer.rd_indx += samples_to_read; |
mahphalke |
17:af1f2416dd26 | 222 | } |
mahphalke |
17:af1f2416dd26 | 223 | |
mahphalke |
17:af1f2416dd26 | 224 | |
mahphalke |
17:af1f2416dd26 | 225 | /*! |
mahphalke |
17:af1f2416dd26 | 226 | * @brief Function to read and align the ADC buffered raw data |
mahphalke |
17:af1f2416dd26 | 227 | * @param device[in]- Device instance |
mahphalke |
17:af1f2416dd26 | 228 | * @param pbuf[out] - Buffer to load ADC raw data |
mahphalke |
17:af1f2416dd26 | 229 | * @param bytes[in] - Number of bytes to be read |
mahphalke |
17:af1f2416dd26 | 230 | * @param active_chns_mask[in] - Active channels mask |
mahphalke |
17:af1f2416dd26 | 231 | * @return Number of bytes read |
mahphalke |
17:af1f2416dd26 | 232 | */ |
mahphalke |
17:af1f2416dd26 | 233 | size_t buffered_data_read(char *pbuf, size_t bytes, |
mahphalke |
17:af1f2416dd26 | 234 | size_t offset, uint32_t active_chns_mask, uint8_t sample_size_in_bytes) |
mahphalke |
17:af1f2416dd26 | 235 | { |
mahphalke |
17:af1f2416dd26 | 236 | size_t samples_to_read = bytes / |
mahphalke |
17:af1f2416dd26 | 237 | sample_size_in_bytes; // Bytes to sample conversion |
mahphalke |
17:af1f2416dd26 | 238 | |
mahphalke |
17:af1f2416dd26 | 239 | /* Make sure requested samples size is less than ADC buffer size. Return constant |
mahphalke |
17:af1f2416dd26 | 240 | * value to avoid IIO client getting timed-out */ |
mahphalke |
17:af1f2416dd26 | 241 | if (num_of_requested_samples >= max_available_buffer_size) { |
mahphalke |
17:af1f2416dd26 | 242 | memset(pbuf, 1, bytes); |
mahphalke |
17:af1f2416dd26 | 243 | return bytes; |
mahphalke |
17:af1f2416dd26 | 244 | } |
mahphalke |
17:af1f2416dd26 | 245 | |
mahphalke |
17:af1f2416dd26 | 246 | wait_and_read_new_samples(pbuf, samples_to_read, sample_size_in_bytes); |
mahphalke |
17:af1f2416dd26 | 247 | |
mahphalke |
17:af1f2416dd26 | 248 | /* Make buffer available again once read completely */ |
mahphalke |
17:af1f2416dd26 | 249 | if (acq_buffer.rd_indx >= max_available_buffer_size) { |
mahphalke |
17:af1f2416dd26 | 250 | acq_buffer.rd_indx = 0; |
mahphalke |
17:af1f2416dd26 | 251 | acq_buffer.wr_indx = 0; |
mahphalke |
17:af1f2416dd26 | 252 | acq_buffer.sample_cnt = 0; |
mahphalke |
17:af1f2416dd26 | 253 | acq_buffer.state = BUF_AVAILABLE; |
mahphalke |
17:af1f2416dd26 | 254 | } |
mahphalke |
17:af1f2416dd26 | 255 | |
mahphalke |
17:af1f2416dd26 | 256 | return bytes; |
mahphalke |
17:af1f2416dd26 | 257 | } |
mahphalke |
17:af1f2416dd26 | 258 | |
mahphalke |
17:af1f2416dd26 | 259 | |
mahphalke |
17:af1f2416dd26 | 260 | /*! |
mahphalke |
17:af1f2416dd26 | 261 | * @brief This is an ISR (Interrupt Service Routine) to monitor end of conversion event. |
mahphalke |
17:af1f2416dd26 | 262 | * @param *ctx[in] - Callback context (unused) |
mahphalke |
17:af1f2416dd26 | 263 | * @param event[in] - Callback event (unused) |
mahphalke |
17:af1f2416dd26 | 264 | * @param extra[in] - Callback extra (unused) |
mahphalke |
17:af1f2416dd26 | 265 | * @return none |
mahphalke |
17:af1f2416dd26 | 266 | * @details This is an Interrupt callback function/ISR invoked in synchronous/asynchronous |
mahphalke |
17:af1f2416dd26 | 267 | * manner depending upon the application implementation. The conversion results |
mahphalke |
17:af1f2416dd26 | 268 | * are read into acquisition buffer and control continue to sample next channel. |
mahphalke |
17:af1f2416dd26 | 269 | * This continues until conversion is stopped (through IIO client command) |
mahphalke |
17:af1f2416dd26 | 270 | * @note This function also handles the logic to align the zeroth channel data after |
mahphalke |
17:af1f2416dd26 | 271 | * every 'n' sample transmission. This is required to visualize data properly |
mahphalke |
17:af1f2416dd26 | 272 | * on IIO client application (more details listed below). |
mahphalke |
17:af1f2416dd26 | 273 | */ |
mahphalke |
17:af1f2416dd26 | 274 | void data_capture_callback(void *ctx, uint32_t event, void *extra) |
mahphalke |
17:af1f2416dd26 | 275 | { |
mahphalke |
17:af1f2416dd26 | 276 | uint32_t adc_sample; |
mahphalke |
17:af1f2416dd26 | 277 | |
mahphalke |
17:af1f2416dd26 | 278 | if (start_adc_data_capture == true) { |
mahphalke |
17:af1f2416dd26 | 279 | do { |
mahphalke |
17:af1f2416dd26 | 280 | /* Read the data for channel which has been sampled recently */ |
mahphalke |
17:af1f2416dd26 | 281 | if (data_capture_ops.read_sampled_data(&adc_sample, buff_chn_indx) != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 282 | break; |
mahphalke |
17:af1f2416dd26 | 283 | } |
mahphalke |
17:af1f2416dd26 | 284 | |
mahphalke |
17:af1f2416dd26 | 285 | /* If next sample/data in acquisition buffer is required to be of the zeroth |
mahphalke |
17:af1f2416dd26 | 286 | * channel from a list of enabled channels (i.e. chn data alignment needed), then |
mahphalke |
17:af1f2416dd26 | 287 | * wait until a conversion end event is triggered for that zeroth enabled channel */ |
mahphalke |
17:af1f2416dd26 | 288 | /* Note: As shown below, after nth sample read, next sample must be for the zeroth |
mahphalke |
17:af1f2416dd26 | 289 | * channel present in the list of enabled channels */ |
mahphalke |
17:af1f2416dd26 | 290 | /*+-----------------------+-------------------------+---------------------------+ |
mahphalke |
17:af1f2416dd26 | 291 | *| 0 | 1 | 2 | ------| n | 0 | 1 | 2 | --------| n | 0 | 1 | 2 |-----------| n | |
mahphalke |
17:af1f2416dd26 | 292 | *+-^-------------------^-+-^---------------------^-+-^-----------------------^-+ |
mahphalke |
17:af1f2416dd26 | 293 | * | | | | | | |
mahphalke |
17:af1f2416dd26 | 294 | * 0th chn data last data 0th chn data last data 0th chn data last data |
mahphalke |
17:af1f2416dd26 | 295 | * n = number of requested samples |
mahphalke |
17:af1f2416dd26 | 296 | **/ |
mahphalke |
17:af1f2416dd26 | 297 | /* Wait until conversion event for the zeroth channel is triggered */ |
mahphalke |
17:af1f2416dd26 | 298 | if ((do_chn_alignment == true) && (buff_chn_indx != 0)) { |
mahphalke |
17:af1f2416dd26 | 299 | /* Track the count for recently sampled channel */ |
mahphalke |
17:af1f2416dd26 | 300 | buff_chn_indx++; |
mahphalke |
17:af1f2416dd26 | 301 | if (buff_chn_indx >= num_of_active_channels) { |
mahphalke |
17:af1f2416dd26 | 302 | buff_chn_indx = 0; |
mahphalke |
17:af1f2416dd26 | 303 | } |
mahphalke |
17:af1f2416dd26 | 304 | |
mahphalke |
17:af1f2416dd26 | 305 | /* If recent sampled channel is not a zeroth enabled channel |
mahphalke |
17:af1f2416dd26 | 306 | * in the channels list, return without storing data into buffer */ |
mahphalke |
17:af1f2416dd26 | 307 | break; |
mahphalke |
17:af1f2416dd26 | 308 | } |
mahphalke |
17:af1f2416dd26 | 309 | |
mahphalke |
17:af1f2416dd26 | 310 | /* Track the count for recently sampled channel */ |
mahphalke |
17:af1f2416dd26 | 311 | buff_chn_indx++; |
mahphalke |
17:af1f2416dd26 | 312 | if (buff_chn_indx >= num_of_active_channels) { |
mahphalke |
17:af1f2416dd26 | 313 | buff_chn_indx = 0; |
mahphalke |
17:af1f2416dd26 | 314 | } |
mahphalke |
17:af1f2416dd26 | 315 | |
mahphalke |
17:af1f2416dd26 | 316 | if (acq_buffer.state == BUF_AVAILABLE) { |
mahphalke |
17:af1f2416dd26 | 317 | /* Reset channel data alignment flag if control reach here */ |
mahphalke |
17:af1f2416dd26 | 318 | do_chn_alignment = false; |
mahphalke |
17:af1f2416dd26 | 319 | |
mahphalke |
17:af1f2416dd26 | 320 | acq_buffer.data[acq_buffer.wr_indx++] = adc_sample; |
mahphalke |
17:af1f2416dd26 | 321 | acq_buffer.sample_cnt++; |
mahphalke |
17:af1f2416dd26 | 322 | |
mahphalke |
17:af1f2416dd26 | 323 | /* Check if current buffer is full */ |
mahphalke |
17:af1f2416dd26 | 324 | if (acq_buffer.wr_indx >= max_available_buffer_size) { |
mahphalke |
17:af1f2416dd26 | 325 | acq_buffer.state = BUF_FULL; |
mahphalke |
17:af1f2416dd26 | 326 | } |
mahphalke |
17:af1f2416dd26 | 327 | |
mahphalke |
17:af1f2416dd26 | 328 | /* Once all requested number of samples are transmitted, make sure |
mahphalke |
17:af1f2416dd26 | 329 | * next data to be loaded into acquisition buffer is for zeroth channel |
mahphalke |
17:af1f2416dd26 | 330 | * present in the channels list */ |
mahphalke |
17:af1f2416dd26 | 331 | if (acq_buffer.sample_cnt >= num_of_requested_samples) { |
mahphalke |
17:af1f2416dd26 | 332 | acq_buffer.sample_cnt = 0; |
mahphalke |
17:af1f2416dd26 | 333 | do_chn_alignment = true; |
mahphalke |
17:af1f2416dd26 | 334 | } |
mahphalke |
17:af1f2416dd26 | 335 | } |
mahphalke |
17:af1f2416dd26 | 336 | } while (0); |
mahphalke |
17:af1f2416dd26 | 337 | |
mahphalke |
17:af1f2416dd26 | 338 | /* Trigger next continuous conversion (optional or device dependent) */ |
mahphalke |
17:af1f2416dd26 | 339 | if (data_capture_ops.trigger_next_cont_conversion) { |
mahphalke |
17:af1f2416dd26 | 340 | data_capture_ops.trigger_next_cont_conversion(); |
mahphalke |
17:af1f2416dd26 | 341 | } |
mahphalke |
17:af1f2416dd26 | 342 | } |
mahphalke |
17:af1f2416dd26 | 343 | } |
mahphalke |
17:af1f2416dd26 | 344 | |
mahphalke |
17:af1f2416dd26 | 345 | |
mahphalke |
17:af1f2416dd26 | 346 | /*! |
mahphalke |
17:af1f2416dd26 | 347 | * @brief Reset the data capture specific variables |
mahphalke |
17:af1f2416dd26 | 348 | * @return none |
mahphalke |
17:af1f2416dd26 | 349 | */ |
mahphalke |
17:af1f2416dd26 | 350 | static void reset_data_capture(void) |
mahphalke |
17:af1f2416dd26 | 351 | { |
mahphalke |
17:af1f2416dd26 | 352 | /* Reset data capture flags */ |
mahphalke |
17:af1f2416dd26 | 353 | start_adc_data_capture = false; |
mahphalke |
17:af1f2416dd26 | 354 | num_of_active_channels = 0; |
mahphalke |
17:af1f2416dd26 | 355 | |
mahphalke |
17:af1f2416dd26 | 356 | /* Reset acquisition buffer states and clear old data */ |
mahphalke |
17:af1f2416dd26 | 357 | acq_buffer.state = BUF_EMPTY; |
mahphalke |
17:af1f2416dd26 | 358 | |
mahphalke |
17:af1f2416dd26 | 359 | acq_buffer.wr_indx = 0; |
mahphalke |
17:af1f2416dd26 | 360 | acq_buffer.rd_indx = 0; |
mahphalke |
17:af1f2416dd26 | 361 | acq_buffer.sample_cnt = 0; |
mahphalke |
17:af1f2416dd26 | 362 | |
mahphalke |
17:af1f2416dd26 | 363 | buff_chn_indx = 0; |
mahphalke |
17:af1f2416dd26 | 364 | do_chn_alignment = true; |
mahphalke |
17:af1f2416dd26 | 365 | } |
mahphalke |
17:af1f2416dd26 | 366 | |
mahphalke |
17:af1f2416dd26 | 367 | |
mahphalke |
17:af1f2416dd26 | 368 | /*! |
mahphalke |
17:af1f2416dd26 | 369 | * @brief Function to trigger ADC conversion for new READBUFF |
mahphalke |
17:af1f2416dd26 | 370 | * request from IIO client (for active channels) |
mahphalke |
17:af1f2416dd26 | 371 | * @param ch_mask[in] - Channels to enable for data capturing |
mahphalke |
17:af1f2416dd26 | 372 | * @param num_of_chns[in] - ADC channel count |
mahphalke |
17:af1f2416dd26 | 373 | * @return none |
mahphalke |
17:af1f2416dd26 | 374 | */ |
mahphalke |
17:af1f2416dd26 | 375 | void start_data_capture(uint32_t ch_mask, uint8_t num_of_chns) |
mahphalke |
17:af1f2416dd26 | 376 | { |
mahphalke |
17:af1f2416dd26 | 377 | uint32_t mask = 0x1; |
mahphalke |
17:af1f2416dd26 | 378 | |
mahphalke |
17:af1f2416dd26 | 379 | /* Make sure requested samples size is less than ADC buffer size */ |
mahphalke |
17:af1f2416dd26 | 380 | if (num_of_requested_samples >= max_available_buffer_size) { |
mahphalke |
17:af1f2416dd26 | 381 | return; |
mahphalke |
17:af1f2416dd26 | 382 | } |
mahphalke |
17:af1f2416dd26 | 383 | |
mahphalke |
17:af1f2416dd26 | 384 | if (data_capture_ops.disable_conversion) { |
mahphalke |
17:af1f2416dd26 | 385 | /* Stop any previous conversion by putting ADC into standby mode */ |
mahphalke |
17:af1f2416dd26 | 386 | if (data_capture_ops.disable_conversion() != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 387 | return; |
mahphalke |
17:af1f2416dd26 | 388 | } |
mahphalke |
17:af1f2416dd26 | 389 | } |
mahphalke |
17:af1f2416dd26 | 390 | |
mahphalke |
17:af1f2416dd26 | 391 | /* Reset data capture related flags and variables */ |
mahphalke |
17:af1f2416dd26 | 392 | reset_data_capture(); |
mahphalke |
17:af1f2416dd26 | 393 | |
mahphalke |
17:af1f2416dd26 | 394 | if (data_capture_ops.save_prev_active_chns) { |
mahphalke |
17:af1f2416dd26 | 395 | /* Store the previous active channels */ |
mahphalke |
17:af1f2416dd26 | 396 | if (data_capture_ops.save_prev_active_chns() != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 397 | return; |
mahphalke |
17:af1f2416dd26 | 398 | } |
mahphalke |
17:af1f2416dd26 | 399 | } |
mahphalke |
17:af1f2416dd26 | 400 | |
mahphalke |
17:af1f2416dd26 | 401 | /* Enable/Disable channels based on channel mask set in the IIO client */ |
mahphalke |
17:af1f2416dd26 | 402 | for (uint8_t chn = 0; chn < num_of_chns; chn++) { |
mahphalke |
17:af1f2416dd26 | 403 | if (ch_mask & mask) { |
mahphalke |
17:af1f2416dd26 | 404 | if (data_capture_ops.enable_curr_chn) { |
mahphalke |
17:af1f2416dd26 | 405 | /* Enable the selected channel */ |
mahphalke |
17:af1f2416dd26 | 406 | if (data_capture_ops.enable_curr_chn(chn) != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 407 | return; |
mahphalke |
17:af1f2416dd26 | 408 | } |
mahphalke |
17:af1f2416dd26 | 409 | } |
mahphalke |
17:af1f2416dd26 | 410 | |
mahphalke |
17:af1f2416dd26 | 411 | num_of_active_channels++; |
mahphalke |
17:af1f2416dd26 | 412 | } else { |
mahphalke |
17:af1f2416dd26 | 413 | if (data_capture_ops.disable_curr_chn) { |
mahphalke |
17:af1f2416dd26 | 414 | /* Disable the selected channel */ |
mahphalke |
17:af1f2416dd26 | 415 | if (data_capture_ops.disable_curr_chn(chn) != SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 416 | return; |
mahphalke |
17:af1f2416dd26 | 417 | } |
mahphalke |
17:af1f2416dd26 | 418 | } |
mahphalke |
17:af1f2416dd26 | 419 | } |
mahphalke |
17:af1f2416dd26 | 420 | |
mahphalke |
17:af1f2416dd26 | 421 | mask <<= 1; |
mahphalke |
17:af1f2416dd26 | 422 | } |
mahphalke |
17:af1f2416dd26 | 423 | |
mahphalke |
17:af1f2416dd26 | 424 | /* Make primary acquisition buffer available and start continuous conversion */ |
mahphalke |
17:af1f2416dd26 | 425 | acq_buffer.state = BUF_AVAILABLE; |
mahphalke |
17:af1f2416dd26 | 426 | if (data_capture_ops.enable_continuous_read_conversion(ch_mask) == SUCCESS) { |
mahphalke |
17:af1f2416dd26 | 427 | start_adc_data_capture = true; |
mahphalke |
17:af1f2416dd26 | 428 | } else { |
mahphalke |
17:af1f2416dd26 | 429 | start_adc_data_capture = false; |
mahphalke |
17:af1f2416dd26 | 430 | } |
mahphalke |
17:af1f2416dd26 | 431 | } |
mahphalke |
17:af1f2416dd26 | 432 | |
mahphalke |
17:af1f2416dd26 | 433 | |
mahphalke |
17:af1f2416dd26 | 434 | /*! |
mahphalke |
17:af1f2416dd26 | 435 | * @brief Function to stop ADC data capture |
mahphalke |
17:af1f2416dd26 | 436 | * @return none |
mahphalke |
17:af1f2416dd26 | 437 | */ |
mahphalke |
17:af1f2416dd26 | 438 | void stop_data_capture(void) |
mahphalke |
17:af1f2416dd26 | 439 | { |
mahphalke |
17:af1f2416dd26 | 440 | start_adc_data_capture = false; |
mahphalke |
17:af1f2416dd26 | 441 | |
mahphalke |
17:af1f2416dd26 | 442 | if (data_capture_ops.disable_conversion) { |
mahphalke |
17:af1f2416dd26 | 443 | /* Stop conversion */ |
mahphalke |
17:af1f2416dd26 | 444 | data_capture_ops.disable_conversion(); |
mahphalke |
17:af1f2416dd26 | 445 | } |
mahphalke |
17:af1f2416dd26 | 446 | |
mahphalke |
17:af1f2416dd26 | 447 | if (data_capture_ops.restore_prev_active_chns) { |
mahphalke |
17:af1f2416dd26 | 448 | /* Enabled all previously active channels (active during conversion start) */ |
mahphalke |
17:af1f2416dd26 | 449 | data_capture_ops.restore_prev_active_chns(); |
mahphalke |
17:af1f2416dd26 | 450 | } |
mahphalke |
17:af1f2416dd26 | 451 | |
mahphalke |
17:af1f2416dd26 | 452 | reset_data_capture(); |
mahphalke |
17:af1f2416dd26 | 453 | } |