Example Program for EVAL-AD7606

Dependencies:   platform_drivers

Files at this revision

API Documentation at this revision

Comitter:
Kjansen
Date:
Tue Aug 03 11:54:49 2021 +0100
Parent:
6:32de160dce43
Commit message:
Modified the ADC data capture module to remove dependancy on type of ADC and it's specific operations

Changed in this revision

app/.mbedignore Show annotated file Show diff for this revision Revisions of this file
app/ad7606_data_capture.c Show annotated file Show diff for this revision Revisions of this file
app/ad7606_data_capture.h Show annotated file Show diff for this revision Revisions of this file
app/app_config.c Show annotated file Show diff for this revision Revisions of this file
app/iio_ad7606.c Show annotated file Show diff for this revision Revisions of this file
app/iio_ad7606.h Show annotated file Show diff for this revision Revisions of this file
app/mbed_platform_drivers.lib Show annotated file Show diff for this revision Revisions of this file
diff -r 32de160dce43 -r 054dbd5e1f45 app/.mbedignore
--- a/app/.mbedignore	Wed Jul 21 11:16:56 2021 +0100
+++ b/app/.mbedignore	Tue Aug 03 11:54:49 2021 +0100
@@ -57,6 +57,4 @@
 no-OS/tools/
 no-OS/v4l2_config/
 libtinyiiod/ci/
-libtinyiiod/example.c
-mbed_platform_drivers/adc_data_capture.c
-mbed_platform_drivers/adc_data_capture.h
\ No newline at end of file
+libtinyiiod/example.c
\ No newline at end of file
diff -r 32de160dce43 -r 054dbd5e1f45 app/ad7606_data_capture.c
--- a/app/ad7606_data_capture.c	Wed Jul 21 11:16:56 2021 +0100
+++ b/app/ad7606_data_capture.c	Tue Aug 03 11:54:49 2021 +0100
@@ -3,8 +3,7 @@
  *   @brief   Data capture interface for AD7606 IIO application
  *   @details This module handles the AD7606 data capturing
 ********************************************************************************
- * Copyright (c) 2020 Analog Devices, Inc.
- *
+ * Copyright (c) 2020-2021 Analog Devices, Inc.
  * All rights reserved.
  *
  * This software is proprietary to Analog Devices, Inc. and its licensors.
@@ -21,135 +20,88 @@
 
 #include "app_config.h"
 #include "ad7606_data_capture.h"
+#include "iio_ad7606.h"
 #include "ad7606_support.h"
-#include "gpio_extra.h"
+#include "error.h"
+#include "adc_data_capture.h"
 
 /******************************************************************************/
 /********************** Macros and Constants Definition ***********************/
 /******************************************************************************/
 
-#if (AD7606X_ADC_RESOLUTION > 16)
-#define		BYTES_PER_SAMPLE	sizeof(uint32_t)
+#if (AD7606X_ADC_RESOLUTION == 18)
+#define	SAMPLE_SIZE_IN_BYTE		3
 #else
-#define		BYTES_PER_SAMPLE	sizeof(uint16_t)
+#define	SAMPLE_SIZE_IN_BYTE		2
 #endif
 
-/* Max size of the acquisition buffer (in terms of samples) */
-#define DATA_BUFFER_SIZE		(8192)
-
-/* 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, but this period here makes sure
- * we are not stuck into a loop forever, in case data capture interrupted
- * or failed in between */
-#define BUF_READ_TIMEOUT	(5000000)
-
 /******************************************************************************/
 /********************** Variables and User Defined Data Types *****************/
 /******************************************************************************/
 
-/* Device instance for background adc conversion callback */
-static volatile struct ad7606_dev *dev = NULL;
-
-/*
- *@enum		acq_buffer_state_e
- *@details	Enum holding the data acquisition buffer states
- **/
-typedef enum {
-	BUF_EMPTY,
-	BUF_AVAILABLE,
-	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 rd_indx;			// buffer read index
-	uint32_t wr_indx;			// buffer write index
-	uint32_t align_cnt;			// buffer alignment counter
-#if (AD7606X_ADC_RESOLUTION > 16)
-	uint32_t data[DATA_BUFFER_SIZE];
-#else
-	uint16_t data[DATA_BUFFER_SIZE];
-#endif
-} acq_buf_t;
-
-/* ADC data acquisition buffers */
-static volatile acq_buf_t acq_buffer;
-
-/* Flag to indicate background data capture status */
-static volatile bool start_adc_data_capture = false;
-
-/* Active channels to be captured */
-static volatile uint32_t active_channels = 0;
-
-/* Number of active channels */
-static volatile uint8_t num_of_active_channels = 0;
-
-/* Minimum number of bytes to be read from device over digital interface */
-static volatile uint8_t min_bytes_to_read = 0;
-
-/* Number of channels requested for read into acquisition buffer */
-static volatile uint8_t chn_read_cnt = 0;
-
-/* Number of samples requested by IIO client */
-static volatile uint16_t num_of_samples = 0;
-
-/* Max available size of buffer */
-static volatile uint16_t max_available_buffer_size = 0;
+/* Polarity of channels */
+static polarity_e polarity[AD7606X_ADC_CHANNELS];
 
 /******************************************************************************/
 /************************ Functions Declarations ******************************/
 /******************************************************************************/
 
