Example program for EVAL-AD4130

Dependencies:   tempsensors sdp_k1_sdram

Revision:
2:7b2b268ea49c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/ad4130_support.c	Wed Jul 20 18:12:00 2022 +0530
@@ -0,0 +1,380 @@
+/*************************************************************************//**
+ *   @file   ad4130_support.c
+ *   @brief  AD4130 device No-OS driver supports
+******************************************************************************
+* Copyright (c) 2020, 2022 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 <stdint.h>
+
+#include "app_config.h"
+#include "ad4130_support.h"
+#include "no_os_error.h"
+
+/******************************************************************************/
+/********************** Macros and Constants Definition ***********************/
+/******************************************************************************/
+
+/* AD4130 FIFO size and readback command size in bytes */
+#define AD4130_FIFO_MAX_SIZE		(256)
+#define AD4130_FIFO_READ_CMD_BYTES	(2)
+
+#define BYTE_SIZE					(8)
+
+/* Timeout to monitor CON monitor GPIO. The timeout count is dependent upon the
+ * MCU clock frequency. This timeout is tested for SDP-K1 Mbed controller platform */
+#define CONV_MON_GPIO_TIMEOUT	(10000)
+
+/* Select between GPIO Or STATUS register to monitor the end
+ * of conversion in single conversion mode */
+//#define CONV_MON_USING_RDY_STATUS		// Uncomment to use STATUS reg
+
+/* FIFO busy time as per specifications (in usec)
+ * Note : This time is stringent in FIFO readback.The minimum time period
+ * as per specifications is 20usec
+ */
+#define	FIFO_BUSY_TIME		(20)
+
+/******************************************************************************/
+/********************** Variables and User Defined Data Types *****************/
+/******************************************************************************/
+
+/* AD4130 FIFO readback buffer.
+ * Size for 24-bit ADC = (256 * 3) + 2 = 770 bytes
+ * Size for 16-bit ADC = (256 * 2) + 2 = 514 bytes
+ * */
+static uint8_t fifo_buf[(AD4130_FIFO_MAX_SIZE * (ADC_RESOLUTION / BYTE_SIZE)) +
+									      AD4130_FIFO_READ_CMD_BYTES];
+
+/******************************************************************************/
+/************************ Functions Definitions *******************************/
+/******************************************************************************/
+
+/*!
+ * @brief	Get reference voltage based on the reference source
+ * @param	dev[in] - Device instance
+ * @param	chn[in] - ADC channel
+ * @return	Reference voltage
+ */
+float ad4130_get_reference_voltage(struct ad413x_dev *dev, uint8_t chn)
+{
+	float ref_voltage;
+	uint8_t preset = dev->ch[chn].preset;
+	enum ad413x_ref_sel ref = dev->preset[preset].ref_sel;
+	enum ad413x_int_ref int_ref = dev->int_ref;
+
+	switch (ref) {
+	case AD413X_REFIN1:
+		ref_voltage = AD4130_REFIN1_VOLTAGE;
+		break;
+
+	case AD413X_REFIN2:
+		ref_voltage = AD4130_REFIN2_VOLTAGE;
+		break;
+
+	case AD413X_AVDD_AVSS:
+		ref_voltage = AD4130_AVDD_VOLTAGE;
+		break;
+
+	case AD413X_REFOUT_AVSS:
+		if (int_ref == AD413X_INTREF_1_25V) {
+			ref_voltage = AD4170_1_25V_INT_REF_VOLTAGE;
+		} else {
+			ref_voltage = AD4170_2_5V_INT_REF_VOLTAGE;
+		}
+		break;
+
+	default:
+		ref_voltage = AD4170_2_5V_INT_REF_VOLTAGE;
+		break;
+	}
+
+	return ref_voltage;
+}
+
+/*!
+ * @brief	Perform the sign conversion for handling negative voltages in
+ *			bipolar mode
+ * @param	dev[in] - Device instance
+ * @param	adc_raw_data[in] - ADC raw value
+ * @param	chn[in] - ADC Channel
+ * @return	ADC data after signed conversion
+ */
+int32_t perform_sign_conversion(struct ad413x_dev *dev, uint32_t adc_raw_data,
+				uint8_t chn)
+{
+	int32_t adc_data;
+	bool bipolar = dev->bipolar;
+
+	/* Bipolar ADC Range:  (-FS) <-> 0 <-> (+FS) : 0 <-> 2^(ADC_RES-1)-1 <-> 2^(ADC_RES-1)
+	   Unipolar ADC Range: 0 <-> (+FS) : 0 <-> 2^ADC_RES
+	 **/
+	if (bipolar) {
+		/* Data output format is offset binary for bipolar mode */
+		adc_data = adc_raw_data - ADC_MAX_COUNT_BIPOLAR;
+	} else {
+		/* Data output format is straight binary for unipolar mode */
+		adc_data = adc_raw_data;
+	}
+
+	return adc_data;
+}
+
+/*!
+ * @brief	Convert the ADC raw value into equivalent voltage
+ * @param	dev[in] - Device instance
+ * @param	adc_raw[in]- ADC raw data
+ * @param	chn[in] - ADC channel
+ * @return	ADC voltage value
+ */
+float convert_adc_sample_into_voltage(void *dev, uint32_t adc_raw,
+				      uint8_t chn)
+{
+	enum ad413x_gain pga;
+	float vref;
+	int32_t adc_data;
+	uint8_t preset = ((struct ad413x_dev *)dev)->ch[chn].preset;
+	bool bipolar = ((struct ad413x_dev *)dev)->bipolar;
+
+	pga = ((struct ad413x_dev *)dev)->preset[preset].gain;
+	vref = ad4130_get_reference_voltage(dev, chn);
+	adc_data = perform_sign_conversion(dev, adc_raw, chn);
+
+	if (bipolar) {
+		return (adc_data * (vref / (ADC_MAX_COUNT_BIPOLAR * (1 << pga))));
+	} else {
+		return (adc_data * (vref / (ADC_MAX_COUNT_UNIPOLAR * (1 << pga))));
+	}
+}
+
+/*!
+ * @brief	Convert the ADC raw value into equivalent RTD resistance
+ * @param	dev[in] - Device instance
+ * @param	adc_raw[in] - ADC raw sample
+ * @param	rtd_ref[in] - RTD reference resistance in ohms
+ * @param	chn[in] - ADC channel
+ * @return	RTD resistance value
+ * @note	RTD is biased with constant excitation current. Below formula
+ *			is based on ratiometric measurement, where fixed value of RTD RREF
+ *			(reference resistor) and gain is taken into account
+ */
+float convert_adc_raw_into_rtd_resistance(void *dev, uint32_t adc_raw,
+		float rtd_ref, uint8_t chn)
+{
+	enum ad413x_gain pga;
+	int32_t adc_data;
+	uint8_t preset = ((struct ad413x_dev *)dev)->ch[chn].preset;
+	bool bipolar = ((struct ad413x_dev *)dev)->bipolar;
+
+	pga = ((struct ad413x_dev *)dev)->preset[preset].gain;
+	adc_data = perform_sign_conversion(dev, adc_raw, chn);
+
+	if (bipolar) {
+		return (((float)adc_data * rtd_ref) / (ADC_MAX_COUNT_BIPOLAR * (1 << pga)));
+	} else {
+		return (((float)adc_data * rtd_ref) / (ADC_MAX_COUNT_UNIPOLAR * (1 << pga)));
+	}
+}
+
+/*!
+ * @brief	Function to monitor end of conversion and read
+ *			conversion result
+ * @param	dev[in] - Device instance
+ * @param	raw_data[in, out]- ADC raw data
+ * @return	0 in case of success, negative error code otherwise
+ */
+int32_t ad413x_mon_conv_and_read_data(struct ad413x_dev *dev,
+				      uint32_t *raw_data)
+{
+	int32_t ret;
+	uint8_t conv_mon = 0;
+	uint32_t timeout = CONV_MON_GPIO_TIMEOUT;
+
+	if (!dev || !raw_data) {
+		return -EINVAL;
+	}
+
+	/* Wait for conversion */
+#if defined(CONV_MON_USING_RDY_STATUS)
+	while (!conv_mon && timeout--) {
+		/* Read the value of the Status Register */
+		ret = ad413x_reg_read(dev, AD413X_REG_STATUS, raw_data);
+		if (ret) {
+			return ret;
+		}
+
+		/* Check the RDY bit in the Status Register */
+		conv_mon = (*raw_data & AD413X_ADC_DATA_STATUS);
+	}
+
+	if (!timeout) {
+		return -EIO;
+	}
+
+	/* Read the conversion result */
+	ret = ad413x_reg_read(dev, AD413X_REG_DATA, raw_data);
+	if (ret) {
+		return ret;
+	}
+#else
+	conv_mon = NO_OS_GPIO_HIGH;
+	while (conv_mon == NO_OS_GPIO_HIGH && timeout--) {
+		ret = no_os_gpio_get_value(conv_mon_gpio_desc, &conv_mon);
+		if (ret) {
+			return ret;
+		}
+	}
+
+	if (!timeout) {
+		return -EIO;
+	}
+
+	/* Read the conversion result */
+	ret = ad413x_reg_read(dev, AD413X_REG_DATA, raw_data);
+	if (ret) {
+		return ret;
+	}
+
+	conv_mon = NO_OS_GPIO_LOW;
+	timeout = CONV_MON_GPIO_TIMEOUT;
+	while (conv_mon == NO_OS_GPIO_LOW && timeout--) {
+		ret = no_os_gpio_get_value(conv_mon_gpio_desc, &conv_mon);
+		if (ret) {
+			return ret;
+		}
+	}
+
+	if (!timeout) {
+		return -EIO;
+	}
+#endif
+
+	return 0;
+}
+
+/*!
+ * @brief	Read the data from FIFO
+ * @param	dev[in] - device instance
+ * @param	data[in] - Buffer to store FIFO data
+ * @param	adc_samples[in] - Number of ADC samples to read
+ * @return	0 in case of success, negative error code otherwise
+ * @note	This function doesn't consider the FIFO status and header information
+ *			during data readback. It is assumed data user is intending to read
+ *			only the data from FIFO.
+ */
+int32_t ad4130_read_fifo(struct ad413x_dev *dev, uint32_t *data,
+			 uint32_t adc_samples)
+{
+	int32_t ret;
+	uint32_t loop_cntr;
+	uint32_t buf_indx = 0;
+	uint32_t bytes;
+
+	if (!dev || !data) {
+		return -EINVAL;
+	}
+
+	/* Watermark count of 0 implies full FIFO readback */
+	if ((adc_samples == 0) || (adc_samples > AD4130_FIFO_MAX_SIZE)) {
+		adc_samples = AD4130_FIFO_MAX_SIZE;
+	}
+
+	/* Delay b/w interrupt trigger and FIFO readback start */
+	no_os_udelay(FIFO_BUSY_TIME);
+
+	/* MOSI pin outputs 0x00 during FIFO data readback */
+	memset(fifo_buf, 0, sizeof(fifo_buf));
+
+	/* Enter into FIFO read mode by issuing dummy read command. Command consists of first byte as
+	 * address of FIFO data register and 2nd byte as number of samples to read from FIFO */
+	fifo_buf[0] = AD413X_COMM_REG_RD | AD413X_ADDR(AD413X_REG_FIFO_DATA);
+	fifo_buf[1] = adc_samples;
+
+	/* Bytes to read = (samples * data size) + fifo data reg address + sample_cnt */
+	bytes = (adc_samples * (ADC_RESOLUTION / BYTE_SIZE)) +
+		AD4130_FIFO_READ_CMD_BYTES;
+
+	/* Read all bytes over SPI */
+	ret = no_os_spi_write_and_read(dev->spi_dev, fifo_buf, bytes);
+	if (ret) {
+		return ret;
+	}
+
+	/* Extract the data from buffer (data doesn't contain header/status info) */
+	for (loop_cntr = AD4130_FIFO_READ_CMD_BYTES; loop_cntr < bytes;
+	     loop_cntr += (ADC_RESOLUTION / BYTE_SIZE)) {
+#if (ADC_RESOLUTION == 24)
+		data[buf_indx++] = ((int32_t)fifo_buf[loop_cntr] << 16) |
+				   ((int32_t)fifo_buf[loop_cntr + 1] << 8) |
+				   (int32_t)fifo_buf[loop_cntr + 2];
+#else
+		/* For 16-bit resolution */
+		data[buf_indx++] = ((int32_t)fifo_buf[loop_cntr] << 8) |
+				   (int32_t)fifo_buf[loop_cntr + 1];
+#endif
+	}
+
+	return 0;
+}
+
+/*!
+ * @brief	Set interrupt conversion source (GPIO)
+ * @param	dev[in] - Device instance
+ * @param	conv_int_source[in]- Interrupt source
+ * @return	0 in case of success, negative error code otherwise
+ */
+int32_t ad413x_set_int_source(struct ad413x_dev *dev,
+			      adc_conv_int_source_e conv_int_source)
+{
+	int32_t ret;
+
+	if (!dev) {
+		return -EINVAL;
+	}
+
+	ret = ad413x_reg_write_msk(dev,
+				   AD413X_REG_IO_CTRL,
+				   AD413X_INT_PIN_SEL(conv_int_source),
+				   AD4130_INT_SRC_SEL_MSK);
+	if (ret) {
+		return ret;
+	}
+
+	return 0;
+}
+
+/*!
+ * @brief	Set filter FS value
+ * @param	dev[in] - Device instance
+ * @param	fs[in]- FS value
+ * @param	preset[in] - Channel setup
+ * @return	0 in case of success, negative error code otherwise
+ */
+int32_t ad413x_set_filter_fs(struct ad413x_dev *dev, uint32_t fs,
+			     uint8_t preset)
+{
+	int32_t ret;
+
+	if (!dev) {
+		return -EINVAL;
+	}
+
+	ret = ad413x_reg_write_msk(dev,
+				   AD413X_REG_FILTER(preset),
+				   AD413X_FS_N(fs),
+				   AD4130_FILTER_FS_MSK);
+	if (ret) {
+		return ret;
+	}
+
+	return 0;
+}