Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: sdp_k1_sdram
Diff: app/ad7689_data_capture.c
- Revision:
- 2:007533849deb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/app/ad7689_data_capture.c Thu Jul 21 16:45:24 2022 +0530
@@ -0,0 +1,704 @@
+/***************************************************************************//**
+ * @file ad7689_data_capture.c
+ * @brief Data capture interface for AD7689 IIO application
+ * @details This module handles the AD7689 data capturing for IIO client
+********************************************************************************
+ * Copyright (c) 2021-22 Analog Devices, Inc.
+ * All rights reserved.
+ *
+ * This software is proprietary to Analog Devices, Inc. and its licensors.
+ * By using this software you agree to the terms of the associated
+ * Analog Devices Software License Agreement.
+*******************************************************************************/
+
+/******************************************************************************/
+/***************************** Include Files **********************************/
+/******************************************************************************/
+#include <string.h>
+
+#include "ad7689_data_capture.h"
+#include "app_config.h"
+#include "ad7689_iio.h"
+#include "ad7689_user_config.h"
+#include "no_os_delay.h"
+#include "no_os_spi.h"
+#include "no_os_util.h"
+#include "no_os_gpio.h"
+#include "no_os_error.h"
+
+/******************************************************************************/
+/********************** Macros and Constants Definition ***********************/
+/******************************************************************************/
+
+/* Timeout count to avoid stuck into potential infinite loop while checking
+ * for new data into an acquisition buffer. The actual timeout factor is determined
+ * through 'sampling_frequency' attribute of IIO app, but this period here makes sure
+ * we are not stuck into a forever loop in case data capture is interrupted
+ * or failed in between.
+ * Note: This timeout factor is dependent upon the MCU clock frequency. Below timeout
+ * is tested for SDP-K1 platform @180Mhz default core clock */
+#define BUF_READ_TIMEOUT 0xffffffff
+
+#define BYTE_SIZE 8
+
+/* Value indicating end of channels from active channels list */
+#define END_OF_CHN 0xff
+
+/* Config register bit positions */
+#define CONFIG_OVERRIDE_BIT_POS 13
+#define CHN_CONFIG_SELECT_BIT_POS 10
+#define CHN_SELECT_BIT_POS 7
+#define REF_SRC_SELECT_BIT_POS 3
+
+/******************************************************************************/
+/********************** Variables and User Defined Data Types *****************/
+/******************************************************************************/
+
+/* ADC data buffer */
+#if !defined(USE_SDRAM_CAPTURE_BUFFER)
+int8_t adc_data_buffer[DATA_BUFFER_SIZE] = { 0 };
+#endif
+
+/*
+ *@enum acq_buffer_state_e
+ *@details Enum holding the data acquisition buffer states
+ **/
+typedef enum {
+ BUF_AVAILABLE,
+ BUF_EMPTY,
+ BUF_FULL
+} acq_buffer_state_e;
+
+/*
+ *@struct acq_buf_t
+ *@details Structure holding the data acquisition buffer parameters
+ **/
+typedef struct {
+ acq_buffer_state_e state; // Buffer state
+ uint32_t wr_indx; // Buffer write index (incremented per sample read)
+ uint32_t rd_indx; // Buffer read index (incremented per sample read)
+ int8_t *wr_pdata; // Data buffer write pointer
+ int8_t *rd_pdata; // Data buffer read pointer
+ bool reindex_buffer; // Reindex buffer to 0th channel
+} acq_buf_t;
+
+/* ADC data acquisition buffers */
+static volatile acq_buf_t acq_buffer;
+
+/* Flag to indicate data capture status */
+static volatile bool start_cont_data_capture = false;
+
+/* Count to track number of actual samples requested by IIO client */
+static volatile uint32_t num_of_requested_samples = 0;
+
+/* ADC sample/raw data size in bytes */
+static volatile uint8_t sample_size_in_bytes;
+
+/* Max available buffer size (after considering the data alignment with IIO buffer) */
+static volatile uint32_t max_buffer_sz;
+
+/* List of input channels to be captured */
+static volatile uint8_t input_channels[ADC_CHN_COUNT];
+
+/* Number of active channels */
+static volatile uint8_t num_of_active_channels;
+
+/* Current active channel index */
+static volatile uint8_t chn_indx;
+
+/* Active channels list */
+static uint8_t active_chns[ADC_CHN_COUNT + 1];
+
+/* Index to next channel from active channels list */
+static uint8_t next_chn_indx;
+
+static uint8_t first_active_chn;
+static uint8_t second_active_chn;
+
+/******************************************************************************/
+/************************ Functions Declarations ******************************/
+/******************************************************************************/
+
+/******************************************************************************/
+/************************ Functions Definitions *******************************/
+/******************************************************************************/
+
+/*!
+ * @brief Read the single ADC sample (raw data) for input channel
+ * @param input_chn[in] - Input channel to be sampled and read data for
+ * @param raw_data[in, out]- ADC raw data
+ * @return 0 in case of success, negative error code otherwise
+ */
+int32_t read_single_sample(uint8_t input_chn, uint32_t *raw_data)
+{
+ uint16_t adc_raw = 0;
+ int32_t ret;
+
+ /* Configure 1st channel (n) for acquisition, data is read for (n-2) channel
+ * (undefined conversion result) */
+ if (input_chn == TEMPERATURE_CHN) {
+ ad7689_current_config.inx = input_chn;
+ ad7689_current_config.incc = AD7689_TEMPERATURE_SENSOR;
+ ad7689_current_config.ref = AD7689_REF_INTERNAL_4p096V;
+ } else {
+ ad7689_current_config.inx = input_chn;
+ ad7689_current_config.incc = ADC_INPUT_TYPE_CFG;
+ ad7689_current_config.ref = ADC_REF_VOLTAGE_CFG;
+ }
+
+ ret = ad7689_write_config(p_ad7689_dev_inst, &ad7689_current_config);
+ if (ret) {
+ return ret;
+ }
+
+ /* Previous conversion wait delay */
+ no_os_udelay(10);
+
+ /* Configure 2nd channel (n+1) for acquisition, data is read for (n-1) channel */
+ if (input_chn == TEMPERATURE_CHN) {
+ /* Load the inx bit to a next valid channel */
+ ad7689_current_config.inx = input_chn;
+ ad7689_current_config.incc = AD7689_TEMPERATURE_SENSOR;
+ ad7689_current_config.ref = AD7689_REF_INTERNAL_4p096V;
+ } else {
+ ad7689_current_config.inx = input_chn;
+ ad7689_current_config.incc = ADC_INPUT_TYPE_CFG;
+ ad7689_current_config.ref = ADC_REF_VOLTAGE_CFG;
+ }
+
+ ret = ad7689_write_config(p_ad7689_dev_inst, &ad7689_current_config);
+ if (ret) {
+ return ret;
+ }
+
+ /* Previous conversion wait delay */
+ no_os_udelay(10);
+
+ /* The acquisition for channel (n) started from
+ * 'ad7689_enable_single_read_conversion' function. Data for that channel
+ * is available here (after 2 dummy reads).
+ **/
+ ret = ad7689_read(p_ad7689_dev_inst, &adc_raw, 1);
+ if (ret) {
+ return ret;
+ }
+
+ *raw_data = adc_raw;
+
+ return 0;
+}
+
+/*!
+ * @brief Read ADC raw data for recently sampled channel
+ * @param adc_data[out] - Pointer to adc data read variable
+ * @param input_chn[in] - Input channel
+ * @return 0 in case of success, negative error code otherwise
+ * @note This function is intended to call from the conversion end trigger
+ * event. Therefore, this function should just read raw ADC data
+ * without further monitoring conversion end event
+ */
+static int32_t adc_read_converted_sample(uint32_t *adc_data,
+ uint8_t input_chn)
+{
+ uint16_t adc_raw;
+ uint16_t config_reg;
+ uint8_t next_chn;
+ uint8_t buf[2] = { 0, 0 };
+ int32_t ret;
+
+ if (!adc_data) {
+ return -EINVAL;
+ }
+
+ /* The acquisition for 1st (n) and 2nd (n+1) active channels is started from
+ * 'ad7689_enable_continuous_read_conversion' function. When chn_indx = 0,
+ * (i.e. first entry to this function), the converion result for 1st active
+ * channel (n) is read and is returned back. The next channel to be set for
+ * acquisition therefore must be (n+2). This is done by adding +2 offset in
+ * channel index recursively.
+ **/
+ if (active_chns[next_chn_indx] == END_OF_CHN) {
+ next_chn_indx = 0;
+ }
+ next_chn = active_chns[next_chn_indx++];
+
+ /* Form the config register with new channel configuration */
+ config_reg = (1 << CONFIG_OVERRIDE_BIT_POS);
+ config_reg |= (next_chn << CHN_SELECT_BIT_POS);
+ if (next_chn == TEMPERATURE_CHN) {
+ config_reg |= ((AD7689_TEMPERATURE_SENSOR << CHN_CONFIG_SELECT_BIT_POS) |
+ (AD7689_REF_INTERNAL_4p096V
+ << REF_SRC_SELECT_BIT_POS));
+ } else {
+ config_reg |= ((ad7689_current_config.incc << CHN_CONFIG_SELECT_BIT_POS) |
+ (ad7689_current_config.ref
+ << REF_SRC_SELECT_BIT_POS));
+ }
+
+ /* Config word must to be sent during first 14 (MSBbits) clocks, therefore left
+ * shifted by 2 */
+ config_reg <<= 2;
+
+ buf[0] = config_reg >> BYTE_SIZE;
+ buf[1] = config_reg;
+
+ /* Read the conversion result */
+ ret = no_os_spi_write_and_read(p_ad7689_dev_inst->spi_desc,
+ buf,
+ sizeof(buf));
+ if (ret) {
+ return ret;
+ }
+
+ /* Extract the data */
+ adc_raw = ((uint16_t)buf[0] << BYTE_SIZE) | buf[1];
+#if (ADC_RESOLUTION == 14)
+ adc_raw >>= 2;
+#endif
+
+ *adc_data = adc_raw;
+ return 0;
+}
+
+/*!
+ * @brief Reset the data capture specific variables
+ * @return none
+ */
+static void reset_data_capture(void)
+{
+ /* Reset data capture flags */
+ start_cont_data_capture = false;
+ num_of_active_channels = 0;
+ chn_indx = 0;
+
+ /* Reset acquisition buffer states and clear old data */
+ acq_buffer.state = BUF_EMPTY;
+ acq_buffer.wr_indx = 0;
+ acq_buffer.rd_indx = 0;
+ acq_buffer.reindex_buffer = false;
+
+ acq_buffer.wr_pdata = adc_data_buffer;
+ acq_buffer.rd_pdata = adc_data_buffer;
+
+ max_buffer_sz = DATA_BUFFER_SIZE;
+}
+
+/*!
+ * @brief Store the list of all previously enabled channels and enable
+ * new channels set in the channel mask argument
+ * @param chn_mask[in] - Active channels list
+ * @return 0 in case of success, negative error code otherwise
+ */
+static int32_t adc_store_active_chns(uint32_t chn_mask)
+{
+ uint8_t chn;
+ uint8_t indx = 0;
+
+ /* Get the list of active channels */
+ for (chn = 0; chn < ADC_CHN_COUNT; chn++) {
+ if (chn_mask & 0x1) {
+ if (indx == 0) {
+ /* Get the n channel */
+ first_active_chn = chn;
+ } else if (indx == 1) {
+ /* Get the n+1 channel */
+ second_active_chn = chn;
+ } else {
+ /* Store the list of n+2 and onward channels */
+ active_chns[indx - 2] = chn;
+ }
+ indx++;
+ }
+ chn_mask >>= 1;
+ }
+
+ if (indx >= 2) {
+ active_chns[indx - 2] = first_active_chn;
+ active_chns[indx - 1] = second_active_chn;
+ } else {
+ active_chns[0] = first_active_chn;
+ }
+
+ next_chn_indx = 0;
+ active_chns[indx] = END_OF_CHN; // end of channel list
+
+ return 0;
+}
+
+/*!
+ * @brief Trigger a data capture in continuous/burst mode
+ * @return 0 in case of success, negative error code otherwise
+ */
+static int32_t adc_start_data_capture(void)
+{
+ int32_t ret;
+
+ /* From power-up, in any read/write mode, the first three conversion results are
+ * undefined because a valid CFG does not take place until the second EOC;
+ * therefore, two dummy conversions are required
+ **/
+
+ /* Configure 1st channel (n) for acquisition, data is read for (n-2) channel
+ * (undefined conversion reult) */
+ ad7689_current_config.inx = first_active_chn;
+ ret = ad7689_write_config(p_ad7689_dev_inst, &ad7689_current_config);
+ if (ret) {
+ return ret;
+ }
+
+ /* Previous conversion wait delay */
+ no_os_udelay(10);
+
+ if (num_of_active_channels > 1) {
+ /* Configure 2nd channel (n+1) for acquisition, data is read for (n-1) channel */
+ ad7689_current_config.inx = second_active_chn;
+ ret = ad7689_write_config(p_ad7689_dev_inst, &ad7689_current_config);
+ if (ret) {
+ return ret;
+ }
+
+ /* Previous conversion wait delay */
+ no_os_udelay(10);
+ }
+
+ return 0;
+}
+
+/*!
+ * @brief Function to prepare the data ADC capture for new READBUFF
+ * request from IIO client (for active channels)
+ * @param chn_mask[in] - Channels to enable for data capturing
+ * @param num_of_chns[in] - ADC channel count
+ * @param sample_size[in] - Sample size in bytes
+ * @return 0 in case of success, negative error code otherwise
+ */
+int32_t prepare_data_transfer(uint32_t chn_mask,
+ uint8_t num_of_chns,
+ uint8_t sample_size)
+{
+ int32_t ret;
+ uint32_t mask = 0x1;
+ uint8_t index = 0;
+
+ /* Reset data capture module specific flags and variables */
+ reset_data_capture();
+
+ sample_size_in_bytes = sample_size;
+
+ /* Get the active channels count based on the channel mask set in an IIO
+ * client application (channel mask starts from bit 0) */
+ for (uint8_t chn = 0; chn < num_of_chns; chn++) {
+ if (chn_mask & mask) {
+ input_channels[index++] = chn;
+ num_of_active_channels++;
+ }
+
+ mask <<= 1;
+ }
+
+ /* Store active channels */
+ ret = adc_store_active_chns(chn_mask);
+ if (ret) {
+ return ret;
+ }
+
+#if (DATA_CAPTURE_MODE == CONTINUOUS_DATA_CAPTURE)
+ /* Trigger continuous data capture */
+ ret = adc_start_data_capture();
+ if (ret) {
+ return ret;
+ }
+
+ acq_buffer.state = BUF_AVAILABLE;
+ start_cont_data_capture = true;
+#endif
+
+ return 0;
+}
+
+/*!
+ * @brief Function to stop data capture
+ * @return 0 in case of success, negative error code otherwise
+ */
+int32_t end_data_transfer(void)
+{
+ start_cont_data_capture = false;
+
+ /* Reset data capture module specific flags and variables */
+ reset_data_capture();
+
+ return 0;
+}
+
+/*!
+ * @brief Perform buffer read operations to read requested samples
+ * @param nb_of_samples[in] - Requested number of samples to read
+ * @return 0 in case of success, negative error code otherwise
+ */
+static int32_t buffer_read_operations(uint32_t nb_of_samples)
+{
+ uint32_t timeout = BUF_READ_TIMEOUT;
+ int32_t offset;
+
+ /* Wait until requested samples are available in the buffer to read */
+ do {
+ if (acq_buffer.wr_indx >= acq_buffer.rd_indx) {
+ offset = acq_buffer.wr_indx - acq_buffer.rd_indx;
+ } else {
+ offset = max_buffer_sz + (acq_buffer.wr_indx - acq_buffer.rd_indx);
+ }
+
+ timeout--;
+ } while ((offset < (int32_t)(nb_of_samples)) && (timeout > 0));
+
+ if (timeout == 0) {
+ /* This returns the empty buffer */
+ return -EIO;
+ }
+
+ if (acq_buffer.rd_indx >= max_buffer_sz) {
+ acq_buffer.rd_indx = 0;
+ }
+
+ return 0;
+}
+
+/*!
+ * @brief Perform buffer write operations such as buffer full or empty
+ * check, resetting buffer index and pointers, etc
+ * @return none
+ */
+static void buffer_write_operations(void)
+{
+ acq_buffer.wr_indx++;
+
+ /* Perform buffer full check and operations */
+ if (acq_buffer.wr_indx >= max_buffer_sz) {
+ if ((acq_buffer.rd_indx >= num_of_requested_samples)
+ && (acq_buffer.rd_indx != 0)) {
+ /* Reset buffer write index and write pointer when enough
+ * space available in the buffer to wrap to start */
+ acq_buffer.wr_indx = 0;
+
+ acq_buffer.wr_pdata = adc_data_buffer;
+ if (acq_buffer.rd_indx >= max_buffer_sz) {
+ /* Wrap the read index and read pointer to start of buffer
+ * if buffer is completely read/emptied */
+ acq_buffer.rd_indx = 0;
+ acq_buffer.rd_pdata = adc_data_buffer;
+ }
+
+ acq_buffer.state = BUF_AVAILABLE;
+ } else {
+ /* Wait until enough space available to wrap buffer write index
+ * at the start of buffer */
+ acq_buffer.wr_indx = max_buffer_sz;
+ acq_buffer.state = BUF_FULL;
+ acq_buffer.reindex_buffer = true;
+ }
+ }
+}
+
+/*!
+ * @brief This is an ISR (Interrupt Service Routine) to monitor end of conversion event.
+ * @param ctx[in] - Callback context (unused)
+ * @return none
+ * @details This is an Interrupt callback function/ISR invoked in synchronous/asynchronous
+ * manner depending upon the application implementation. The conversion results
+ * are read into acquisition buffer and control continue to sample next channel.
+ * This continues until conversion is stopped (through IIO client command)
+ */
+void data_capture_callback(void *ctx)
+{
+ uint32_t adc_sample;
+ volatile uint8_t *wr_addr;
+
+ if (start_cont_data_capture == true) {
+ /* Read the sample for channel which has been sampled recently */
+ if (!adc_read_converted_sample(&adc_sample,
+ input_channels[chn_indx])) {
+ do {
+ if (acq_buffer.state == BUF_AVAILABLE) {
+ if (acq_buffer.reindex_buffer) {
+ /* Buffer refilling must start with first active channel data
+ * for IIO client to synchronize the buffered data */
+ if (chn_indx != 0) {
+ break;
+ }
+ acq_buffer.reindex_buffer = false;
+ }
+
+ /* Copy adc samples into acquisition buffer to transport over
+ * communication link */
+ wr_addr = (volatile uint8_t *)(acq_buffer.wr_pdata + (acq_buffer.wr_indx *
+ sample_size_in_bytes));
+ memcpy((uint8_t *)wr_addr, &adc_sample, sample_size_in_bytes);
+ }
+
+ /* Perform buffer write operations */
+ buffer_write_operations();
+ } while (0);
+
+ /* Track the count for recently sampled channel */
+ chn_indx++;
+ if (chn_indx >= num_of_active_channels) {
+ chn_indx = 0;
+ }
+ }
+ }
+}
+
+/*!
+ * @brief Capture requested number of ADC samples in burst mode
+ * @param pbuf[out] - Pointer to ADC data buffer
+ * @param nb_of_samples[in] - Number of samples to be read
+ * @return 0 in case of success, negative error code otherwise
+ */
+static int32_t read_burst_data(int8_t *pbuf, uint32_t nb_of_samples)
+{
+ int32_t ret;
+ uint32_t sample_indx = 0;
+ uint8_t next_chn_indx = 0;
+ uint16_t config_reg;
+ uint16_t adc_raw;
+ uint8_t next_chn;
+ uint8_t buf[2] = { 0, 0 };
+
+ ret = adc_start_data_capture();
+ if (ret) {
+ return ret;
+ }
+
+ while (sample_indx < nb_of_samples) {
+ if (active_chns[next_chn_indx] == END_OF_CHN) {
+ next_chn_indx = 0;
+ }
+ next_chn = active_chns[next_chn_indx++];
+
+ /* Form the config register with new channel configuration */
+ config_reg = (1 << CONFIG_OVERRIDE_BIT_POS);
+ config_reg |= (next_chn << CHN_SELECT_BIT_POS);
+ if (next_chn == TEMPERATURE_CHN) {
+ config_reg |= ((AD7689_TEMPERATURE_SENSOR << CHN_CONFIG_SELECT_BIT_POS) |
+ (AD7689_REF_INTERNAL_4p096V
+ << REF_SRC_SELECT_BIT_POS));
+ } else {
+ config_reg |= ((ad7689_current_config.incc << CHN_CONFIG_SELECT_BIT_POS) |
+ (ad7689_current_config.ref
+ << REF_SRC_SELECT_BIT_POS));
+ }
+
+ /* Config word must to be sent during first 14 (MSBbits) clocks, therefore left
+ * shifted by 2 */
+ config_reg <<= 2;
+
+ buf[0] = config_reg >> BYTE_SIZE;
+ buf[1] = config_reg;
+
+ /* Read the conversion result */
+ ret = no_os_spi_write_and_read(p_ad7689_dev_inst->spi_desc,
+ buf,
+ sizeof(buf));
+ if (ret) {
+ return ret;
+ }
+
+ /* Extract the data */
+ adc_raw = ((uint16_t)buf[0] << BYTE_SIZE) | buf[1];
+#if (ADC_RESOLUTION == 14)
+ adc_raw >>= 2;
+#endif
+
+ memcpy((uint8_t *)pbuf, &adc_raw, sample_size_in_bytes);
+ pbuf += sample_size_in_bytes;
+
+ /* Conversion delay = Acquisition time + Data read time
+ * Conv time = 4usec (min), Read time = ~2.1usec (@22.5Mhz SPI clock)
+ * Acq Time (req) = 4usec - 2.1usec = 1.9usec.
+ * Due to inaccuracy and overhead in the udelay() function,
+ * 1usec delay typically results into ~2.5usec time on SDP-K1 Mbed board.
+ * This delay is very critical in the conversion and may change
+ * from compiler to compiler and hardware to hardware. */
+ if (next_chn == TEMPERATURE_CHN) {
+ no_os_udelay(5);
+ } else {
+ no_os_udelay(1);
+ }
+
+ sample_indx++;
+ }
+
+ return 0;
+}
+
+/*!
+ * @brief Read requested number of ADC samples in continuous mode
+ * @param pbuf[in] - Pointer to data buffer
+ * @param nb_of_samples[in] - Number of samples to read
+ * @return 0 in case of success, negative error code otherwise
+ * @note The actual sample capturing happens through interrupt. This
+ * function tracks the buffer read pointer to read block of data
+ */
+static int32_t read_continuous_conv_data(int8_t **pbuf, uint32_t nb_of_samples)
+{
+ volatile int8_t *rd_addr;
+ int32_t ret;
+
+ /* Determine the max available buffer size based on the requested
+ * samples count and actual avilable buffer size. Buffer should be
+ * capable of holding all requested 'n' samples from previous write
+ * index upto to the end of buffer, as data is read linearly
+ * from adc buffer in IIO library.
+ * E.g. If actual buffer size is 2048 samples and requested samples
+ * are 1600, max available buffer size is actually 1600. So in given
+ * iteration, only 1600 samples will be stored into buffer and after
+ * that buffer indexes will be wrapped to a start of buffer. If index
+ * is not wrapped, the next 1600 requested samples won't accomodate into
+ * remaining 448 samples space. As buffer is read in linear fashion, the
+ * read index can't be wrapped to start of buffer to read remaining samples.
+ * So max available space in this case is 2048 but only utilized space
+ * will be 1600 in single read buffer request from IIO client.
+ **/
+ max_buffer_sz = ((DATA_BUFFER_SIZE / sample_size_in_bytes) /
+ nb_of_samples) * nb_of_samples;
+
+ ret = buffer_read_operations(nb_of_samples);
+ if (ret) {
+ return ret;
+ }
+
+ /* Get the next read address */
+ rd_addr = (volatile int8_t *)(acq_buffer.rd_pdata + (acq_buffer.rd_indx *
+ sample_size_in_bytes));
+ acq_buffer.rd_indx += nb_of_samples;
+
+ /* Update the IIO buffer pointer to point to next read start location */
+ *pbuf = rd_addr;
+
+ return 0;
+}
+
+/*!
+ * @brief Function to read the ADC buffered raw data requested
+ * by IIO client
+ * @param pbuf[in] - Pointer to data buffer
+ * @param nb_of_bytes[in] - Number of bytes to read
+ * @return 0 in case of success, negative error code otherwise
+ */
+int32_t read_buffered_data(int8_t **pbuf, uint32_t nb_of_bytes)
+{
+ int32_t ret;
+ num_of_requested_samples = nb_of_bytes / sample_size_in_bytes;
+
+#if (DATA_CAPTURE_MODE == BURST_DATA_CAPTURE)
+ ret = read_burst_data(*pbuf, num_of_requested_samples);
+#else
+ ret = read_continuous_conv_data(pbuf, num_of_requested_samples);
+#endif
+
+ if (ret) {
+ return ret;
+ }
+
+ return 0;
+}