-static void adjust_buffer_offset(uint8_t *arr_indx, uint8_t *offset_end,
-				 uint8_t *mask);
+/* Perform conversion on input channel and read single conversion sample */
+static int32_t ad7606_perform_conv_and_read_sample(uint32_t *adc_data,
+		uint8_t chn);
+
+/* Perform continuous sample read pre-operations */
+static int32_t ad7606_continuous_sample_read_start_ops(uint32_t ch_mask);
+
+/* Read ADC sampled/conversion data */
+static int32_t ad7606_read_converted_sample(uint32_t *adc_data,
+		uint8_t input_chn);
+
+/* Trigger next ADC conversion */
+static int32_t ad7606_trigger_next_conversion(void);
+
+/* Define the variable for data_capture_ops structure */
+struct data_capture_ops data_capture_ops = {
+	/* Point AD7606 data capture functions to generic ADC data capture functions */
+	.single_sample_read_start_ops = NULL,
+	.perform_conv_and_read_sample = ad7606_perform_conv_and_read_sample,
+	.single_sample_read_stop_ops = NULL,
+	.continuous_sample_read_start_ops = ad7606_continuous_sample_read_start_ops,
+	.read_converted_sample = ad7606_read_converted_sample,
+	.continuous_sample_read_stop_ops = NULL,
+	.trigger_next_conversion = ad7606_trigger_next_conversion
+};
 
 /******************************************************************************/
 /************************ Functions Definitions *******************************/
 /******************************************************************************/
 
 /*!
- * @brief	Function to init the data capture for AD7606 device
- * @param	device[in]- Device instance
- * @return	none
- */
-int32_t iio_data_capture_init(struct ad7606_dev **device)
-{
-	dev = *device;
-	return SUCCESS;
-}
-
-
-/*!
- * @brief	Function to read the ADC raw data for single channel
- * @param	device[in]- Device instance
- * @param	chn[in] - Input channel
- * @return	adc raw data/sample
+ * @brief	Remove the offset from data to change output data format to
+ *			normal or stright  binary representation (needed for IIO client)
+ * @param	adc_raw[out] - Pointer to adc data read variable
+ * @param	bipolar[in] - Channel polarity
+ * @return	SUCCESS in case of success, FAILURE otherwise
  */
-int32_t single_data_read(void *device, uint8_t chn, polarity_e polarity)
+static int32_t reformat_adc_raw_data(uint32_t adc_raw_data, polarity_e polarity)
 {
-	int32_t adc_data = 0;
-	uint32_t adc_raw[AD7606X_ADC_RESOLUTION] = { 0 };
-
-	if (ad7606_read(device, adc_raw) != SUCCESS) {
-		adc_raw[chn] = 0;
-	}
+	int32_t adc_data;
 
+	/* Bipolar ADC Range:  (-FS) <-> 0 <-> (+FS) : 2^(ADC_RES-1) <-> 0 <-> 2^(ADC_RES-1)-1
+	   Unipolar ADC Range: 0 <-> (+FS) : 0 <-> 2^ADC_RES
+	 **/
 	if (polarity == BIPOLAR) {
-		/* Check for negative adc value for bipolar inputs */
-		if (adc_raw[chn] >= ADC_MAX_COUNT_BIPOLAR) {
-			/* Take the 2s complement for the negative counts (>full scale value) */
-			adc_data = ADC_MAX_COUNT_UNIPOLAR - adc_raw[chn];
-			adc_data = 0 - adc_data;
+		/* Data output format is 2's complement for bipolar mode */
+		if (adc_raw_data > ADC_MAX_COUNT_BIPOLAR) {
+			/* Remove the offset from result to convert into negative reading */
+			adc_data = ADC_MAX_COUNT_UNIPOLAR - adc_raw_data;
+			adc_data = -adc_data;
 		} else {
-			adc_data = adc_raw[chn];
+			adc_data = adc_raw_data;
 		}
 	} else {
-		adc_data = adc_raw[chn];
+		/* Data output format is straight binary for unipolar mode */
+		adc_data = adc_raw_data;
 	}
 
 	return adc_data;
@@ -157,270 +109,132 @@
 
 
 /*!
- * @brief	Function to store the number of requested samples from IIO client
- * @param	bytes[in] - Number of bytes corresponding to requested samples
- * @return	none
+ * @brief	Perform conversion and read conversion sample
+ * @param	adc_data[out] - Pointer to adc data read variable
+ * @param	chn[in] - Channel for which data is to read
+ * @return	SUCCESS in case of success, FAILURE otherwise
  */
-void store_requested_samples_count(size_t bytes)
+int32_t ad7606_perform_conv_and_read_sample(uint32_t *adc_data, uint8_t chn)
 {
-	/* This gets the number of samples requested by IIO client for all active channels */
-	num_of_samples = bytes / BYTES_PER_SAMPLE;
-
-	/* Get the actual available size of buffer by aligning with number of requested samples.
-	 * e.g. if requested samples are 1050, the max available size of buffer is:
-	 * available size = (8192 / 1050) * 1050 = 7 * 1050 = 7350.
-	 * The max samples to be requested should always be less than half the max size of buffer
-	 * (in this case: 8192 / 2 = 4096).
-	 * */
-	max_available_buffer_size = ((DATA_BUFFER_SIZE / num_of_samples) *
-				     num_of_samples);
-}
-
+	uint32_t adc_raw[AD7606X_ADC_CHANNELS] = { 0 };
+	uint8_t read_val;
+	uint8_t chn_range;
+	polarity_e polarity;
 
-/*!
- * @brief	Function to read new samples into buffer without timeout IIO request
- * @param	input_buffer[in] - Input data acquisition buffer
- * @param	output_buffer[in, out] - Output data buffer
- * @param	samples_to_read[in] - Number of samples to read
- * @return	none
- */
-static void wait_and_read_new_samples(char *output_buffer,
-				      size_t samples_to_read)
-{
-	int32_t buff_rd_wr_indx_offset; 			// Offset b/w buffer read and write indexes
-	uint32_t timeout = BUF_READ_TIMEOUT;   		// Buffer new data read timeout count
-	size_t bytes = samples_to_read * BYTES_PER_SAMPLE;
-
-	/* Copy the bytes into buffer provided there is enough offset b/w read and write counts.
-	* If there is overlap b/w read and write indexes (read is faster than write), empty buffer
-	* should be returned to IIO client to avoid IIO request timeout */
-	do {
-		buff_rd_wr_indx_offset = acq_buffer.wr_indx - acq_buffer.rd_indx;
-		timeout--;
-	} while (((buff_rd_wr_indx_offset < (int32_t)(samples_to_read))
-		  || (acq_buffer.wr_indx < acq_buffer.rd_indx)) && (timeout > 0)
-		 && start_adc_data_capture);
-
-	if ((timeout == 0) || (acq_buffer.wr_indx <= 0)) {
-		/* This returns the empty buffer */
-		return;
+	/* Get input channel range */
+	if (ad7606_spi_reg_read(p_ad7606_dev_inst,
+				AD7606_REG_RANGE_CH_ADDR(chn),
+				&read_val) != SUCCESS) {
+		return FAILURE;
 	}
 
-	memcpy(output_buffer,
-	       (void const *)&acq_buffer.data[acq_buffer.rd_indx],
-	       bytes);
-	acq_buffer.rd_indx += samples_to_read;
-}
-
-
-/*!
- * @brief	Function to read and align the ADC buffered raw data
- * @param	device[in]- Device instance
- * @param	pbuf[out] - Buffer to load ADC raw data
- * @param	bytes[in] - Number of bytes to be read
- * @param	active_chns_mask[in] - Active channels mask
- * @return	Number of bytes read
- */
-size_t buffered_data_read(char *pbuf, size_t bytes, size_t offset,
-			  uint32_t active_chns_mask)
-{
-	size_t samples_to_read = bytes / BYTES_PER_SAMPLE;	// Bytes to sample conversion
-
-	/* Make sure requested samples size is less than ADC buffer size. Return constant
-	 * value to avoid IIO client getting timed-out */
-	if (num_of_samples >= max_available_buffer_size) {
-		memset(pbuf, 1, bytes);
-		return bytes;
+	if (((chn) % 2) != 0) {
+		read_val >>= CHANNEL_RANGE_MSK_OFFSET;
+		chn_range = read_val;
+	} else {
+		chn_range = (read_val & AD7606_RANGE_CH_MSK(chn));
 	}
 
-	wait_and_read_new_samples(pbuf, samples_to_read);
+	/* Get polarity based on input channel range */
+	polarity = ad7606_get_input_polarity(chn_range);
 
-	/* Make buffer available again once read completely */
-	if (acq_buffer.rd_indx >= max_available_buffer_size) {
-		acq_buffer.rd_indx = 0;
-		acq_buffer.wr_indx = 0;
-		acq_buffer.align_cnt = 0;
-		acq_buffer.state = BUF_AVAILABLE;
+	/* This function monitors BUSY line for EOC and read ADC result post that */
+	if (ad7606_read(p_ad7606_dev_inst, adc_raw) != SUCCESS) {
+		adc_raw[chn] = 0;
 	}
 
-	return bytes;
+	*adc_data = reformat_adc_raw_data(adc_raw[chn], polarity);
+
+	return SUCCESS;
 }
 
 
 /*!
- * @brief	Function to perform background ADC conversion and data capture
- * @return	none
- * @details	This is an External Interrupt callback function/ISR, which is tied up to
- *			falling edge trigger of BUSY pin. It is trigered when previous data
- *			conversion is over and BUSY line goes low. Upon trigger, conversion
- *			results are read into acquisition buffer and next conversion is triggered.
- *			This continues until background conversion is stopped.
+ * @brief	Perform the operations required before starting continuous sample read
+ * @param	chn_mask[in] - active channels list received from IIO client
+ * @return	SUCCESS in case of success, FAILURE otherwise
  */
-void do_conversion_callback(void *ctx, uint32_t event, void *extra)
+int32_t ad7606_continuous_sample_read_start_ops(uint32_t chn_mask)
 {
-#if (AD7606X_ADC_RESOLUTION == 18)
-	uint8_t arr_indx = 0;
-	uint8_t offset_end = 2;
-	uint8_t mask = 0xff;
-#else
-	uint8_t mask = 0x01;
-#endif
-
-	if (start_adc_data_capture == true) {
-		/* Read the conversion result for required number of bytes */
-		if (ad7606_read_conversion_data(dev, min_bytes_to_read) == SUCCESS) {
-			/* Extract the data based on the active channels selected in IIO client.
-			 * Note: The extraction of data based on active channel needs
-			 * to be done since its not possible to capture individual
-			 * channel in AD7606 devices */
-			for (uint8_t chn = 0; chn < chn_read_cnt; chn++) {
-				if (active_channels & mask) {
-					if (acq_buffer.state == BUF_AVAILABLE) {
-#if (AD7606X_ADC_RESOLUTION == 18)
-						/* For AD7606C device (18-bit resolution) */
-						acq_buffer.data[acq_buffer.wr_indx++] =
-							(((uint32_t)(dev->data[arr_indx] & mask) << 16) |    			// MSB
-							 ((uint32_t)dev->data[arr_indx + 1] << 8) |
-							 ((uint32_t)(dev->data[arr_indx + 2] >> (8 - offset_end))));   	// LSB
-#else
+	uint8_t read_val;
+	uint8_t chn_range;
 
-						acq_buffer.data[acq_buffer.wr_indx++] =
-							(uint16_t)(((uint16_t)dev->data[chn << 1] << 8) |   // MSB
-								   dev->data[(chn << 1) + 1]);     				// LSB
-#endif
-
-						acq_buffer.align_cnt++;
-
-						/* Monitor primary buffer full state */
-						if (acq_buffer.wr_indx >= max_available_buffer_size) {
-							acq_buffer.state = BUF_FULL;
-
-							/* This aligns the buffer to first active channel once all requested samples are transmitted */
-							if (acq_buffer.align_cnt >= num_of_samples) {
-								acq_buffer.align_cnt = 0;
-							}
-#if (AD7606X_ADC_RESOLUTION == 18)
-							adjust_buffer_offset(&arr_indx, &offset_end, &mask);
-#endif
-							mask <<= 1;
-							continue;
-						}
-
-						/* This aligns the buffer to first active channel once all requested samples are transmitted */
-						if (acq_buffer.align_cnt >= num_of_samples) {
-							acq_buffer.align_cnt = 0;
-							break;
-						}
-					}
-				}
-
-#if (AD7606X_ADC_RESOLUTION == 18)
-				adjust_buffer_offset(&arr_indx, &offset_end, &mask);
-#endif
-
-				mask <<= 1;
+	for (uint8_t chn = 0; chn < AD7606X_ADC_CHANNELS; chn++) {
+		/* Store the channels polarity */
+		if (ad7606_spi_reg_read(p_ad7606_dev_inst,
+					AD7606_REG_RANGE_CH_ADDR(chn),
+					&read_val) == SUCCESS) {
+			if (((chn) % 2) != 0) {
+				read_val >>= CHANNEL_RANGE_MSK_OFFSET;
+				chn_range = read_val;
+			} else {
+				chn_range = (read_val & AD7606_RANGE_CH_MSK(chn));
 			}
 
-			/* Trigger next conversion */
-			if (ad7606_convst(dev) != SUCCESS) {
-				start_adc_data_capture = false;
-			}
-		} else {
-			start_adc_data_capture = false;
+			polarity[chn] = ad7606_get_input_polarity(chn_range);
 		}
 	}
+
+	/* Trigger first conversion */
+	return ad7606_trigger_next_conversion();
 }
 
 
 /*!
- * @brief	Function to trigger bakground ADC conversion for new READBUFF
- *              request from IIO client (for active channels)
- * @return	Conversion start status
+ * @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	SUCCESS in case of success, FAILURE 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
  */
-void start_background_data_capture(uint32_t ch_mask, size_t bytes_count)
+int32_t ad7606_read_converted_sample(uint32_t *adc_data,
+				     uint8_t input_chn)
 {
-	uint8_t mask = 0x1;
-
-	/* Make sure requested samples size is less than ADC buffer size */
-	if (num_of_samples >= max_available_buffer_size)
-		return;
-
-	active_channels = ch_mask;
-
-	stop_background_data_capture();
+	uint32_t adc_raw;
+	uint8_t bytes_to_read;
+	uint8_t buffer_offset;
 
-	/* Find the minimum number of bytes to be read from device during
-	 * background conversion (Reading all bytes/channels adds extra overhead,
-	 * so restrict the minimum reads to whatever is possible).
-	 * Note: This happens only at the start of buffer read request. */
-	for (uint8_t chn = 1, indx = 0; chn <= AD7606X_ADC_CHANNELS; chn++, indx++) {
-		if (ch_mask & mask) {
-			/* 1 sample = 2 or 4 bytes */
-			min_bytes_to_read = chn * BYTES_PER_SAMPLE;
-			if (min_bytes_to_read > AD7606X_ADC_RESOLUTION) {
-				min_bytes_to_read = AD7606X_ADC_RESOLUTION;
-			}
-
-			/* Get the count for number of samples to be stored into acquisition buffer */
-			chn_read_cnt = chn;
-			num_of_active_channels++;
-		}
-
-		mask <<= 1;
+	if (!adc_data) {
+		return FAILURE;
 	}
 
-	/* Make primary acquisition buffer available and start conversion */
-	acq_buffer.state = BUF_AVAILABLE;
-	if (ad7606_convst(dev) == SUCCESS) {
-		start_adc_data_capture = true;
-	} else {
-		start_adc_data_capture = false;
-	}
+	/* Get number of bytes to read count = chn_cnt * bytes per sample */
+	bytes_to_read = AD7606X_ADC_CHANNELS * SAMPLE_SIZE_IN_BYTE;
+	buffer_offset = input_chn * SAMPLE_SIZE_IN_BYTE;
+
+	/* Read data over spi interface for all ADC channels */
+	memset(p_ad7606_dev_inst->data, 0, sizeof(p_ad7606_dev_inst->data));
+	spi_write_and_read(p_ad7606_dev_inst->spi_desc,
+			   p_ad7606_dev_inst->data, bytes_to_read);
+
+#if (AD7606X_ADC_RESOLUTION == 18)
+	adc_raw =
+		(((uint32_t)p_ad7606_dev_inst->data[buffer_offset] << 16) |		// MSB
+		 ((uint32_t)p_ad7606_dev_inst->data[buffer_offset + 1] << 8) |
+		 ((uint32_t)p_ad7606_dev_inst->data[buffer_offset + 2]));		// LSB
+#else
+	adc_raw =
+		(uint16_t)(((uint16_t)p_ad7606_dev_inst->data[buffer_offset] << 8) | 	// MSB
+			   p_ad7606_dev_inst->data[buffer_offset + 1]); 		// LSB
+#endif
+
+	*adc_data = reformat_adc_raw_data(adc_raw, polarity[input_chn]);
+
+	return SUCCESS;
 }
 
 
 /*!
- * @brief	Function to stop background ADC data capture
- * @return	none
+ * @brief	Trigger next ADC conversion
+ * @return	SUCCESS in case of success, FAILURE otherwise
  */
-void stop_background_data_capture(void)
+int32_t ad7606_trigger_next_conversion(void)
 {
-	/* Reset data capture flags */
-	start_adc_data_capture = false;
-	num_of_active_channels = 0;
-	min_bytes_to_read = 0;
-	chn_read_cnt = 0;
-
-	/* Reset acquisition buffer states and clear old data */
-	acq_buffer.state = BUF_EMPTY;
-
-	memset((void *)acq_buffer.data, 0, sizeof(acq_buffer.data));
-
-	acq_buffer.wr_indx = 0;
-	acq_buffer.rd_indx = 0;
-	acq_buffer.align_cnt = 0;
-}
-
+	if (ad7606_convst(p_ad7606_dev_inst) != SUCCESS) {
+		return FAILURE;
+	}
 
-/*!
- * @brief	Function to adjust the data buffer offset
- * @param	*arr_indx[in, out]- Array index
- * @param	*offset_end[out] - offset to extract LSB from 18-bit data
- * @param	*mask[out] - channel select mask
- * @return	none
- */
-static void adjust_buffer_offset(uint8_t *arr_indx, uint8_t *offset_end,
-				 uint8_t *mask)
-{
-	*arr_indx += 2;
-
-	/* Track array to reach at the middle (9 bytes apart) to change the offsets */
-	if (*arr_indx == ((AD7606X_ADC_RESOLUTION / 2) - 1)) {
-		(*arr_indx)++;
-		*offset_end = 2;
-		*mask = 0xff;
-	} else {
-		*mask = (0xff >> *offset_end);
-		*offset_end += 2;
-	}
+	return SUCCESS;
 }
diff -r 32de160dce43 -r 054dbd5e1f45 app/ad7606_data_capture.h
--- a/app/ad7606_data_capture.h	Wed Jul 21 11:16:56 2021 +0100
+++ b/app/ad7606_data_capture.h	Tue Aug 03 11:54:49 2021 +0100
@@ -2,8 +2,7 @@
  *   @file   ad7606_data_capture.h
  *   @brief  Header for AD7606 data capture interfaces
 ********************************************************************************
- * Copyright (c) 2020 Analog Devices, Inc.
- *
+ * Copyright (c) 2020-2021 Analog Devices, Inc.
  * All rights reserved.
  *
  * This software is proprietary to Analog Devices, Inc. and its licensors.
@@ -34,13 +33,4 @@
 /************************ Public Declarations *********************************/
 /******************************************************************************/
 
-int32_t iio_data_capture_init(struct ad7606_dev **device);
-int32_t single_data_read(void *device, uint8_t chn, polarity_e polarity);
-size_t buffered_data_read(char *pbuf, size_t bytes, size_t offset,
-			  uint32_t chn_mask);
-void store_requested_samples_count(size_t bytes);
-void do_conversion_callback(void *ctx, uint32_t event, void *extra);
-void start_background_data_capture(uint32_t ch_mask, size_t bytes_count);
-void stop_background_data_capture(void);
-
 #endif /* AD7606_DATA_CAPTURE_H_ */
diff -r 32de160dce43 -r 054dbd5e1f45 app/app_config.c
--- a/app/app_config.c	Wed Jul 21 11:16:56 2021 +0100
+++ b/app/app_config.c	Tue Aug 03 11:54:49 2021 +0100
@@ -18,7 +18,7 @@
 #include <stdbool.h>
 
 #include "app_config.h"
-#include "ad7606_data_capture.h"
+#include "adc_data_capture.h"
 #include "error.h"
 #include "uart.h"
 #include "gpio.h"
@@ -54,7 +54,7 @@
 
 /* External interrupt callback descriptor */
 static struct callback_desc ext_int_callback_desc = {
-	do_conversion_callback,
+	data_capture_callback,
 	NULL,
 	NULL
 };
diff -r 32de160dce43 -r 054dbd5e1f45 app/iio_ad7606.c
--- a/app/iio_ad7606.c	Wed Jul 21 11:16:56 2021 +0100
+++ b/app/iio_ad7606.c	Tue Aug 03 11:54:49 2021 +0100
@@ -29,7 +29,7 @@
 #include "error.h"
 
 #include "ad7606.h"
-#include "ad7606_data_capture.h"
+#include "adc_data_capture.h"
 #include "ad7606_support.h"
 #include "ad7606_user_config.h"
 
@@ -68,6 +68,22 @@
 #define	OFFSET_REG_RESOLUTION		1
 #endif
 
+/* Bytes per sample. This count should divide the total 256 bytes into 'n' equivalent
+ * ADC samples as IIO library requests only 256bytes of data at a time in a given
+ * data read query.
+ * For 1 to 8-bit ADC, bytes per sample = 1 (2^0)
+ * For 9 to 16-bit ADC, bytes per sample = 2 (2^1)
+ * For 17 to 32-bit ADC, bytes per sample = 4 (2^2)
+ **/
+#if (AD7606X_ADC_RESOLUTION == 18)
+#define	BYTES_PER_SAMPLE	sizeof(uint32_t)	// For ADC resolution of 18-bits
+#else
+#define	BYTES_PER_SAMPLE	sizeof(uint16_t)	// For ADC resolution of 16-bits
+#endif
+
+/* Number of data storage bits (needed for IIO client to plot ADC data) */
+#define CHN_STORAGE_BITS	(BYTES_PER_SAMPLE * 8)
+
 /******************************************************************************/
 /*************************** Types Declarations *******************************/
 /******************************************************************************/
@@ -83,7 +99,7 @@
 /**
  * Pointer to the struct representing the AD7606 IIO device
  */
-static struct ad7606_dev *p_ad7606_dev_inst = NULL;
+struct ad7606_dev *p_ad7606_dev_inst = NULL;
 
 
 /* Device attributes with default values */
@@ -282,8 +298,9 @@
 	int32_t adc_data_raw;
 
 	/* Capture the raw adc data */
-	adc_data_raw = single_data_read(device, channel->ch_num,
-					attr_polarity_val[channel->ch_num]);
+	if (read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw) != SUCCESS) {
+		return -EINVAL;
+	}
 
 	return (ssize_t) sprintf(buf, "%d", adc_data_raw);
 }
@@ -834,7 +851,7 @@
 				   const struct iio_ch_info *channel,
 				   intptr_t id)
 {
-	int32_t adc_chn_data = 0;
+	int32_t adc_data_raw = 0;
 	float temperature;
 	float voltage;
 
@@ -849,11 +866,10 @@
 		udelay(100);
 
 		/* Sample the channel and read conversion result */
-		adc_chn_data = single_data_read(device, channel->ch_num,
-						attr_polarity_val[channel->ch_num]);
+		read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
 
 		/* Convert ADC data into equivalent voltage */
-		voltage = convert_adc_raw_to_voltage(adc_chn_data,
+		voltage = convert_adc_raw_to_voltage(adc_data_raw,
 						     attr_scale_val[channel->ch_num]);
 
 		/* Obtain the temperature using equation specified in device datasheet */
@@ -899,7 +915,7 @@
 			    intptr_t id)
 {
 	float vref_voltge;
-	int32_t adc_chn_data;
+	int32_t adc_data_raw;
 
 	/* Configure the channel multiplexer to select Vref read */
 	if (ad7606_spi_write_mask(device,
@@ -912,11 +928,10 @@
 		udelay(100);
 
 		/* Sample the channel and read conversion result */
-		adc_chn_data = single_data_read(device, channel->ch_num,
-						attr_polarity_val[channel->ch_num]);
+		read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
 
 		/* Convert ADC data into equivalent voltage */
-		vref_voltge = convert_adc_raw_to_voltage(adc_chn_data,
+		vref_voltge = convert_adc_raw_to_voltage(adc_data_raw,
 				attr_scale_val[channel->ch_num]);
 
 		/* Divide by 4 since Vref Mux has 4x multiplier on it */
@@ -962,7 +977,7 @@
 			      intptr_t id)
 {
 	float vdrive_voltge;
-	int32_t adc_chn_data;
+	int32_t adc_data_raw;
 
 	/* Configure the channel multiplexer to select Vdrive read */
 	if (ad7606_spi_write_mask(device,
@@ -975,11 +990,10 @@
 		udelay(100);
 
 		/* Sample the channel and read conversion result */
-		adc_chn_data = single_data_read(device, channel->ch_num,
-						attr_polarity_val[channel->ch_num]);
+		read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
 
 		/* Convert ADC data into equivalent voltage */
-		vdrive_voltge = convert_adc_raw_to_voltage(adc_chn_data,
+		vdrive_voltge = convert_adc_raw_to_voltage(adc_data_raw,
 				attr_scale_val[channel->ch_num]);
 
 		/* Change channel mux back to analog input */
@@ -1022,7 +1036,7 @@
 			    intptr_t id)
 {
 	float aldo_voltge;
-	int32_t adc_chn_data;
+	int32_t adc_data_raw;
 
 	/* Configure the channel multiplexer to select ALDO read */
 	if (ad7606_spi_write_mask(device,
@@ -1035,11 +1049,10 @@
 		udelay(100);
 
 		/* Sample the channel and read conversion result */
-		adc_chn_data = single_data_read(device, channel->ch_num,
-						attr_polarity_val[channel->ch_num]);
+		read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
 
 		/* Convert ADC data into equivalent voltage */
-		aldo_voltge = convert_adc_raw_to_voltage(adc_chn_data,
+		aldo_voltge = convert_adc_raw_to_voltage(adc_data_raw,
 				attr_scale_val[channel->ch_num]);
 
 		/* Divide by 4 since ALDO Mux has 4x multiplier on it */
@@ -1085,7 +1098,7 @@
 			    intptr_t id)
 {
 	float dldo_voltge;
-	int32_t adc_chn_data;
+	int32_t adc_data_raw;
 
 	/* Configure the channel multiplexer to select DLDO read */
 	if (ad7606_spi_write_mask(device,
@@ -1098,12 +1111,10 @@
 		udelay(100);
 
 		/* Sample the channel and read conversion result */
-		adc_chn_data = single_data_read(device,
-						channel->ch_num,
-						attr_polarity_val[channel->ch_num]);
+		read_single_sample(channel->ch_num, (uint32_t *)&adc_data_raw);
 
 		/* Convert ADC data into equivalent voltage */
-		dldo_voltge = convert_adc_raw_to_voltage(adc_chn_data,
+		dldo_voltge = convert_adc_raw_to_voltage(adc_data_raw,
 				attr_scale_val[channel->ch_num]);
 
 		/* Divide by 4 since ALDO Mux has 4x multiplier on it */
@@ -1156,18 +1167,14 @@
 	do {
 		if (ad7606_spi_reg_write(device, AD7606_REG_OPEN_DETECT_QUEUE, 1) == SUCCESS) {
 			/* Read the ADC on selected chnnel (first reading post open circuit detection start) */
-			prev_adc_code = single_data_read(device,
-							 channel->ch_num,
-							 attr_polarity_val[channel->ch_num]);
+			read_single_sample(channel->ch_num, (uint32_t *)&prev_adc_code);
 
 			/* Perform N conversions and monitor the code delta */
 			for (cnt = 0; cnt < MANUAL_OPEN_DETECT_CONV_CNTS; cnt++) {
 				/* Check if code is within 350LSB (nearest ZS code) */
 				if (prev_adc_code >= 0 && prev_adc_code < MANUAL_OPEN_DETECT_ENTRY_TRHLD) {
 					/* Perform next conversion and read the result */
-					curr_adc_code = single_data_read(device,
-									 channel->ch_num,
-									 attr_polarity_val[channel->ch_num]);
+					read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code);
 
 					/* Check if delta b/w current and previus reading is within 10 LSB code */
 					if (abs(curr_adc_code - prev_adc_code) > MANUAL_OPEN_DETECT_CONV_TRSHLD) {
@@ -1195,9 +1202,7 @@
 				/* Perform next conversions (~2-3) and read the result (with common mode set high) */
 				for (cnt = 0; cnt < MANUAL_OPEN_DETECT_CM_CNV_CNT; cnt++) {
 					udelay(100);
-					curr_adc_code = single_data_read(device,
-									 channel->ch_num,
-									 attr_polarity_val[channel->ch_num]);
+					read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code);
 				}
 
 				/* Check if delta b/w common mode high code and previous N conversion code is > threshold */
@@ -1218,9 +1223,7 @@
 						 AD7606_REG_OPEN_DETECT_ENABLE,
 						 0) == SUCCESS) {
 				/* Perform next conversion and read the result (with common mode set low) */
-				curr_adc_code = single_data_read(device,
-								 channel->ch_num,
-								 attr_polarity_val[channel->ch_num]);
+				read_single_sample(channel->ch_num, (uint32_t *)&curr_adc_code);
 
 				/* Check if delta b/w common mode low code and previous N conversion code is < threshold */
 				if (abs(curr_adc_code - prev_adc_code) < MANUAL_OPEN_DETECT_THRESHOLD_RPD50K) {
@@ -1395,7 +1398,7 @@
 	float lsb_voltage;
 	float adc_voltage;
 	polarity_e polarity = attr_polarity_val[channel->ch_num];
-	int32_t adc_data;
+	int32_t adc_raw_data;
 	int8_t chn_offset;
 
 	/* Perform the system offset calibration */
@@ -1407,11 +1410,10 @@
 	}
 
 	/* Sample and read the ADC channel */
-	adc_data = single_data_read(device, channel->ch_num,
-				    polarity);
+	read_single_sample(channel->ch_num, (uint32_t *)&adc_raw_data);
 
 	/* Get an equivalent ADC voltage */
-	adc_voltage = convert_adc_raw_to_voltage(adc_data,
+	adc_voltage = convert_adc_raw_to_voltage(adc_raw_data,
 			attr_scale_val[channel->ch_num]);
 
 	/* Calculate the channel offset and write it to offset register */
@@ -1553,12 +1555,16 @@
 				    uint32_t ch_mask)
 {
 	if (adc_data_capture_started == false) {
-		start_background_data_capture(ch_mask, bytes_count);
+		start_data_capture(ch_mask, AD7606X_ADC_CHANNELS);
 		adc_data_capture_started = true;
 	}
 
 	/* Read the buffered data */
-	return (ssize_t)buffered_data_read(pbuf, bytes_count, offset, ch_mask);
+	return (ssize_t)read_buffered_data(pbuf,
+					   bytes_count,
+					   offset,
+					   ch_mask,
+					   BYTES_PER_SAMPLE);
 }
 
 
@@ -1579,7 +1585,7 @@
 	 * iio_ad7606_read_data() function */
 
 	/* Store the requested samples count value for data capture */
-	store_requested_samples_count(bytes_count);
+	store_requested_samples_count(bytes_count, BYTES_PER_SAMPLE);
 
 	return SUCCESS;
 }
@@ -1605,7 +1611,7 @@
 static int32_t iio_ad7606_stop_transfer(void *dev)
 {
 	adc_data_capture_started = false;
-	stop_background_data_capture();
+	stop_data_capture();
 
 	return SUCCESS;
 }
@@ -1688,7 +1694,6 @@
 		.store = set_chn_calibrate_adc_gain,
 	},
 #if defined(DEV_AD7606C_18) || defined(DEV_AD7606C_16)
-	&iio_attr_bandwidth
 	{
 		.name = "bandwidth",
 		.show = get_bandwidth,
@@ -1750,13 +1755,8 @@
 /* IIOD channels configurations */
 struct scan_type chn_scan = {
 	.sign = 's',
-#if (AD7606X_ADC_RESOLUTION == 18)
-	.realbits = 18,
-	.storagebits = 18,
-#else
-	.realbits = 16,
-	.storagebits = 16,
-#endif
+	.realbits = CHN_STORAGE_BITS,
+	.storagebits = CHN_STORAGE_BITS,
 	.shift = 0,
 	.is_big_endian = false
 };
@@ -2008,12 +2008,6 @@
 		return init_status;
 	}
 
-	/* Init the data capture for AD7606 IIO app */
-	init_status = iio_data_capture_init(&p_ad7606_dev_inst);
-	if (init_status != SUCCESS) {
-		return init_status;
-	}
-
 	return init_status;
 }
 
diff -r 32de160dce43 -r 054dbd5e1f45 app/iio_ad7606.h
--- a/app/iio_ad7606.h	Wed Jul 21 11:16:56 2021 +0100
+++ b/app/iio_ad7606.h	Tue Aug 03 11:54:49 2021 +0100
@@ -30,7 +30,7 @@
 /******************************************************************************/
 
 /******************************************************************************/
-/************************ Functions Declarations ******************************/
+/*************************** Public Declarations ******************************/
 /******************************************************************************/
 
 /* Init the IIO interface */
@@ -39,4 +39,6 @@
 /* Run the IIO event handler */
 void ad7606_iio_event_handler(void);
 
+extern struct ad7606_dev *p_ad7606_dev_inst;
+
 #endif /* IIO_AD7606_H_ */
diff -r 32de160dce43 -r 054dbd5e1f45 app/mbed_platform_drivers.lib
--- a/app/mbed_platform_drivers.lib	Wed Jul 21 11:16:56 2021 +0100
+++ b/app/mbed_platform_drivers.lib	Tue Aug 03 11:54:49 2021 +0100
@@ -1,1 +1,1 @@
-https://os.mbed.com/teams/AnalogDevices/code/platform_drivers/#af1f2416dd26
\ No newline at end of file
+https://os.mbed.com/teams/AnalogDevices/code/platform_drivers/#5ae03a197e59
\ No newline at end of file