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.
Revision 1:abe97d9dd504, committed 2021-03-15
- Comitter:
- jngarlitos
- Date:
- Mon Mar 15 06:51:56 2021 +0000
- Parent:
- 0:3c3bc5b9174a
- Commit message:
- Initial Commit for AD7768-1 library files
Changed in this revision
diff -r 3c3bc5b9174a -r abe97d9dd504 AD77681.cpp
diff -r 3c3bc5b9174a -r abe97d9dd504 AD77681.h
diff -r 3c3bc5b9174a -r abe97d9dd504 ad77681.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ad77681.c Mon Mar 15 06:51:56 2021 +0000
@@ -0,0 +1,1848 @@
+/***************************************************************************//**
+ * @file ad77681.c
+ * @brief Implementation of AD7768-1 Driver.
+ * @author SPopa (stefan.popa@analog.com)
+********************************************************************************
+ * Copyright 2017(c) Analog Devices, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of Analog Devices, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * - The use of this software may or may not infringe the patent rights
+ * of one or more patent holders. This license does not release you
+ * from the requirement that you obtain separate licenses from these
+ * patent holders to use this software.
+ * - Use of the software either in source or binary form, must be run
+ * on or directly connected to an Analog Devices Inc. component.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+/******************************************************************************/
+/***************************** Include Files **********************************/
+/******************************************************************************/
+#include "stdio.h"
+#include "stdlib.h"
+#include "stdbool.h"
+#include <string.h>
+#include "ad77681.h"
+#include "error.h"
+#include "delay.h"
+
+/******************************************************************************/
+/************************** Functions Implementation **************************/
+/******************************************************************************/
+/**
+ * Compute CRC8 checksum.
+ * @param data - The data buffer.
+ * @param data_size - The size of the data buffer.
+ * @param init_val - CRC initial value.
+ * @return CRC8 checksum.
+ */
+uint8_t ad77681_compute_crc8(uint8_t *data,
+ uint8_t data_size,
+ uint8_t init_val)
+{
+ uint8_t i;
+ uint8_t crc = init_val;
+
+ while (data_size) {
+ for (i = 0x80; i != 0; i >>= 1) {
+ if (((crc & 0x80) != 0) != ((*data & i) != 0)) {
+ crc <<= 1;
+ crc ^= AD77681_CRC8_POLY;
+ } else
+ crc <<= 1;
+ }
+ data++;
+ data_size--;
+ }
+ return crc;
+}
+
+/**
+ * Compute XOR checksum.
+ * @param data - The data buffer.
+ * @param data_size - The size of the data buffer.
+ * @param init_val - CRC initial value.
+ * @return XOR checksum.
+ */
+uint8_t ad77681_compute_xor(uint8_t *data,
+ uint8_t data_size,
+ uint8_t init_val)
+{
+ uint8_t crc = init_val;
+ uint8_t buf[3];
+ uint8_t i;
+
+ for (i = 0; i < data_size; i++) {
+ buf[i] = *data;
+ crc ^= buf[i];
+ data++;
+ }
+ return crc;
+}
+
+/**
+ * Read from device.
+ * @param dev - The device structure.
+ * @param reg_addr - The register address.
+ * @param reg_data - The register data.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_reg_read(struct ad77681_dev *dev,
+ uint8_t reg_addr,
+ uint8_t *reg_data)
+{
+ int32_t ret;
+ uint8_t crc;
+ uint8_t buf[3], crc_buf[2];
+ uint8_t buf_len = (dev->crc_sel == AD77681_NO_CRC) ? 2 : 3;
+
+ buf[0] = AD77681_REG_READ(reg_addr);
+ buf[1] = 0x00;
+
+ ret = spi_write_and_read(dev->spi_desc, buf, buf_len);
+ if (ret < 0)
+ return ret;
+
+ /* XOR or CRC checksum for read transactions */
+ if (dev->crc_sel != AD77681_NO_CRC) {
+ crc_buf[0] = AD77681_REG_READ(reg_addr);
+ crc_buf[1] = buf[1];
+
+ if (dev->crc_sel == AD77681_XOR)
+ /* INITIAL_CRC is 0, when ADC is not in continuous-read mode */
+ crc = ad77681_compute_xor(crc_buf, 2, INITIAL_CRC);
+ else if(dev->crc_sel == AD77681_CRC)
+ /* INITIAL_CRC is 0, when ADC is not in continuous-read mode */
+ crc = ad77681_compute_crc8(crc_buf, 2, INITIAL_CRC);
+
+ /* In buf[2] is CRC from the ADC */
+ if (crc != buf[2])
+ ret = FAILURE;
+#ifdef CRC_DEBUG
+ printf("\n%x\t%x\tCRC/XOR: %s\n", crc,
+ buf[2], ((crc != buf[2]) ? "FAULT" : "OK"));
+#endif /* CRC_DEBUG */
+ }
+
+ reg_data[0] = AD77681_REG_READ(reg_addr);
+ memcpy(reg_data + 1, buf + 1, ARRAY_SIZE(buf) - 1);
+
+ return ret;
+}
+
+/**
+ * Write to device.
+ * @param dev - The device structure.
+ * @param reg_addr - The register address.
+ * @param reg_data - The register data.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_reg_write(struct ad77681_dev *dev,
+ uint8_t reg_addr,
+ uint8_t reg_data)
+{
+ uint8_t buf[3];
+ /* Buffer length in case of checksum usage */
+ uint8_t buf_len = (dev->crc_sel == AD77681_NO_CRC) ? 2 : 3;
+
+ buf[0] = AD77681_REG_WRITE(reg_addr);
+ buf[1] = reg_data;
+
+ /* CRC only for read transactions, CRC and XOR for write transactions*/
+ if (dev->crc_sel != AD77681_NO_CRC)
+ buf[2] = ad77681_compute_crc8(buf, 2, INITIAL_CRC);
+
+ return spi_write_and_read(dev->spi_desc, buf, buf_len);
+}
+
+/**
+ * SPI read from device using a mask.
+ * @param dev - The device structure.
+ * @param reg_addr - The register address.
+ * @param mask - The mask.
+ * @param data - The register data.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_read_mask(struct ad77681_dev *dev,
+ uint8_t reg_addr,
+ uint8_t mask,
+ uint8_t *data)
+{
+ uint8_t reg_data[3];
+ int32_t ret;
+
+ ret = ad77681_spi_reg_read(dev, reg_addr, reg_data);
+ *data = (reg_data[1] & mask);
+
+ return ret;
+}
+
+/**
+ * SPI write to device using a mask.
+ * @param dev - The device structure.
+ * @param reg_addr - The register address.
+ * @param mask - The mask.
+ * @param data - The register data.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_write_mask(struct ad77681_dev *dev,
+ uint8_t reg_addr,
+ uint8_t mask,
+ uint8_t data)
+{
+ uint8_t reg_data[3];
+ int32_t ret;
+
+ ret = ad77681_spi_reg_read(dev, reg_addr, reg_data);
+ reg_data[1] &= ~mask;
+ reg_data[1] |= data;
+ ret |= ad77681_spi_reg_write(dev, reg_addr, reg_data[1]);
+
+ return ret;
+}
+
+/**
+ * Helper function to get the number of rx bytes
+ * @param dev - The device structure.
+ * @return rx_buf_len - the number of rx bytes
+ */
+uint8_t ad77681_get_rx_buf_len(struct ad77681_dev *dev)
+{
+ uint8_t rx_buf_len = 0;
+ uint8_t data_len = 0;
+ uint8_t crc = 0;
+ uint8_t status_bit = 0;
+
+ data_len = 3;
+ crc = (dev->crc_sel == AD77681_NO_CRC) ? 0 : 1; // 1 byte for crc
+ status_bit = dev->status_bit; // one byte for status
+
+ rx_buf_len = data_len + crc + status_bit;
+
+ return rx_buf_len;
+}
+
+/**
+ * Helper function to get the number of SPI 16bit frames for INTERRUPT ADC DATA READ
+ * @param dev - The device structure.
+ * @return frame_16bit - the number of 16 bit SPI frames
+ */
+uint8_t ad77681_get_frame_byte(struct ad77681_dev *dev)
+{
+ /* number of 8bit frames */
+ uint8_t frame_bytes;
+ if (dev->conv_len == AD77681_CONV_24BIT)
+ frame_bytes = 3;
+ else
+ frame_bytes = 2;
+ if (dev->crc_sel != AD77681_NO_CRC)
+ frame_bytes++;
+ if (dev->status_bit)
+ frame_bytes++;
+
+ dev->data_frame_byte = frame_bytes;
+
+ return frame_bytes;
+}
+
+/**
+ * Read conversion result from device.
+ * @param dev - The device structure.
+ * @param adc_data - The conversion result data
+ * @param mode - Data read mode
+ * Accepted values: AD77681_REGISTER_DATA_READ
+ * AD77681_CONTINUOUS_DATA_READ
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_spi_read_adc_data(struct ad77681_dev *dev,
+ uint8_t *adc_data,
+ enum ad77681_data_read_mode mode)
+{
+ uint8_t buf[6], crc_xor, add_buff;
+ int32_t ret;
+
+ if (mode == AD77681_REGISTER_DATA_READ) {
+ buf[0] = AD77681_REG_READ(AD77681_REG_ADC_DATA);
+ add_buff = 1;
+ } else {
+ buf[0] = 0x00;
+ add_buff = 0;
+ }
+ buf[1] = 0x00; /* added 2 more array places for max data length read */
+ buf[2] = 0x00; /* For register data read */
+ buf[3] = 0x00; /* register address + 3 bytes of data (24bit format) + Status bit + CRC */
+ buf[4] = 0x00; /* For continuous data read */
+ buf[5] = 0x00; /* 3 bytes of data (24bit format) + Status bit + CRC */
+
+
+ ret = spi_write_and_read(dev->spi_desc, buf, dev->data_frame_byte + add_buff);
+ if (ret < 0)
+ return ret;
+
+ if (dev->crc_sel != AD77681_NO_CRC) {
+ if (dev->crc_sel == AD77681_CRC)
+ crc_xor = ad77681_compute_crc8(buf + add_buff, dev->data_frame_byte - 1,
+ INITIAL_CRC_CRC8);
+ else
+ crc_xor = ad77681_compute_xor(buf + add_buff, dev->data_frame_byte - 1,
+ INITIAL_CRC_XOR);
+
+ if (crc_xor != buf[dev->data_frame_byte - (1 - add_buff)]) {
+ printf("%s: CRC Error.\n", __func__);
+ ret = FAILURE;
+ }
+#ifdef CRC_DEBUG
+ printf("\n%x\t%x\tCRC/XOR: %s\n", crc_xor,
+ buf[dev->data_frame_byte - (1 - add_buff)],
+ ((crc_xor != buf[dev->data_frame_byte - (1 - add_buff)]) ? "FAULT" : "OK"));
+#endif /* CRC_DEBUG */
+ }
+
+ /* Fill the adc_data buffer */
+ memcpy(adc_data, buf, ARRAY_SIZE(buf));
+
+ return ret;
+}
+
+/**
+ * CRC and status bit handling after each readout form the ADC
+ * @param dev - The device structure.
+ * @param *data_buffer - 16-bit buffer readed from the ADC containing the CRC,
+ * data and the stattus bit.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_CRC_status_handling(struct ad77681_dev *dev,
+ uint16_t *data_buffer)
+{
+ int32_t ret = 0;
+ uint8_t status_byte = 0, checksum = 0, checksum_byte = 0, checksum_buf[5],
+ checksum_length = 0, i;
+ char print_buf[50];
+
+ /* Status bit handling */
+ if (dev->status_bit) {
+ /* 24bit ADC data + 8bit of status = 2 16bit frames */
+ if (dev->conv_len == AD77681_CONV_24BIT)
+ status_byte = data_buffer[1] & 0xFF;
+ /* 16bit ADC data + 8bit of status = 2 16bit frames */
+ else
+ status_byte = data_buffer[1] >> 8;
+ }
+
+ /* Checksum bit handling */
+ if (dev->crc_sel != AD77681_NO_CRC) {
+ if ((dev->status_bit == true) & (dev->conv_len == AD77681_CONV_24BIT)) {
+ /* 24bit ADC data + 8bit of status + 8bit of CRC = 3 16bit frames */
+ checksum_byte = data_buffer[2] >> 8;
+ checksum_length = 4;
+ } else if ((dev->status_bit == true) & (dev->conv_len == AD77681_CONV_16BIT)) {
+ /* 16bit ADC data + 8bit of status + 8bit of CRC = 2 16bit frames */
+ checksum_byte = data_buffer[1] & 0xFF;
+ checksum_length = 3;
+ } else if ((dev->status_bit == false) & (dev->conv_len == AD77681_CONV_24BIT)) {
+ /* 24bit ADC data + 8bit of CRC = 2 16bit frames */
+ checksum_byte = data_buffer[1] & 0xFF;
+ checksum_length = 3;
+ } else if ((dev->status_bit == false) & (dev->conv_len == AD77681_CONV_16BIT)) {
+ /* 16bit ADC data + 8bit of CRC = 2 16bit frames */
+ checksum_byte = data_buffer[1] >> 8;
+ checksum_length = 2;
+ }
+
+ for (i = 0; i < checksum_length; i++) {
+ if (i % 2)
+ checksum_buf[i] = data_buffer[i / 2] & 0xFF;
+ else
+ checksum_buf[i] = data_buffer[i / 2] >> 8;
+ }
+
+ if (dev->crc_sel == AD77681_CRC)
+ checksum = ad77681_compute_crc8(checksum_buf, checksum_length,
+ INITIAL_CRC_CRC8);
+ else if (dev->crc_sel == AD77681_XOR)
+ checksum = ad77681_compute_xor(checksum_buf, checksum_length, INITIAL_CRC_XOR);
+
+ if (checksum != checksum_byte)
+ ret = FAILURE;
+
+#ifdef CRC_DEBUG
+
+ char ok[3] = { 'O', 'K' }, fault[6] = { 'F', 'A', 'U', 'L', 'T' };
+ sprintf(print_buf, "\n%x\t%x\t%x\tCRC %s", checksum_byte, checksum, status_byte,
+ ((ret == FAILURE) ? (fault) : (ok)));
+ printf(print_buf);
+
+#endif /* CRC_DEBUG */
+ }
+
+ return ret;
+}
+
+/**
+ * Conversion from measured data to voltage
+ * @param dev - The device structure.
+ * @param raw_code - ADC raw code measurements
+ * @param voltage - Converted ADC code to voltage
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_data_to_voltage(struct ad77681_dev *dev,
+ uint32_t *raw_code,
+ double *voltage)
+{
+ int32_t converted_data;
+
+ if (*raw_code & 0x800000)
+ converted_data = (int32_t)((0xFF << 24) | *raw_code);
+ else
+ converted_data = (int32_t)((0x00 << 24) | *raw_code);
+
+ /* ((2*Vref)*code)/2^24 */
+ *voltage = (double)(((2.0 * (((double)(dev->vref)) / 1000.0)) /
+ AD7768_FULL_SCALE) * converted_data);
+
+ return SUCCESS;
+}
+
+/**
+ * Update ADCs sample rate depending on MCLK, MCLK_DIV and filter settings
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_update_sample_rate(struct ad77681_dev *dev)
+{
+ uint8_t mclk_div;
+ uint16_t osr;
+
+ /* Finding out MCLK divider */
+ switch (dev->mclk_div) {
+ case AD77681_MCLK_DIV_16:
+ mclk_div = 16;
+ break;
+ case AD77681_MCLK_DIV_8:
+ mclk_div = 8;
+ break;
+ case AD77681_MCLK_DIV_4:
+ mclk_div = 4;
+ break;
+ case AD77681_MCLK_DIV_2:
+ mclk_div = 2;
+ break;
+ default:
+ return FAILURE;
+ break;
+ }
+
+ /* Finding out decimation ratio */
+ switch (dev->filter) {
+ case (AD77681_SINC5 | AD77681_FIR):
+ /* Decimation ratio of FIR or SINC5 (x32 to x1024) */
+ switch (dev->decimate) {
+ case AD77681_SINC5_FIR_DECx32:
+ osr = 32;
+ break;
+ case AD77681_SINC5_FIR_DECx64:
+ osr = 64;
+ break;
+ case AD77681_SINC5_FIR_DECx128:
+ osr = 128;
+ break;
+ case AD77681_SINC5_FIR_DECx256:
+ osr = 256;
+ break;
+ case AD77681_SINC5_FIR_DECx512:
+ osr = 512;
+ break;
+ case AD77681_SINC5_FIR_DECx1024:
+ osr = 1024;
+ break;
+ default:
+ return FAILURE;
+ break;
+ }
+ break;
+ /* Decimation ratio of SINC5 x8 */
+ case AD77681_SINC5_DECx8:
+ osr = 8;
+ break;
+ /* Decimation ratio of SINC5 x16 */
+ case AD77681_SINC5_DECx16:
+ osr = 16;
+ break;
+ /* Decimation ratio of SINC3 */
+ case AD77681_SINC3:
+ osr = (dev->sinc3_osr + 1) * 32;
+ break;
+ default:
+ return FAILURE;
+ break;
+ }
+
+ /* Sample rate to Hz */
+ dev->sample_rate = (dev->mclk / (osr*mclk_div)) * 1000;
+
+ return SUCCESS;
+}
+
+/**
+ * Get SINC3 filter oversampling ratio register value based on user's inserted
+ * output data rate ODR
+ * @param dev - The device structure.
+ * @param sinc3_dec_reg - Returned closest value of SINC3 register
+ * @param sinc3_odr - Desired output data rage
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_SINC3_ODR(struct ad77681_dev *dev,
+ uint16_t *sinc3_dec_reg,
+ float sinc3_odr)
+{
+ uint8_t mclk_div;
+ float odr;
+
+ if (sinc3_odr < 0)
+ return FAILURE;
+
+ switch (dev->mclk_div) {
+ case AD77681_MCLK_DIV_16:
+ mclk_div = 16;
+ break;
+ case AD77681_MCLK_DIV_8:
+ mclk_div = 8;
+ break;
+ case AD77681_MCLK_DIV_4:
+ mclk_div = 4;
+ break;
+ case AD77681_MCLK_DIV_2:
+ mclk_div = 2;
+ break;
+ default:
+ return FAILURE;
+ break;
+ }
+
+ odr = ((float)(dev->mclk * 1000.0) / (sinc3_odr * (float)(32 * mclk_div))) - 1;
+
+ /* Sinc3 oversamplig register has 13 bits, biggest value = 8192 */
+ if (odr < 8193)
+ *sinc3_dec_reg = (uint16_t)(odr);
+ else
+ return FAILURE;
+
+ return SUCCESS;
+}
+
+/**
+ * Set the power consumption mode of the ADC core.
+ * @param dev - The device structure.
+ * @param mode - The power mode.
+ * Accepted values: AD77681_ECO
+ * AD77681_MEDIAN
+ * AD77681_FAST
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_power_mode(struct ad77681_dev *dev,
+ enum ad77681_power_mode mode)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_POWER_CLOCK,
+ AD77681_POWER_CLK_PWRMODE_MSK,
+ AD77681_POWER_CLK_PWRMODE(mode));
+
+ if (ret == SUCCESS)
+ dev->power_mode = mode;
+
+ return ret;
+}
+
+/**
+ * Set the MCLK divider.
+ * @param dev - The device structure.
+ * @param clk_div - The MCLK divider.
+ * Accepted values: AD77681_MCLK_DIV_16
+ * AD77681_MCLK_DIV_8
+ * AD77681_MCLK_DIV_4
+ * AD77681_MCLK_DIV_2
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_mclk_div(struct ad77681_dev *dev,
+ enum ad77681_mclk_div clk_div)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_POWER_CLOCK,
+ AD77681_POWER_CLK_MCLK_DIV_MSK,
+ AD77681_POWER_CLK_MCLK_DIV(clk_div));
+
+ if (ret == SUCCESS)
+ dev->mclk_div = clk_div;
+
+ return ret;
+}
+
+/**
+ * Set the VCM output.
+ * @param dev - The device structure.
+ * @param VCM_out - The VCM output voltage.
+ * Accepted values: AD77681_VCM_HALF_VCC
+ * AD77681_VCM_2_5V
+ * AD77681_VCM_2_05V
+ * AD77681_VCM_1_9V
+ * AD77681_VCM_1_65V
+ * AD77681_VCM_1_1V
+ * AD77681_VCM_0_9V
+ * AD77681_VCM_OFF
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_VCM_output(struct ad77681_dev *dev,
+ enum ad77681_VCM_out VCM_out)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_ANALOG2,
+ AD77681_ANALOG2_VCM_MSK,
+ AD77681_ANALOG2_VCM(VCM_out));
+
+ if (ret == SUCCESS)
+ dev->VCM_out = VCM_out;
+
+ return ret;
+}
+
+/**
+ * Set the AIN- precharge buffer.
+ * @param dev - The device structure.
+ * @param AINn - The negative analog input precharge buffer selector
+ * Accepted values: AD77681_AINn_ENABLED
+ * AD77681_AINn_DISABLED
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_AINn_buffer(struct ad77681_dev *dev,
+ enum ad77681_AINn_precharge AINn)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_ANALOG,
+ AD77681_ANALOG_AIN_BUF_NEG_OFF_MSK,
+ AD77681_ANALOG_AIN_BUF_NEG_OFF(AINn));
+
+ if (ret == SUCCESS)
+ dev->AINn = AINn;
+
+ return ret;
+}
+
+/**
+ * Set the AIN+ precharge buffer.
+ * @param dev - The device structure.
+ * @param AINp - The positive analog input precharge buffer selector
+ * Accepted values: AD77681_AINp_ENABLED
+ * AD77681_AINp_DISABLED
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_AINp_buffer(struct ad77681_dev *dev,
+ enum ad77681_AINp_precharge AINp)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_ANALOG,
+ AD77681_ANALOG_AIN_BUF_POS_OFF_MSK,
+ AD77681_ANALOG_AIN_BUF_POS_OFF(AINp));
+
+ if (ret == SUCCESS)
+ dev->AINp = AINp;
+
+ return ret;
+}
+
+/**
+ * Set the REF- reference buffer
+ * @param dev - The device structure.
+ * @param REFn - The negative reference buffer selector
+ * Accepted values: AD77681_BUFn_DISABLED
+ * AD77681_BUFn_ENABLED
+ * AD77681_BUFn_FULL_BUFFER_ON
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_REFn_buffer(struct ad77681_dev *dev,
+ enum ad77681_REFn_buffer REFn)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_ANALOG,
+ AD77681_ANALOG_REF_BUF_NEG_MSK,
+ AD77681_ANALOG_REF_BUF_NEG(REFn));
+
+ if (ret == SUCCESS)
+ dev->REFn = REFn;
+
+ return ret;
+}
+
+/**
+ * Set the REF+ reference buffer
+ * @param dev - The device structure.
+ * @param REFp - The positive reference buffer selector
+ * Accepted values: AD77681_BUFp_DISABLED
+ * AD77681_BUFp_ENABLED
+ * AD77681_BUFp_FULL_BUFFER_ON
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_REFp_buffer(struct ad77681_dev *dev,
+ enum ad77681_REFp_buffer REFp)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_ANALOG,
+ AD77681_ANALOG_REF_BUF_POS_MSK,
+ AD77681_ANALOG_REF_BUF_POS(REFp));
+
+ if (ret == SUCCESS)
+ dev->REFp = REFp;
+ else
+ return FAILURE;
+
+ return ret;
+}
+
+/**
+ * Set filter type and decimation ratio
+ * @param dev - The device structure.
+ * @param decimate - Decimation ratio of filter
+ * Accepted values: AD77681_SINC5_FIR_DECx32
+ * AD77681_SINC5_FIR_DECx64
+ * AD77681_SINC5_FIR_DECx128
+ * AD77681_SINC5_FIR_DECx256
+ * AD77681_SINC5_FIR_DECx512
+ * AD77681_SINC5_FIR_DECx1024
+ * @param filter - Select filter type
+ * Accepted values: AD77681_SINC5
+ * AD77681_SINC5_DECx8
+ * AD77681_SINC5_DECx16
+ * AD77681_SINC3
+ * AD77681_FIR
+ * @param sinc3_osr - Select decimation ratio for SINC3 filter separately as
+ * integer from 0 to 8192.
+ * See the AD7768-1 datasheet for more info
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_filter_type(struct ad77681_dev *dev,
+ enum ad77681_sinc5_fir_decimate decimate,
+ enum ad77681_filter_type filter,
+ uint16_t sinc3_osr)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_reg_write(dev, AD77681_REG_DIGITAL_FILTER, 0x00);
+
+ /* SINC5 for OSR 8x and 16x*/
+ if ((filter == AD77681_SINC5_DECx8) || (filter == AD77681_SINC5_DECx16)) {
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_DIGITAL_FILTER,
+ AD77681_DIGI_FILTER_FILTER_MSK,
+ AD77681_DIGI_FILTER_FILTER(filter));
+ /* SINC5 and FIR for osr 32x to 1024x */
+ } else if ((filter == AD77681_SINC5) || (filter == AD77681_FIR)) {
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_DIGITAL_FILTER,
+ AD77681_DIGI_FILTER_FILTER_MSK,
+ AD77681_DIGI_FILTER_FILTER(filter));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_DIGITAL_FILTER,
+ AD77681_DIGI_FILTER_DEC_RATE_MSK,
+ AD77681_DIGI_FILTER_DEC_RATE(decimate));
+ /* SINC3*/
+ } else {
+ uint8_t sinc3_LSB = 0, sinc3_MSB = 0;
+
+ sinc3_MSB = sinc3_osr >> 8;
+ sinc3_LSB = sinc3_osr & 0x00FF;
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_DIGITAL_FILTER,
+ AD77681_DIGI_FILTER_FILTER_MSK,
+ AD77681_DIGI_FILTER_FILTER(filter));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SINC3_DEC_RATE_MSB,
+ AD77681_SINC3_DEC_RATE_MSB_MSK,
+ AD77681_SINC3_DEC_RATE_MSB(sinc3_MSB));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SINC3_DEC_RATE_LSB,
+ AD77681_SINC3_DEC_RATE_LSB_MSK,
+ AD77681_SINC3_DEC_RATE_LSB(sinc3_LSB));
+ }
+
+ if ( ret == SUCCESS) {
+ dev->decimate = decimate;
+ dev->filter = filter;
+ /* Sync pulse after each filter change */
+ ret |= ad77681_initiate_sync(dev);
+ }
+
+ return ret;
+}
+
+/**
+ * Enable 50/60 Hz rejection
+ * @param dev - The device structure.
+ * @param enable - The positive reference buffer selector
+ * Accepted values: true
+ * false
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_50HZ_rejection(struct ad77681_dev *dev,
+ uint8_t enable)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_DIGITAL_FILTER,
+ AD77681_DIGI_FILTER_60HZ_REJ_EN_MSK,
+ AD77681_DIGI_FILTER_60HZ_REJ_EN(enable));
+
+ return ret;
+}
+
+/**
+ * Set the REF- reference buffer
+ * @param dev - The device structure.
+ * @param continuous_enable - Continous read enable
+ * Accepted values: AD77681_CONTINUOUS_READ_ENABLE
+ * AD77681_CONTINUOUS_READ_DISABLE
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_continuos_read(struct ad77681_dev *dev,
+ enum ad77681_continuous_read continuous_enable)
+{
+ int32_t ret;
+
+ if (continuous_enable) {
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_INTERFACE_FORMAT,
+ AD77681_INTERFACE_CONT_READ_MSK,
+ AD77681_INTERFACE_CONT_READ_EN(continuous_enable));
+ } else {
+ /* To exit the continuous read mode, a key 0x6C must be
+ written into the device over the SPI*/
+ uint8_t end_key = EXIT_CONT_READ;
+ ret = spi_write_and_read(dev->spi_desc, &end_key, 1);
+ }
+
+ return ret;
+}
+
+/**
+ * Power down / power up the device
+ * @param dev - The device structure.
+ * @param sleep_wake - Power down, or power up the ADC
+ * Accepted values: AD77681_SLEEP
+ * AD77681_WAKE
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_power_down(struct ad77681_dev *dev,
+ enum ad77681_sleep_wake sleep_wake)
+{
+ int32_t ret;
+
+ if (sleep_wake == AD77681_SLEEP) {
+ ret = ad77681_spi_reg_write(dev, AD77681_REG_POWER_CLOCK,
+ AD77681_POWER_CLK_POWER_DOWN);
+ } else {
+ /* Wake up the ADC over SPI, by sending a wake-up sequence:
+ 1 followed by 63 zeroes and CS hold low*/
+ uint8_t wake_sequence[8] = { 0 };
+ /* Insert '1' to the beginning of the wake_sequence*/
+ wake_sequence[0] = 0x80;
+ ret = spi_write_and_read(dev->spi_desc, wake_sequence,
+ ARRAY_SIZE(wake_sequence));
+ }
+
+ return ret;
+}
+
+/**
+ * Conversion mode and source select
+ * @param dev - The device structure.
+ * @param conv_mode - Sets the conversion mode of the ADC
+ * Accepted values: AD77681_CONV_CONTINUOUS
+ * AD77681_CONV_ONE_SHOT
+ * AD77681_CONV_SINGLE
+ * AD77681_CONV_PERIODIC
+ * @param diag_mux_sel - Selects which signal to route through diagnostic mux
+ * Accepted values: AD77681_TEMP_SENSOR
+ * AD77681_AIN_SHORT
+ * AD77681_POSITIVE_FS
+ * AD77681_NEGATIVE_FS
+ * @param conv_diag_sel - Select the input for conversion as AIN or diagnostic mux
+ * Accepted values: true
+ * false
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_conv_mode(struct ad77681_dev *dev,
+ enum ad77681_conv_mode conv_mode,
+ enum ad77681_conv_diag_mux diag_mux_sel,
+ bool conv_diag_sel)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_CONVERSION,
+ AD77681_CONVERSION_MODE_MSK,
+ AD77681_CONVERSION_MODE(conv_mode));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_CONVERSION,
+ AD77681_CONVERSION_DIAG_MUX_MSK,
+ AD77681_CONVERSION_DIAG_MUX_SEL(diag_mux_sel));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_CONVERSION,
+ AD77681_CONVERSION_DIAG_SEL_MSK,
+ AD77681_CONVERSION_DIAG_SEL(conv_diag_sel));
+
+ if (ret == SUCCESS) {
+ dev->conv_mode = conv_mode;
+ dev->diag_mux_sel = diag_mux_sel;
+ dev->conv_diag_sel = conv_diag_sel;
+ }
+
+ return ret;
+}
+
+/**
+ * Set the Conversion Result Output Length.
+ * @param dev - The device structure.
+ * @param conv_len - The MCLK divider.
+ * Accepted values: AD77681_CONV_24BIT
+ * AD77681_CONV_16BIT
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_convlen(struct ad77681_dev *dev,
+ enum ad77681_conv_len conv_len)
+{
+ int32_t ret;
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_INTERFACE_FORMAT,
+ AD77681_INTERFACE_CONVLEN_MSK,
+ AD77681_INTERFACE_CONVLEN(conv_len));
+
+ if (ret == SUCCESS) {
+ dev->conv_len = conv_len;
+ ad77681_get_frame_byte(dev);
+ }
+
+ return ret;
+}
+
+/**
+ * Activates CRC on all SPI transactions and
+ * Selects CRC method as XOR or 8-bit polynomial
+ * @param dev - The device structure.
+ * @param crc_sel - The CRC type.
+ * Accepted values: AD77681_CRC
+ * AD77681_XOR
+ * AD77681_NO_CRC
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_crc_sel(struct ad77681_dev *dev,
+ enum ad77681_crc_sel crc_sel)
+{
+ int32_t ret;
+
+ if (crc_sel == AD77681_NO_CRC) {
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_INTERFACE_FORMAT,
+ AD77681_INTERFACE_CRC_EN_MSK,
+ AD77681_INTERFACE_CRC_EN(0));
+ } else {
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_INTERFACE_FORMAT,
+ AD77681_INTERFACE_CRC_EN_MSK,
+ AD77681_INTERFACE_CRC_EN(1));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_INTERFACE_FORMAT,
+ AD77681_INTERFACE_CRC_TYPE_MSK,
+ AD77681_INTERFACE_CRC_TYPE(crc_sel));
+ }
+
+ if (ret == SUCCESS) {
+ dev->crc_sel = crc_sel;
+ ad77681_get_frame_byte(dev);
+ }
+
+ return ret;
+}
+
+/**
+ * Enables Status bits output
+ * @param dev - The device structure.
+ * @param status_bit - enable or disable status bit
+ * Accepted values: true
+ * false
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_set_status_bit(struct ad77681_dev *dev,
+ bool status_bit)
+{
+ int32_t ret;
+
+ // Set status bit
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_INTERFACE_FORMAT,
+ AD77681_INTERFACE_STATUS_EN_MSK,
+ AD77681_INTERFACE_STATUS_EN(status_bit));
+
+ if (ret == SUCCESS) {
+ dev->status_bit = status_bit;
+ ad77681_get_frame_byte(dev);
+ }
+
+ return ret;
+}
+
+/**
+ * Device reset over SPI.
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_soft_reset(struct ad77681_dev *dev)
+{
+ int32_t ret = 0;
+
+ // Two writes are required to initialize the reset
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SYNC_RESET,
+ AD77681_SYNC_RST_SPI_RESET_MSK,
+ AD77681_SYNC_RST_SPI_RESET(0x3));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SYNC_RESET,
+ AD77681_SYNC_RST_SPI_RESET_MSK,
+ AD77681_SYNC_RST_SPI_RESET(0x2));
+
+ return ret;
+}
+
+/**
+ * Initiate a SYNC_OUT pulse over spi
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_initiate_sync(struct ad77681_dev *dev)
+{
+ return ad77681_spi_write_mask(dev,
+ AD77681_REG_SYNC_RESET,
+ AD77681_SYNC_RST_SPI_STARTB_MSK,
+ AD77681_SYNC_RST_SPI_STARTB(0));
+}
+
+/**
+ * Write to offset registers
+ * @param dev The device structure.
+ * @param value The desired value of the whole 24-bit offset register
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_apply_offset(struct ad77681_dev *dev,
+ uint32_t value)
+{
+ int32_t ret;
+ uint8_t offset_HI = 0, offset_MID = 0, offset_LO = 0;
+
+ offset_HI = (value & 0x00FF0000) >> 16;
+ offset_MID = (value & 0x0000FF00) >> 8;
+ offset_LO = (value & 0x000000FF);
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_OFFSET_HI,
+ AD77681_OFFSET_HI_MSK,
+ AD77681_OFFSET_HI(offset_HI));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_OFFSET_MID,
+ AD77681_OFFSET_MID_MSK,
+ AD77681_OFFSET_MID(offset_MID));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_OFFSET_LO,
+ AD77681_OFFSET_LO_MSK,
+ AD77681_OFFSET_LO(offset_LO));
+
+ return ret;
+}
+
+/**
+ * Write to gain registers
+ * @param dev - The device structure.
+ * @param value - The desired value of the whole 24-bit gain register
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_apply_gain(struct ad77681_dev *dev,
+ uint32_t value)
+{
+ int32_t ret;
+ uint8_t gain_HI = 0, gain_MID = 0, gain_LO = 0;
+
+ gain_HI = (value & 0x00FF0000) >> 16;
+ gain_MID = (value & 0x0000FF00) >> 8;
+ gain_LO = (value & 0x000000FF);
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GAIN_HI,
+ AD77681_GAIN_HI_MSK,
+ AD77681_GAIN_HI(gain_HI));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_GAIN_MID,
+ AD77681_GAIN_MID_MSK,
+ AD77681_GAIN_MID(gain_MID));
+
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_GAIN_LO,
+ AD77681_GAIN_LOW_MSK,
+ AD77681_GAIN_LOW(gain_LO));
+
+ return ret;
+}
+
+/**
+ * Upload sequence for Programmamble FIR filter
+ * @param dev - The device structure.
+ * @param coeffs - Pointer to the desired filter coefficients array to be written
+ * @param num_coeffs - Count of active filter coeffs
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_programmable_filter(struct ad77681_dev *dev,
+ const float *coeffs,
+ uint8_t num_coeffs)
+{
+ uint8_t coeffs_buf[4], coeffs_index, check_back = 0, i, address;
+ uint32_t twait;
+ int32_t twos_complement, ret;
+ const uint8_t coeff_reg_length = 56;
+
+ /* Specific keys in the upload sequence */
+ const uint8_t key1 = 0xAC, key2 = 0x45, key3 = 0x55;
+ /* Scaling factor for all coefficients 2^22 */
+ const float coeff_scale_factor = (1 << 22);
+ /* Wait time in uS necessary to access the COEFF_CONTROL and */
+ /* COEFF_DATA registers. Twait = 512/MCLK */
+ twait = (uint32_t)(((512.0) / ((float)(dev->mclk))) * 1000.0) + 1;
+
+ /* Set Filter to FIR */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_DIGITAL_FILTER,
+ AD77681_DIGI_FILTER_FILTER_MSK,
+ AD77681_DIGI_FILTER_FILTER(AD77681_FIR));
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ /* Write the first access key to the ACCESS_KEY register */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_ACCESS_KEY,
+ AD77681_ACCESS_KEY_MSK,
+ AD77681_ACCESS_KEY(key1));
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ /* Write the second access key to the ACCESS_KEY register */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_ACCESS_KEY,
+ AD77681_ACCESS_KEY_MSK,
+ AD77681_ACCESS_KEY(key2));
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ /* Read the the ACCESS_KEY register bit 0, the key bit */
+ ret = ad77681_spi_read_mask(dev,
+ AD77681_REG_ACCESS_KEY,
+ AD77681_ACCESS_KEY_CHECK_MSK,
+ &check_back);
+
+ /* Checks ret and key bit, return FAILURE in case key bit not equal to 1 */
+ if ((ret < 0) || (check_back != 1))
+ return FAILURE;
+
+ /* Set the initial adress to 0 and enable the write and coefficient access bits */
+ address = AD77681_COEF_CONTROL_COEFFACCESSEN_MSK
+ | AD77681_COEF_CONTROL_COEFFWRITEEN_MSK;
+
+ /* The COEFF_DATA register has to be filled with 56 coeffs.*/
+ /* In case the number of active filter coefficient is less */
+ /* than 56, zeros will be padded before the desired coeff. */
+ for (i = 0; i < coeff_reg_length; i++) {
+ /* Set the coeff address */
+ ret = ad77681_spi_reg_write(dev,
+ AD77681_REG_COEFF_CONTROL,
+ address);
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ /* Wait for Twait uSeconds*/
+ udelay(twait);
+
+ /* Padding of zeros before the desired coef in case the coef count in less than 56 */
+ if((num_coeffs + i) < coeff_reg_length) {
+ /* wirte zeroes to COEFF_DATA, in case of less coeffs than 56*/
+ coeffs_buf[0] = AD77681_REG_WRITE(AD77681_REG_COEFF_DATA);
+ coeffs_buf[1] = 0;
+ coeffs_buf[2] = 0;
+ coeffs_buf[3] = 0;
+ } else {/* Writting of desired filter coefficients */
+ /* Computes the index of coefficients to be uploaded */
+ coeffs_index = (num_coeffs + i) - coeff_reg_length;
+ /* Scaling the coefficient value and converting it to 2's complement */
+ twos_complement = (int32_t)(coeffs[coeffs_index] * coeff_scale_factor);
+
+ /* Write coefficients to COEFF_DATA */
+ coeffs_buf[0] = AD77681_REG_WRITE(AD77681_REG_COEFF_DATA);
+ coeffs_buf[1] = (twos_complement & 0xFF0000) >> 16;
+ coeffs_buf[2] = (twos_complement & 0x00FF00) >> 8;
+ coeffs_buf[3] = (twos_complement & 0x0000FF);
+ }
+
+ ret = spi_write_and_read(dev->spi_desc, coeffs_buf, 4);
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ /* Increment the address*/
+ address++;
+ /* Wait for Twait uSeconds*/
+ udelay(twait);
+ }
+
+ /* Disable coefficient write */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_COEFF_CONTROL,
+ AD77681_COEF_CONTROL_COEFFWRITEEN_MSK,
+ AD77681_COEF_CONTROL_COEFFWRITEEN(0x00));
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ udelay(twait);
+
+ /* Disable coefficient access */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_COEFF_CONTROL,
+ AD77681_COEF_CONTROL_COEFFACCESSEN_MSK,
+ AD77681_COEF_CONTROL_COEFFACCESSEN(0x00));
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ /* Toggle the synchronization pulse and to begin reading data */
+ /* Write 0x800000 to COEFF_DATA */
+ coeffs_buf[0] = AD77681_REG_WRITE(AD77681_REG_COEFF_DATA);
+ coeffs_buf[1] = 0x80;
+ coeffs_buf[2] = 0x00;
+ coeffs_buf[3] = 0x00;
+
+ ret = spi_write_and_read(dev->spi_desc, coeffs_buf, 4);
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ /* Exit filter upload by wirting specific access key 0x55*/
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_ACCESS_KEY,
+ AD77681_ACCESS_KEY_MSK,
+ AD77681_ACCESS_KEY(key3));
+
+ /* Check return value before proceeding */
+ if (ret < 0)
+ return ret;
+
+ /* Send synchronization pulse */
+ ad77681_initiate_sync(dev);
+
+ return ret;
+}
+
+/**
+ * Read value from GPIOs present in AD7768-1 separately, or all GPIOS at once.
+ * @param dev - The device structure.
+ * @param value - Readed value.
+ * @param gpio_number - Number of GPIO, the value will be written into
+ * Accepted values: AD77681_GPIO0
+ * AD77681_GPIO1
+ * AD77681_GPIO2
+ * AD77681_GPIO3
+ * AD77681_ALL_GPIOS
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_gpio_read(struct ad77681_dev *dev,
+ uint8_t *value,
+ enum ad77681_gpios gpio_number)
+{
+ int32_t ret;
+
+ switch (gpio_number) {
+ case AD77681_GPIO0: /* Read to GPIO0 */
+ ret = ad77681_spi_read_mask(dev,
+ AD77681_REG_GPIO_READ,
+ AD77681_GPIO_READ_0_MSK,
+ value);
+ break;
+ case AD77681_GPIO1: /* Read to GPIO1 */
+ ret = ad77681_spi_read_mask(dev,
+ AD77681_REG_GPIO_READ,
+ AD77681_GPIO_READ_1_MSK,
+ value);
+ break;
+ case AD77681_GPIO2: /* Read to GPIO2 */
+ ret = ad77681_spi_read_mask(dev,
+ AD77681_REG_GPIO_READ,
+ AD77681_GPIO_READ_2_MSK,
+ value);
+ break;
+ case AD77681_GPIO3: /* Read to GPIO3 */
+ ret = ad77681_spi_read_mask(dev,
+ AD77681_REG_GPIO_READ,
+ AD77681_GPIO_READ_3_MSK,
+ value);
+ break;
+ case AD77681_ALL_GPIOS: /* Read to all GPIOs */
+ ret = ad77681_spi_read_mask(dev,
+ AD77681_REG_GPIO_READ,
+ AD77681_GPIO_READ_ALL_MSK,
+ value);
+ break;
+ default:
+ return FAILURE;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Write value to GPIOs present in AD7768-1 separately, or all GPIOS at once.
+ * @param dev - The device structure.
+ * @param value - Value to be written into GPIO
+ * Accepted values: GPIO_HIGH
+ * GPIO_LOW
+ * 4-bit value for all gpios
+ * @param gpio_number - Number of GPIO, the value will be written into
+ * Accepted values: AD77681_GPIO0
+ * AD77681_GPIO1
+ * AD77681_GPIO2
+ * AD77681_GPIO3
+ * AD77681_ALL_GPIOS
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_gpio_write(struct ad77681_dev *dev,
+ uint8_t value,
+ enum ad77681_gpios gpio_number)
+{
+ int32_t ret;
+
+ switch (gpio_number) {
+ case AD77681_GPIO0: /* Write to GPIO0 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_WRITE,
+ AD77681_GPIO_WRITE_0_MSK,
+ AD77681_GPIO_WRITE_0(value));
+ break;
+ case AD77681_GPIO1: /* Write to GPIO1 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_WRITE,
+ AD77681_GPIO_WRITE_1_MSK,
+ AD77681_GPIO_WRITE_1(value));
+ break;
+ case AD77681_GPIO2: /* Write to GPIO2 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_WRITE,
+ AD77681_GPIO_WRITE_2_MSK,
+ AD77681_GPIO_WRITE_2(value));
+ break;
+ case AD77681_GPIO3: /* Write to GPIO3 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_WRITE,
+ AD77681_GPIO_WRITE_3_MSK,
+ AD77681_GPIO_WRITE_3(value));
+ break;
+ case AD77681_ALL_GPIOS: /* Write to all GPIOs */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_WRITE,
+ AD77681_GPIO_WRITE_ALL_MSK,
+ AD77681_GPIO_WRITE_ALL(value));
+ break;
+ default:
+ return FAILURE;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Set AD7768-1s GPIO as input or output.
+ * @param dev - The device structure.
+ * @param direction - Direction of the GPIO
+ * Accepted values: GPIO_INPUT
+ * GPIO_OUTPUT
+ * 4-bit value for all gpios
+ * @param gpio_number - Number of GPIO, which will be affected
+ * Accepted values: AD77681_GPIO0
+ * AD77681_GPIO1
+ * AD77681_GPIO2
+ * AD77681_GPIO3
+ * AD77681_ALL_GPIOS
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_gpio_inout(struct ad77681_dev *dev,
+ uint8_t direction,
+ enum ad77681_gpios gpio_number)
+{
+ int32_t ret;
+
+ switch (gpio_number) {
+ case AD77681_GPIO0: /* Set direction of GPIO0 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_GPIO0_OP_EN_MSK,
+ AD77681_GPIO_CNTRL_GPIO0_OP_EN(direction));
+ break;
+ case AD77681_GPIO1: /* Set direction of GPIO1 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_GPIO1_OP_EN_MSK,
+ AD77681_GPIO_CNTRL_GPIO1_OP_EN(direction));
+ break;
+ case AD77681_GPIO2: /* Set direction of GPIO2 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_GPIO2_OP_EN_MSK,
+ AD77681_GPIO_CNTRL_GPIO2_OP_EN(direction));
+ break;
+ case AD77681_GPIO3: /* Set direction of GPIO3 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_GPIO3_OP_EN_MSK,
+ AD77681_GPIO_CNTRL_GPIO3_OP_EN(direction));
+ break;
+ case AD77681_ALL_GPIOS: /* Set direction of all GPIOs */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_ALL_GPIOS_OP_EN_MSK,
+ AD77681_GPIO_CNTRL_ALL_GPIOS_OP_EN(direction));
+ break;
+ default:
+ return FAILURE;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Enable global GPIO bit.
+ * This bit must be set high to change GPIO settings.
+ * @param dev - The device structure.
+ * @param gpio_enable - Enable or diable the global GPIO pin
+ * Accepted values: AD77681_GLOBAL_GPIO_ENABLE
+ * AD77681_GLOBAL_GPIO_DISABLE
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_global_gpio(struct ad77681_dev *dev,
+ enum ad77681_gobal_gpio_enable gpio_enable)
+{
+ return ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_UGPIO_EN_MSK,
+ AD77681_GPIO_CNTRL_UGPIO_EN(gpio_enable));
+}
+
+/**
+ * Read and write from ADC scratchpad register to check SPI Communication in
+ * the very beginning, during inicialization.
+ * @param dev - The device structure.
+ * @param sequence - The sequence which will be written into scratchpad and the
+ * readed sequence will be returned
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_scratchpad(struct ad77681_dev *dev,
+ uint8_t *sequence)
+{
+ int32_t ret;
+ const uint8_t check = *sequence;/* Save the original sequence */
+ uint8_t ret_sequence = 0;/* Return sequence */
+
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_SCRATCH_PAD,
+ AD77681_SCRATCHPAD_MSK,
+ AD77681_SCRATCHPAD(check));
+
+ ret |= ad77681_spi_read_mask(dev,
+ AD77681_REG_SCRATCH_PAD,
+ AD77681_SCRATCHPAD_MSK,
+ &ret_sequence);
+
+ if (check != ret_sequence)/* Compare original an returned sequence */
+ return FAILURE;
+
+ return ret;
+}
+
+/**
+ * Set AD7768-1s GPIO output type between strong driver and open drain.
+ * GPIO3 can not be accessed!
+ * @param dev - The device structure.
+ * @param gpio_number - AD7768-1s GPIO to be affected (Only GPIO0, GPIO1 and GPIO2)
+ * Accepted values: AD77681_GPIO0
+ * AD77681_GPIO1
+ * AD77681_GPIO2
+ * AD77681_ALL_GPIOS
+ *
+ * @param output_type - Output type of the GPIO
+ * Accepted values: AD77681_GPIO_STRONG_DRIVER
+ * AD77681_GPIO_OPEN_DRAIN
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_gpio_open_drain(struct ad77681_dev *dev,
+ enum ad77681_gpios gpio_number,
+ enum ad77681_gpio_output_type output_type)
+{
+ int32_t ret;
+
+ switch (gpio_number) {
+ case AD77681_GPIO0: /* Set ouptut type of GPIO0 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_GPIO0_OD_EN_MSK,
+ AD77681_GPIO_CNTRL_GPIO0_OD_EN(output_type));
+ break;
+ case AD77681_GPIO1: /* Set ouptut type of GPIO1 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_GPIO1_OD_EN_MSK,
+ AD77681_GPIO_CNTRL_GPIO1_OD_EN(output_type));
+ break;
+ case AD77681_GPIO2: /* Set ouptut type of GPIO2 */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_GPIO2_OD_EN_MSK,
+ AD77681_GPIO_CNTRL_GPIO2_OD_EN(output_type));
+ break;
+ case AD77681_ALL_GPIOS: /* Set ouptut type of all GPIOs */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_GPIO_CONTROL,
+ AD77681_GPIO_CNTRL_ALL_GPIOS_OD_EN_MSK,
+ AD77681_GPIO_CNTRL_ALL_GPIOS_OD_EN(output_type));
+ break;
+ default:
+ return FAILURE;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * Clear all error flags at once
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_clear_error_flags(struct ad77681_dev *dev)
+{
+ int32_t ret;
+
+ /* SPI ignore error CLEAR */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_SPI_DIAG_STATUS,
+ AD77681_SPI_IGNORE_ERROR_MSK,
+ AD77681_SPI_IGNORE_ERROR_CLR(ENABLE));
+ /* SPI read error CLEAR */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SPI_DIAG_STATUS,
+ AD77681_SPI_READ_ERROR_MSK,
+ AD77681_SPI_READ_ERROR_CLR(ENABLE));
+ /* SPI write error CLEAR */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SPI_DIAG_STATUS,
+ AD77681_SPI_WRITE_ERROR_MSK,
+ AD77681_SPI_WRITE_ERROR_CLR(ENABLE));
+ /* SPI CRC error CLEAR */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SPI_DIAG_STATUS,
+ AD77681_SPI_CRC_ERROR_MSK,
+ AD77681_SPI_CRC_ERROR_CLR(ENABLE));
+
+ return ret;
+}
+
+/**
+ * Enabling error flags. All error flags enabled by default
+ * @param dev - The device structure.
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_error_flags_enabe(struct ad77681_dev *dev)
+{
+ int32_t ret;
+
+ /* SPI ERRORS ENABLE */
+ /* SPI ignore error enable */
+ ret = ad77681_spi_write_mask(dev,
+ AD77681_REG_SPI_DIAG_ENABLE,
+ AD77681_SPI_DIAG_ERR_SPI_IGNORE_MSK,
+ AD77681_SPI_DIAG_ERR_SPI_IGNORE(ENABLE));
+ /* SPI Clock count error enable */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SPI_DIAG_ENABLE,
+ AD77681_SPI_DIAG_ERR_SPI_CLK_CNT_MSK,
+ AD77681_SPI_DIAG_ERR_SPI_CLK_CNT(ENABLE));
+ /* SPI Read error enable */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SPI_DIAG_ENABLE,
+ AD77681_SPI_DIAG_ERR_SPI_RD_MSK,
+ AD77681_SPI_DIAG_ERR_SPI_RD(ENABLE));
+ /* SPI Write error enable */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_SPI_DIAG_ENABLE,
+ AD77681_SPI_DIAG_ERR_SPI_WR_MSK,
+ AD77681_SPI_DIAG_ERR_SPI_WR(ENABLE));
+
+ /* ADC DIAG ERRORS ENABLE */
+ /* DLDO PSM error enable */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_ADC_DIAG_ENABLE,
+ AD77681_ADC_DIAG_ERR_DLDO_PSM_MSK,
+ AD77681_ADC_DIAG_ERR_DLDO_PSM(ENABLE));
+ /* ALDO PSM error enable */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_ADC_DIAG_ENABLE,
+ AD77681_ADC_DIAG_ERR_ALDO_PSM_MSK,
+ AD77681_ADC_DIAG_ERR_ALDO_PSM(ENABLE));
+ /* Filter saturated error enable */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_ADC_DIAG_ENABLE,
+ AD77681_ADC_DIAG_ERR_FILT_SAT_MSK,
+ AD77681_ADC_DIAG_ERR_FILT_SAT(ENABLE));
+ /* Filter not settled error enable */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_ADC_DIAG_ENABLE,
+ AD77681_ADC_DIAG_ERR_FILT_NOT_SET_MSK,
+ AD77681_ADC_DIAG_ERR_FILT_NOT_SET(ENABLE));
+ /* External clock check error enable */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_ADC_DIAG_ENABLE,
+ AD77681_ADC_DIAG_ERR_EXT_CLK_QUAL_MSK,
+ AD77681_ADC_DIAG_ERR_EXT_CLK_QUAL(ENABLE));
+
+ /* DIG DIAG ENABLE */
+ /* Memory map CRC error enabled */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_DIG_DIAG_ENABLE,
+ AD77681_DIG_DIAG_ERR_MEMMAP_CRC_MSK,
+ AD77681_DIG_DIAG_ERR_MEMMAP_CRC(ENABLE));
+ /* RAM CRC error enabled */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_DIG_DIAG_ENABLE,
+ AD77681_DIG_DIAG_ERR_RAM_CRC_MSK,
+ AD77681_DIG_DIAG_ERR_RAM_CRC(ENABLE));
+ /* FUSE CRC error enabled */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_DIG_DIAG_ENABLE,
+ AD77681_DIG_DIAG_ERR_FUSE_CRC_MSK,
+ AD77681_DIG_DIAG_ERR_FUSE_CRC(ENABLE));
+ /* Enable MCLK Counter */
+ ret |= ad77681_spi_write_mask(dev,
+ AD77681_REG_DIG_DIAG_ENABLE,
+ AD77681_DIG_DIAG_FREQ_COUNT_EN_MSK,
+ AD77681_DIG_DIAG_FREQ_COUNT_EN(ENABLE));
+
+ return ret;
+}
+
+/**
+ * Read from all ADC status registers
+ * @param dev - The device structure.
+ * @param status - Structure with all satuts bits
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_status(struct ad77681_dev *dev,
+ struct ad77681_status_registers *status)
+{
+ int32_t ret;
+ uint8_t buf[3];
+
+ /* Master status register */
+ ret = ad77681_spi_reg_read(dev, AD77681_REG_MASTER_STATUS,buf);
+ status->master_error = buf[1] & AD77681_MASTER_ERROR_MSK;
+ status->adc_error = buf[1] & AD77681_MASTER_ADC_ERROR_MSK;
+ status->dig_error = buf[1] & AD77681_MASTER_DIG_ERROR_MSK;
+ status->adc_err_ext_clk_qual = buf[1] & AD77681_MASTER_DIG_ERR_EXT_CLK_MSK;
+ status->adc_filt_saturated = buf[1] & AD77681_MASTER_FILT_SAT_MSK;
+ status->adc_filt_not_settled = buf[1] & AD77681_MASTER_FILT_NOT_SET_MSK;
+ status->spi_error = buf[1] & AD77681_MASTER_SPI_ERROR_MSK;
+ status->por_flag = buf[1] & AD77681_MASTER_POR_FLAG_MSK;
+ /* SPI diag status register */
+ ret |= ad77681_spi_reg_read(dev, AD77681_REG_SPI_DIAG_STATUS, buf);
+ status->spi_ignore = buf[1] & AD77681_SPI_IGNORE_ERROR_MSK;
+ status->spi_clock_count = buf[1] & AD77681_SPI_CLK_CNT_ERROR_MSK;
+ status->spi_read_error = buf[1] & AD77681_SPI_READ_ERROR_MSK;
+ status->spi_write_error = buf[1] & AD77681_SPI_WRITE_ERROR_MSK;
+ status->spi_crc_error = buf[1] & AD77681_SPI_CRC_ERROR_MSK;
+ /* ADC diag status register */
+ ret |= ad77681_spi_reg_read(dev, AD77681_REG_ADC_DIAG_STATUS,buf);
+ status->dldo_psm_error = buf[1] & AD77681_ADC_DLDO_PSM_ERROR_MSK;
+ status->aldo_psm_error = buf[1] & AD77681_ADC_ALDO_PSM_ERROR_MSK;
+ status->ref_det_error = buf[1] & AD77681_ADC_REF_DET_ERROR_MSK;
+ status->filt_sat_error = buf[1] & AD77681_ADC_FILT_SAT_MSK;
+ status->filt_not_set_error = buf[1] & AD77681_ADC_FILT_NOT_SET_MSK;
+ status->ext_clk_qual_error = buf[1] & AD77681_ADC_DIG_ERR_EXT_CLK_MSK;
+ /* DIG diag status register */
+ ret |= ad77681_spi_reg_read(dev, AD77681_REG_DIG_DIAG_STATUS,buf);
+ status->memoy_map_crc_error = buf[1] & AD77681_DIG_MEMMAP_CRC_ERROR_MSK;
+ status->ram_crc_error = buf[1] & AD77681_DIG_RAM_CRC_ERROR_MSK;
+ status->fuse_crc_error = buf[1] & AD77681_DIG_FUS_CRC_ERROR_MSK;
+
+ return ret;
+}
+
+/**
+ * Initialize the device.
+ * @param device - The device structure.
+ * @param init_param - The structure that contains the device initial
+ * parameters.
+ * @param status - The structure that will contains the ADC status
+ * @return 0 in case of success, negative error code otherwise.
+ */
+int32_t ad77681_setup(struct ad77681_dev **device,
+ struct ad77681_init_param init_param,
+ struct ad77681_status_registers **status)
+{
+ struct ad77681_dev *dev;
+ struct ad77681_status_registers *stat;
+ int32_t ret;
+ uint8_t scratchpad_check = 0xAD;
+
+ dev = (struct ad77681_dev *)malloc(sizeof(*dev));
+ if (!dev) {
+ return -1;
+ }
+
+ stat = (struct ad77681_status_registers *)malloc(sizeof(*stat));
+ if (!stat) {
+ free(dev);
+ return -1;
+ }
+
+ dev->power_mode = init_param.power_mode;
+ dev->mclk_div = init_param.mclk_div;
+ dev->conv_diag_sel = init_param.conv_diag_sel;
+ dev->conv_mode = init_param.conv_mode;
+ dev->diag_mux_sel = init_param.diag_mux_sel;
+ dev->conv_len = init_param.conv_len;
+ dev->crc_sel = AD77681_NO_CRC;
+ dev->status_bit = init_param.status_bit;
+ dev->VCM_out = init_param.VCM_out;
+ dev->AINn = init_param.AINn;
+ dev->AINp = init_param.AINp;
+ dev->REFn = init_param.REFn;
+ dev->REFp = init_param.REFp;
+ dev->filter = init_param.filter;
+ dev->decimate = init_param.decimate;
+ dev->sinc3_osr = init_param.sinc3_osr;
+ dev->vref = init_param.vref;
+ dev->mclk = init_param.mclk;
+ dev->sample_rate = init_param.sample_rate;
+ dev->data_frame_byte = init_param.data_frame_byte;
+
+ ret = spi_init(&dev->spi_desc, &init_param.spi_eng_dev_init);
+ if (ret < 0) {
+ free(dev);
+ free(stat);
+ return ret;
+ }
+
+ ret |= ad77681_soft_reset(dev);
+
+ udelay(200);
+
+ /* Check physical connection using scratchpad*/
+ if (ad77681_scratchpad(dev, &scratchpad_check) == FAILURE) {
+ scratchpad_check = 0xAD;/* If failure, second try */
+ ret |= (ad77681_scratchpad(dev, &scratchpad_check));
+ if(ret == FAILURE) {
+ free(dev);
+ free(stat);
+ return ret;
+ }
+ }
+ ret |= ad77681_set_power_mode(dev, dev->power_mode);
+ ret |= ad77681_set_mclk_div(dev, dev->mclk_div);
+ ret |= ad77681_set_conv_mode(dev,
+ dev->conv_mode,
+ dev->diag_mux_sel,
+ dev->conv_diag_sel);
+ ret |= ad77681_set_convlen(dev, dev->conv_len);
+ ret |= ad77681_set_status_bit(dev, dev->status_bit);
+ ret |= ad77681_set_crc_sel(dev, init_param.crc_sel);
+ ret |= ad77681_set_VCM_output(dev, dev->VCM_out);
+ ret |= ad77681_set_AINn_buffer(dev, dev->AINn);
+ ret |= ad77681_set_AINp_buffer(dev, dev->AINp);
+ ret |= ad77681_set_REFn_buffer(dev, dev->REFn);
+ ret |= ad77681_set_REFp_buffer(dev, dev->REFp);
+ ret |= ad77681_set_filter_type(dev, dev->decimate, dev->filter, dev->sinc3_osr);
+ ret |= ad77681_error_flags_enabe(dev);
+ ret |= ad77681_clear_error_flags(dev);
+ ret |= ad77681_status(dev, stat);
+ ad77681_get_frame_byte(dev);
+ ad77681_update_sample_rate(dev);
+ *status = stat;
+ *device = dev;
+
+ if (!ret)
+ printf("ad77681 successfully initialized\n");
+
+ return ret;
+}
+
+
diff -r 3c3bc5b9174a -r abe97d9dd504 ad77681.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ad77681.h Mon Mar 15 06:51:56 2021 +0000
@@ -0,0 +1,684 @@
+/***************************************************************************//**
+ * @file ad77681.h
+ * @brief Header file of the AD7768-1 Driver.
+ * @author SPopa (stefan.popa@analog.com)
+********************************************************************************
+ * Copyright 2017(c) Analog Devices, Inc.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * - Neither the name of Analog Devices, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * - The use of this software may or may not infringe the patent rights
+ * of one or more patent holders. This license does not release you
+ * from the requirement that you obtain separate licenses from these
+ * patent holders to use this software.
+ * - Use of the software either in source or binary form, must be run
+ * on or directly connected to an Analog Devices Inc. component.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef SRC_AD77681_H_
+#define SRC_AD77681_H_
+
+#include "platform_drivers.h"
+
+/******************************************************************************/
+/********************** Macros and Constants Definitions **********************/
+/******************************************************************************/
+#define AD77681_REG_CHIP_TYPE 0x3
+#define AD77681_REG_PROD_ID_L 0x4
+#define AD77681_REG_PROD_ID_H 0x5
+#define AD77681_REG_CHIP_GRADE 0x6
+#define AD77681_REG_SCRATCH_PAD 0x0A
+#define AD77681_REG_VENDOR_L 0x0C
+#define AD77681_REG_VENDOR_H 0x0D
+#define AD77681_REG_INTERFACE_FORMAT 0x14
+#define AD77681_REG_POWER_CLOCK 0x15
+#define AD77681_REG_ANALOG 0x16
+#define AD77681_REG_ANALOG2 0x17
+#define AD77681_REG_CONVERSION 0x18
+#define AD77681_REG_DIGITAL_FILTER 0x19
+#define AD77681_REG_SINC3_DEC_RATE_MSB 0x1A
+#define AD77681_REG_SINC3_DEC_RATE_LSB 0x1B
+#define AD77681_REG_DUTY_CYCLE_RATIO 0x1C
+#define AD77681_REG_SYNC_RESET 0x1D
+#define AD77681_REG_GPIO_CONTROL 0x1E
+#define AD77681_REG_GPIO_WRITE 0x1F
+#define AD77681_REG_GPIO_READ 0x20
+#define AD77681_REG_OFFSET_HI 0x21
+#define AD77681_REG_OFFSET_MID 0x22
+#define AD77681_REG_OFFSET_LO 0x23
+#define AD77681_REG_GAIN_HI 0x24
+#define AD77681_REG_GAIN_MID 0x25
+#define AD77681_REG_GAIN_LO 0x26
+#define AD77681_REG_SPI_DIAG_ENABLE 0x28
+#define AD77681_REG_ADC_DIAG_ENABLE 0x29
+#define AD77681_REG_DIG_DIAG_ENABLE 0x2A
+#define AD77681_REG_ADC_DATA 0x2C
+#define AD77681_REG_MASTER_STATUS 0x2D
+#define AD77681_REG_SPI_DIAG_STATUS 0x2E
+#define AD77681_REG_ADC_DIAG_STATUS 0x2F
+#define AD77681_REG_DIG_DIAG_STATUS 0x30
+#define AD77681_REG_MCLK_COUNTER 0x31
+
+/* AD77681_REG_INTERFACE_FORMAT */
+#define AD77681_INTERFACE_CRC_EN_MSK (0x1 << 6)
+#define AD77681_INTERFACE_CRC_EN(x) (((x) & 0x1) << 6)
+#define AD77681_INTERFACE_CRC_TYPE_MSK (0x1 << 5)
+#define AD77681_INTERFACE_CRC_TYPE(x) (((x) & 0x1) << 5)
+#define AD77681_INTERFACE_STATUS_EN_MSK (0x1 << 4)
+#define AD77681_INTERFACE_STATUS_EN(x) (((x) & 0x1) << 4)
+#define AD77681_INTERFACE_CONVLEN_MSK (0x1 << 3)
+#define AD77681_INTERFACE_CONVLEN(x) (((x) & 0x1) << 3)
+#define AD77681_INTERFACE_RDY_EN_MSK (0x1 << 2)
+#define AD77681_INTERFACE_RDY_EN(x) (((x) & 0x1) << 3)
+#define AD77681_INTERFACE_CONT_READ_MSK (0x1 << 0)
+#define AD77681_INTERFACE_CONT_READ_EN(x) (((x) & 0x1) << 0)
+#define AD77681_REG_COEFF_CONTROL 0x32
+#define AD77681_REG_COEFF_DATA 0x33
+#define AD77681_REG_ACCESS_KEY 0x34
+
+/* AD77681_REG_SCRATCH_PAD*/
+#define AD77681_SCRATCHPAD_MSK (0xFF << 0)
+#define AD77681_SCRATCHPAD(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_POWER_CLOCK */
+#define AD77681_POWER_CLK_PWRMODE_MSK 0x3
+#define AD77681_POWER_CLK_PWRMODE(x) (((x) & 0x3) << 0)
+#define AD77681_POWER_CLK_MOD_OUT_MSK (0x1 << 2)
+#define AD77681_POWER_CLK_MOD_OUT(x) (((x) & 0x1) << 2)
+#define AD77681_POWER_CLK_POWER_DOWN 0x08
+#define AD77681_POWER_CLK_MCLK_DIV_MSK (0x3 << 4)
+#define AD77681_POWER_CLK_MCLK_DIV(x) (((x) & 0x3) << 4)
+#define AD77681_POWER_CLK_CLOCK_SEL_MSK (0x3 << 6)
+#define AD77681_POWER_CLK_CLOCK_SEL(x) (((x) & 0x3) << 6)
+
+/* AD77681_CONVERSION_REG */
+#define AD77681_CONVERSION_DIAG_MUX_MSK (0xF << 4)
+#define AD77681_CONVERSION_DIAG_MUX_SEL(x) (((x) & 0xF) << 4)
+#define AD77681_CONVERSION_DIAG_SEL_MSK (0x1 << 3)
+#define AD77681_CONVERSION_DIAG_SEL(x) (((x) & 0x1) << 3)
+#define AD77681_CONVERSION_MODE_MSK (0x7 << 0)
+#define AD77681_CONVERSION_MODE(x) (((x) & 0x7) << 0)
+
+/* AD77681_REG_ANALOG */
+#define AD77681_ANALOG_REF_BUF_POS_MSK (0x3 << 6)
+#define AD77681_ANALOG_REF_BUF_POS(x) (((x) & 0x3) << 6)
+#define AD77681_ANALOG_REF_BUF_NEG_MSK (0x3 << 4)
+#define AD77681_ANALOG_REF_BUF_NEG(x) (((x) & 0x3) << 4)
+#define AD77681_ANALOG_AIN_BUF_POS_OFF_MSK (0x1 << 1)
+#define AD77681_ANALOG_AIN_BUF_POS_OFF(x) (((x) & 0x1) << 1)
+#define AD77681_ANALOG_AIN_BUF_NEG_OFF_MSK (0x1 << 0)
+#define AD77681_ANALOG_AIN_BUF_NEG_OFF(x) (((x) & 0x1) << 0)
+
+/* AD77681_REG_ANALOG2 */
+#define AD77681_ANALOG2_VCM_MSK (0x7 << 0)
+#define AD77681_ANALOG2_VCM(x) (((x) & 0x7) << 0)
+
+/* AD77681_REG_DIGITAL_FILTER */
+#define AD77681_DIGI_FILTER_60HZ_REJ_EN_MSK (0x1 << 7)
+#define AD77681_DIGI_FILTER_60HZ_REJ_EN(x) (((x) & 0x1) << 7)
+#define AD77681_DIGI_FILTER_FILTER_MSK (0x7 << 4)
+#define AD77681_DIGI_FILTER_FILTER(x) (((x) & 0x7) << 4)
+#define AD77681_DIGI_FILTER_DEC_RATE_MSK (0x7 << 0)
+#define AD77681_DIGI_FILTER_DEC_RATE(x) (((x) & 0x7) << 0)
+
+/* AD77681_REG_SINC3_DEC_RATE_MSB */
+#define AD77681_SINC3_DEC_RATE_MSB_MSK (0x0F << 0)
+#define AD77681_SINC3_DEC_RATE_MSB(x) (((x) & 0x0F) << 0)
+
+/* AD77681_REG_SINC3_DEC_RATE_LSB */
+#define AD77681_SINC3_DEC_RATE_LSB_MSK (0xFF << 0)
+#define AD77681_SINC3_DEC_RATE_LSB(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_DUTY_CYCLE_RATIO */
+#define AD77681_DC_RATIO_IDLE_TIME_MSK (0xFF << 0)
+#define AD77681_DC_RATIO_IDLE_TIME(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_SYNC_RESET */
+#define AD77681_SYNC_RST_SPI_STARTB_MSK (0x1 << 7)
+#define AD77681_SYNC_RST_SPI_STARTB(x) (((x) & 0x1) << 7)
+#define AD77681_SYNC_RST_SYNCOUT_EDGE_MSK (0x1 << 6)
+#define AD77681_SYNC_RST_SYNCOUT_EDGE(x) (((x) & 0x1) << 6)
+#define AD77681_SYNC_RST_GPIO_START_EN_MSK (0x1 << 3)
+#define AD77681_SYNC_RST_GPIO_START_EN(x) (((x) & 0x1) << 3)
+#define AD77681_SYNC_RST_SPI_RESET_MSK (0x3 << 0)
+#define AD77681_SYNC_RST_SPI_RESET(x) (((x) & 0x3) << 0)
+
+/* AD77681_REG_GPIO_CONTROL */
+#define AD77681_GPIO_CNTRL_UGPIO_EN_MSK (0x1 << 7)
+#define AD77681_GPIO_CNTRL_UGPIO_EN(x) (((x) & 0x1) << 7)
+#define AD77681_GPIO_CNTRL_GPIO2_OD_EN_MSK (0x1 << 6)
+#define AD77681_GPIO_CNTRL_GPIO2_OD_EN(x) (((x) & 0x1) << 6)
+#define AD77681_GPIO_CNTRL_GPIO1_OD_EN_MSK (0x1 << 5)
+#define AD77681_GPIO_CNTRL_GPIO1_OD_EN(x) (((x) & 0x1) << 5)
+#define AD77681_GPIO_CNTRL_GPIO0_OD_EN_MSK (0x1 << 4)
+#define AD77681_GPIO_CNTRL_GPIO0_OD_EN(x) (((x) & 0x1) << 4)
+#define AD77681_GPIO_CNTRL_ALL_GPIOS_OD_EN_MSK (0x7 << 4)
+#define AD77681_GPIO_CNTRL_ALL_GPIOS_OD_EN(x) (((x) & 0x7) << 4)
+#define AD77681_GPIO_CNTRL_GPIO3_OP_EN_MSK (0x1 << 3)
+#define AD77681_GPIO_CNTRL_GPIO3_OP_EN(x) (((x) & 0x1) << 3)
+#define AD77681_GPIO_CNTRL_GPIO2_OP_EN_MSK (0x1 << 2)
+#define AD77681_GPIO_CNTRL_GPIO2_OP_EN(x) (((x) & 0x1) << 2)
+#define AD77681_GPIO_CNTRL_GPIO1_OP_EN_MSK (0x1 << 1)
+#define AD77681_GPIO_CNTRL_GPIO1_OP_EN(x) (((x) & 0x1) << 1)
+#define AD77681_GPIO_CNTRL_GPIO0_OP_EN_MSK (0x1 << 0)
+#define AD77681_GPIO_CNTRL_GPIO0_OP_EN(x) (((x) & 0x1) << 0)
+#define AD77681_GPIO_CNTRL_ALL_GPIOS_OP_EN_MSK (0xF << 0)
+#define AD77681_GPIO_CNTRL_ALL_GPIOS_OP_EN(x) (((x) & 0xF) << 0)
+
+/* AD77681_REG_GPIO_WRITE */
+#define AD77681_GPIO_WRITE_3_MSK (0x1 << 3)
+#define AD77681_GPIO_WRITE_3(x) (((x) & 0x1) << 3)
+#define AD77681_GPIO_WRITE_2_MSK (0x1 << 2)
+#define AD77681_GPIO_WRITE_2(x) (((x) & 0x1) << 2)
+#define AD77681_GPIO_WRITE_1_MSK (0x1 << 1)
+#define AD77681_GPIO_WRITE_1(x) (((x) & 0x1) << 1)
+#define AD77681_GPIO_WRITE_0_MSK (0x1 << 0)
+#define AD77681_GPIO_WRITE_0(x) (((x) & 0x1) << 0)
+#define AD77681_GPIO_WRITE_ALL_MSK (0xF << 0)
+#define AD77681_GPIO_WRITE_ALL(x) (((x) & 0xF))
+
+/* AD77681_REG_GPIO_READ */
+#define AD77681_GPIO_READ_3_MSK (0x1 << 3)
+#define AD77681_GPIO_READ_2_MSK (0x1 << 2)
+#define AD77681_GPIO_READ_1_MSK (0x1 << 1)
+#define AD77681_GPIO_READ_0_MSK (0x1 << 0)
+#define AD77681_GPIO_READ_ALL_MSK (0xF << 0)
+
+/* AD77681_REG_OFFSET_HI */
+#define AD77681_OFFSET_HI_MSK (0xFF << 0)
+#define AD77681_OFFSET_HI(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_OFFSET_MID */
+#define AD77681_OFFSET_MID_MSK (0xFF << 0)
+#define AD77681_OFFSET_MID(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_OFFSET_LO */
+#define AD77681_OFFSET_LO_MSK (0xFF << 0)
+#define AD77681_OFFSET_LO(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_GAIN_HI */
+#define AD77681_GAIN_HI_MSK (0xFF << 0)
+#define AD77681_GAIN_HI(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_GAIN_MID */
+#define AD77681_GAIN_MID_MSK (0xFF << 0)
+#define AD77681_GAIN_MID(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_GAIN_HI */
+#define AD77681_GAIN_LOW_MSK (0xFF << 0)
+#define AD77681_GAIN_LOW(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_SPI_DIAG_ENABLE */
+#define AD77681_SPI_DIAG_ERR_SPI_IGNORE_MSK (0x1 << 4)
+#define AD77681_SPI_DIAG_ERR_SPI_IGNORE(x) (((x) & 0x1) << 4)
+#define AD77681_SPI_DIAG_ERR_SPI_CLK_CNT_MSK (0x1 << 3)
+#define AD77681_SPI_DIAG_ERR_SPI_CLK_CNT(x) (((x) & 0x1) << 3)
+#define AD77681_SPI_DIAG_ERR_SPI_RD_MSK (0x1 << 2)
+#define AD77681_SPI_DIAG_ERR_SPI_RD(x) (((x) & 0x1) << 2)
+#define AD77681_SPI_DIAG_ERR_SPI_WR_MSK (0x1 << 1)
+#define AD77681_SPI_DIAG_ERR_SPI_WR(x) (((x) & 0x1) << 1)
+
+/* AD77681_REG_ADC_DIAG_ENABLE */
+#define AD77681_ADC_DIAG_ERR_DLDO_PSM_MSK (0x1 << 5)
+#define AD77681_ADC_DIAG_ERR_DLDO_PSM(x) (((x) & 0x1) << 5)
+#define AD77681_ADC_DIAG_ERR_ALDO_PSM_MSK (0x1 << 4)
+#define AD77681_ADC_DIAG_ERR_ALDO_PSM(x) (((x) & 0x1) << 4)
+#define AD77681_ADC_DIAG_ERR_FILT_SAT_MSK (0x1 << 2)
+#define AD77681_ADC_DIAG_ERR_FILT_SAT(x) (((x) & 0x1) << 2)
+#define AD77681_ADC_DIAG_ERR_FILT_NOT_SET_MSK (0x1 << 1)
+#define AD77681_ADC_DIAG_ERR_FILT_NOT_SET(x) (((x) & 0x1) << 1)
+#define AD77681_ADC_DIAG_ERR_EXT_CLK_QUAL_MSK (0x1 << 0)
+#define AD77681_ADC_DIAG_ERR_EXT_CLK_QUAL(x) (((x) & 0x1) << 0)
+
+/* AD77681_REG_DIG_DIAG_ENABLE */
+#define AD77681_DIG_DIAG_ERR_MEMMAP_CRC_MSK (0x1 << 4)
+#define AD77681_DIG_DIAG_ERR_MEMMAP_CRC(x) (((x) & 0x1) << 4)
+#define AD77681_DIG_DIAG_ERR_RAM_CRC_MSK (0x1 << 3)
+#define AD77681_DIG_DIAG_ERR_RAM_CRC(x) (((x) & 0x1) << 3)
+#define AD77681_DIG_DIAG_ERR_FUSE_CRC_MSK (0x1 << 2)
+#define AD77681_DIG_DIAG_ERR_FUSE_CRC(x) (((x) & 0x1) << 2)
+#define AD77681_DIG_DIAG_FREQ_COUNT_EN_MSK (0x1 << 0)
+#define AD77681_DIG_DIAG_FREQ_COUNT_EN(x) (((x) & 0x1) << 0)
+
+/* AD77681_REG_MASTER_STATUS */
+#define AD77681_MASTER_ERROR_MSK (0x1 << 7)
+#define AD77681_MASTER_ADC_ERROR_MSK (0x1 << 6)
+#define AD77681_MASTER_DIG_ERROR_MSK (0x1 << 5)
+#define AD77681_MASTER_DIG_ERR_EXT_CLK_MSK (0x1 << 4)
+#define AD77681_MASTER_FILT_SAT_MSK (0x1 << 3)
+#define AD77681_MASTER_FILT_NOT_SET_MSK (0x1 << 2)
+#define AD77681_MASTER_SPI_ERROR_MSK (0x1 << 1)
+#define AD77681_MASTER_POR_FLAG_MSK (0x1 << 0)
+
+/* AD77681_REG_SPI_DIAG_STATUS */
+#define AD77681_SPI_IGNORE_ERROR_MSK (0x1 << 4)
+#define AD77681_SPI_IGNORE_ERROR_CLR(x) (((x) & 0x1) << 4)
+#define AD77681_SPI_CLK_CNT_ERROR_MSK (0x1 << 3)
+#define AD77681_SPI_READ_ERROR_MSK (0x1 << 2)
+#define AD77681_SPI_READ_ERROR_CLR(x) (((x) & 0x1) << 2)
+#define AD77681_SPI_WRITE_ERROR_MSK (0x1 << 1)
+#define AD77681_SPI_WRITE_ERROR_CLR(x) (((x) & 0x1) << 1)
+#define AD77681_SPI_CRC_ERROR_MSK (0x1 << 0)
+#define AD77681_SPI_CRC_ERROR_CLR(x) (((x) & 0x1) << 0)
+
+/* AD77681_REG_ADC_DIAG_STATUS */
+#define AD77681_ADC_DLDO_PSM_ERROR_MSK (0x1 << 5)
+#define AD77681_ADC_ALDO_PSM_ERROR_MSK (0x1 << 4)
+#define AD77681_ADC_REF_DET_ERROR_MSK (0x1 << 3)
+#define AD77681_ADC_FILT_SAT_MSK (0x1 << 2)
+#define AD77681_ADC_FILT_NOT_SET_MSK (0x1 << 1)
+#define AD77681_ADC_DIG_ERR_EXT_CLK_MSK (0x1 << 0)
+
+/* AD77681_REG_DIG_DIAG_STATUS */
+#define AD77681_DIG_MEMMAP_CRC_ERROR_MSK (0x1 << 4)
+#define AD77681_DIG_RAM_CRC_ERROR_MSK (0x1 << 3)
+#define AD77681_DIG_FUS_CRC_ERROR_MSK (0x1 << 2)
+
+/* AD77681_REG_MCLK_COUNTER */
+#define AD77681_MCLK_COUNTER_MSK (0xFF << 0)
+#define AD77681_MCLK_COUNTER(x) (((x) & 0xFF) << 0)
+
+/* AD77681_REG_COEFF_CONTROL */
+#define AD77681_COEF_CONTROL_COEFFACCESSEN_MSK (0x1 << 7)
+#define AD77681_COEF_CONTROL_COEFFACCESSEN(x) (((x) & 0x1) << 7)
+#define AD77681_COEF_CONTROL_COEFFWRITEEN_MSK (0x1 << 6)
+#define AD77681_COEF_CONTROL_COEFFWRITEEN(x) (((x) & 0x1) << 6)
+#define AD77681_COEF_CONTROL_COEFFADDR_MSK (0x3F << 5)
+#define AD77681_COEF_CONTROL_COEFFADDR(x) (((x) & 0x3F) << 5)
+
+/* AD77681_REG_COEFF_DATA */
+#define AD77681_COEFF_DATA_USERCOEFFEN_MSK (0x1 << 23)
+#define AD77681_COEFF_DATA_USERCOEFFEN(x) (((x) & 0x1) << 23)
+#define AD77681_COEFF_DATA_COEFFDATA_MSK (0x7FFFFF << 22)
+#define AD77681_COEFF_DATA_COEFFDATA(x) (((x) & 0x7FFFFF) << 22)
+
+/* AD77681_REG_ACCESS_KEY */
+#define AD77681_ACCESS_KEY_MSK (0xFF << 0)
+#define AD77681_ACCESS_KEY(x) (((x) & 0xFF) << 0)
+#define AD77681_ACCESS_KEY_CHECK_MSK (0x1 << 0)
+
+#define AD77681_REG_READ(x) ( (1 << 6) | (x & 0xFF) ) // Read from register x
+#define AD77681_REG_WRITE(x) ( (~(1 << 6)) & (x & 0xFF) ) // Write to register x
+
+/* 8-bits wide checksum generated using the polynomial */
+#define AD77681_CRC8_POLY 0x07 // x^8 + x^2 + x^1 + x^0
+
+/* Initial CRC for continuous read mode */
+#define INITIAL_CRC_CRC8 0x03
+#define INITIAL_CRC_XOR 0x6C
+#define INITIAL_CRC 0x00
+
+#define CRC_DEBUG
+
+/* AD7768-1 */
+/* A special key for exit the contiuous read mode, taken from the AD7768-1 datasheet */
+#define EXIT_CONT_READ 0x6C
+/* Bit resolution of the AD7768-1 */
+#define AD7768_N_BITS 24
+/* Full scale of the AD7768-1 = 2^24 = 16777216 */
+#define AD7768_FULL_SCALE (1 << AD7768_N_BITS)
+/* Half scale of the AD7768-1 = 2^23 = 8388608 */
+#define AD7768_HALF_SCALE (1 << (AD7768_N_BITS - 1))
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define ENABLE 1
+#define DISABLE 0
+
+/*****************************************************************************/
+/*************************** Types Declarations *******************************/
+/******************************************************************************/
+enum ad77681_power_mode {
+ AD77681_ECO = 0,
+ AD77681_MEDIAN = 2,
+ AD77681_FAST = 3,
+};
+
+enum ad77681_mclk_div {
+ AD77681_MCLK_DIV_16 = 0,
+ AD77681_MCLK_DIV_8 = 1,
+ AD77681_MCLK_DIV_4 = 2,
+ AD77681_MCLK_DIV_2 = 3
+};
+
+enum ad77681_conv_mode {
+ AD77681_CONV_CONTINUOUS = 0,
+ AD77681_CONV_ONE_SHOT = 1,
+ AD77681_CONV_SINGLE = 2,
+ AD77681_CONV_PERIODIC = 3,
+ AD77681_CONV_STANDBY = 4
+};
+
+enum ad77681_conv_len {
+ AD77681_CONV_24BIT = 0,
+ AD77681_CONV_16BIT = 1
+};
+
+enum ad77681_rdy_dout {
+ AD77681_RDY_DOUT_EN,
+ AD77681_RDY_DOUT_DIS
+};
+
+enum ad77681_conv_diag_mux {
+ AD77681_TEMP_SENSOR = 0x0,
+ AD77681_AIN_SHORT= 0x8,
+ AD77681_POSITIVE_FS = 0x9,
+ AD77681_NEGATIVE_FS = 0xA
+};
+
+enum ad77681_crc_sel {
+ AD77681_CRC,
+ AD77681_XOR,
+ AD77681_NO_CRC
+};
+
+/* Filter tye FIR, SINC3, SINC5 */
+enum ad77681_filter_type {
+ AD77681_SINC5 = 0,
+ AD77681_SINC5_DECx8 = 1,
+ AD77681_SINC5_DECx16 = 2,
+ AD77681_SINC3 = 3,
+ AD77681_FIR = 4
+};
+
+/* Dectimation ratios for SINC5 and FIR */
+enum ad77681_sinc5_fir_decimate {
+ AD77681_SINC5_FIR_DECx32 = 0,
+ AD77681_SINC5_FIR_DECx64 = 1,
+ AD77681_SINC5_FIR_DECx128 = 2,
+ AD77681_SINC5_FIR_DECx256 = 3,
+ AD77681_SINC5_FIR_DECx512 = 4,
+ AD77681_SINC5_FIR_DECx1024 = 5
+};
+
+/* Sleep / Power up */
+enum ad77681_sleep_wake {
+ AD77681_SLEEP = 1,
+ AD77681_WAKE = 0
+};
+
+/* Reset option */
+enum ad7761_reset_option {
+ AD77681_SOFT_RESET,
+ AD77681_HARD_RESET
+};
+/* AIN- precharge */
+enum ad77681_AINn_precharge {
+ AD77681_AINn_ENABLED = 0,
+ AD77681_AINn_DISABLED = 1
+};
+
+/* AIN+ precharge */
+enum ad77681_AINp_precharge {
+ AD77681_AINp_ENABLED = 0,
+ AD77681_AINp_DISABLED = 1
+};
+
+/* REF- buffer */
+enum ad77681_REFn_buffer {
+ AD77681_BUFn_ENABLED = 0,
+ AD77681_BUFn_DISABLED = 1,
+ AD77681_BUFn_FULL_BUFFER_ON = 2
+};
+
+/* REF+ buffer */
+enum ad77681_REFp_buffer {
+ AD77681_BUFp_ENABLED = 0,
+ AD77681_BUFp_DISABLED = 1,
+ AD77681_BUFp_FULL_BUFFER_ON = 2
+};
+
+/* VCM output voltage */
+enum ad77681_VCM_out {
+ AD77681_VCM_HALF_VCC = 0,
+ AD77681_VCM_2_5V = 1,
+ AD77681_VCM_2_05V = 2,
+ AD77681_VCM_1_9V = 3,
+ AD77681_VCM_1_65V = 4,
+ AD77681_VCM_1_1V = 5,
+ AD77681_VCM_0_9V = 6,
+ AD77681_VCM_OFF = 7
+};
+
+/* Global GPIO enable/disable */
+enum ad77681_gobal_gpio_enable {
+ AD77681_GLOBAL_GPIO_ENABLE = 1,
+ AD77681_GLOBAL_GPIO_DISABLE = 0
+};
+
+/* ADCs GPIO numbering */
+enum ad77681_gpios {
+ AD77681_GPIO0 = 0,
+ AD77681_GPIO1 = 1,
+ AD77681_GPIO2 = 2,
+ AD77681_GPIO3 = 3,
+ AD77681_ALL_GPIOS = 4
+};
+
+enum ad77681_gpio_output_type {
+ AD77681_GPIO_STRONG_DRIVER = 0,
+ AD77681_GPIO_OPEN_DRAIN = 1
+};
+
+/* Continuous ADC read */
+enum ad77681_continuous_read {
+ AD77681_CONTINUOUS_READ_ENABLE = 1,
+ AD77681_CONTINUOUS_READ_DISABLE = 0,
+};
+
+/* ADC data read mode */
+enum ad77681_data_read_mode {
+ AD77681_REGISTER_DATA_READ = 0,
+ AD77681_CONTINUOUS_DATA_READ = 1,
+};
+
+/* ADC data structure */
+struct adc_data {
+ bool finish;
+ uint16_t count;
+ uint16_t samples;
+ uint32_t raw_data[4096];
+};
+/* ADC status registers structure */
+struct ad77681_status_registers {
+ bool master_error;
+ bool adc_error;
+ bool dig_error;
+ bool adc_err_ext_clk_qual;
+ bool adc_filt_saturated;
+ bool adc_filt_not_settled;
+ bool spi_error;
+ bool por_flag;
+ bool spi_ignore;
+ bool spi_clock_count;
+ bool spi_read_error;
+ bool spi_write_error;
+ bool spi_crc_error;
+ bool dldo_psm_error;
+ bool aldo_psm_error;
+ bool ref_det_error;
+ bool filt_sat_error;
+ bool filt_not_set_error;
+ bool ext_clk_qual_error;
+ bool memoy_map_crc_error;
+ bool ram_crc_error;
+ bool fuse_crc_error;
+};
+
+struct ad77681_dev {
+ /* SPI */
+ spi_desc *spi_desc;
+ /* Configuration */
+ enum ad77681_power_mode power_mode;
+ enum ad77681_mclk_div mclk_div;
+ enum ad77681_conv_mode conv_mode;
+ enum ad77681_conv_diag_mux diag_mux_sel;
+ bool conv_diag_sel;
+ enum ad77681_conv_len conv_len;
+ enum ad77681_crc_sel crc_sel;
+ uint8_t status_bit;
+ enum ad77681_VCM_out VCM_out;
+ enum ad77681_AINn_precharge AINn;
+ enum ad77681_AINp_precharge AINp;
+ enum ad77681_REFn_buffer REFn;
+ enum ad77681_REFp_buffer REFp;
+ enum ad77681_filter_type filter;
+ enum ad77681_sinc5_fir_decimate decimate;
+ uint16_t sinc3_osr;
+ uint16_t vref; /* Reference voltage*/
+ uint16_t mclk; /* Mater clock*/
+ uint32_t sample_rate; /* Sample rate*/
+ uint8_t data_frame_byte; /* SPI 8bit frames*/
+};
+
+struct ad77681_init_param {
+ /* SPI */
+ spi_init_param spi_eng_dev_init;
+ /* Configuration */
+ enum ad77681_power_mode power_mode;
+ enum ad77681_mclk_div mclk_div;
+ enum ad77681_conv_mode conv_mode;
+ enum ad77681_conv_diag_mux diag_mux_sel;
+ bool conv_diag_sel;
+ enum ad77681_conv_len conv_len;
+ enum ad77681_crc_sel crc_sel;
+ uint8_t status_bit;
+ enum ad77681_VCM_out VCM_out;
+ enum ad77681_AINn_precharge AINn;
+ enum ad77681_AINp_precharge AINp;
+ enum ad77681_REFn_buffer REFn;
+ enum ad77681_REFp_buffer REFp;
+ enum ad77681_filter_type filter;
+ enum ad77681_sinc5_fir_decimate decimate;
+ uint16_t sinc3_osr;
+ uint16_t vref;
+ uint16_t mclk;
+ uint32_t sample_rate;
+ uint8_t data_frame_byte;
+};
+
+/******************************************************************************/
+/************************ Functions Declarations ******************************/
+/******************************************************************************/
+uint8_t ad77681_compute_crc8(uint8_t *data,
+ uint8_t data_size,
+ uint8_t init_val);
+uint8_t ad77681_compute_xor(uint8_t *data,
+ uint8_t data_size,
+ uint8_t init_val);
+int32_t ad77681_setup(struct ad77681_dev **device,
+ struct ad77681_init_param init_param,
+ struct ad77681_status_registers **status);
+int32_t ad77681_spi_reg_read(struct ad77681_dev *dev,
+ uint8_t reg_addr,
+ uint8_t *reg_data);
+int32_t ad77681_spi_read_mask(struct ad77681_dev *dev,
+ uint8_t reg_addr,
+ uint8_t mask,
+ uint8_t *data);
+int32_t ad77681_spi_reg_write(struct ad77681_dev *dev,
+ uint8_t reg_addr,
+ uint8_t reg_data);
+int32_t ad77681_spi_write_mask(struct ad77681_dev *dev,
+ uint8_t reg_addr,
+ uint8_t mask,
+ uint8_t data);
+int32_t ad77681_set_power_mode(struct ad77681_dev *dev,
+ enum ad77681_power_mode mode);
+int32_t ad77681_set_mclk_div(struct ad77681_dev *dev,
+ enum ad77681_mclk_div clk_div);
+int32_t ad77681_spi_read_adc_data(struct ad77681_dev *dev,
+ uint8_t *adc_data,
+ enum ad77681_data_read_mode mode);
+int32_t ad77681_set_conv_mode(struct ad77681_dev *dev,
+ enum ad77681_conv_mode conv_mode,
+ enum ad77681_conv_diag_mux diag_mux_sel,
+ bool conv_diag_sel);
+int32_t ad77681_set_convlen(struct ad77681_dev *dev,
+ enum ad77681_conv_len conv_len);
+int32_t ad77681_soft_reset(struct ad77681_dev *dev);
+int32_t ad77681_initiate_sync(struct ad77681_dev *dev);
+int32_t ad77681_programmable_filter(struct ad77681_dev *dev,
+ const float *coeffs,
+ uint8_t num_coeffs);
+int32_t ad77681_gpio_read(struct ad77681_dev *dev,
+ uint8_t *value,
+ enum ad77681_gpios gpio_number);
+int32_t ad77681_apply_offset(struct ad77681_dev *dev,
+ uint32_t value);
+int32_t ad77681_apply_gain(struct ad77681_dev *dev,
+ uint32_t value);
+int32_t ad77681_set_crc_sel(struct ad77681_dev *dev,
+ enum ad77681_crc_sel crc_sel);
+int32_t ad77681_gpio_open_drain(struct ad77681_dev *dev,
+ enum ad77681_gpios gpio_number,
+ enum ad77681_gpio_output_type output_type);
+int32_t ad77681_set_continuos_read(struct ad77681_dev *dev,
+ enum ad77681_continuous_read continuous_enable);
+int32_t ad77681_clear_error_flags(struct ad77681_dev *dev);
+int32_t ad77681_data_to_voltage(struct ad77681_dev *dev,
+ uint32_t *raw_code,
+ double *voltage);
+int32_t ad77681_CRC_status_handling(struct ad77681_dev *dev,
+ uint16_t *data_buffer);
+int32_t ad77681_set_AINn_buffer(struct ad77681_dev *dev,
+ enum ad77681_AINn_precharge AINn);
+int32_t ad77681_set_AINp_buffer(struct ad77681_dev *dev,
+ enum ad77681_AINp_precharge AINp);
+int32_t ad77681_set_REFn_buffer(struct ad77681_dev *dev,
+ enum ad77681_REFn_buffer REFn);
+int32_t ad77681_set_REFp_buffer(struct ad77681_dev *dev,
+ enum ad77681_REFp_buffer REFp);
+int32_t ad77681_set_filter_type(struct ad77681_dev *dev,
+ enum ad77681_sinc5_fir_decimate decimate,
+ enum ad77681_filter_type filter,
+ uint16_t sinc3_osr);
+int32_t ad77681_set_50HZ_rejection(struct ad77681_dev *dev,
+ uint8_t enable);
+int32_t ad77681_power_down(struct ad77681_dev *dev,
+ enum ad77681_sleep_wake sleep_wake);
+int32_t ad77681_set_status_bit(struct ad77681_dev *dev,
+ bool status_bit);
+int32_t ad77681_set_VCM_output(struct ad77681_dev *dev,
+ enum ad77681_VCM_out VCM_out);
+int32_t ad77681_gpio_write(struct ad77681_dev *dev,
+ uint8_t value,
+ enum ad77681_gpios gpio_number);
+int32_t ad77681_gpio_inout(struct ad77681_dev *dev,
+ uint8_t direction,
+ enum ad77681_gpios gpio_number);
+int32_t ad77681_global_gpio(struct ad77681_dev *devices,
+ enum ad77681_gobal_gpio_enable gpio_enable);
+int32_t ad77681_scratchpad(struct ad77681_dev *dev,
+ uint8_t *sequence);
+int32_t ad77681_error_flags_enabe(struct ad77681_dev *dev);
+int32_t ad77681_update_sample_rate(struct ad77681_dev *dev);
+int32_t ad77681_SINC3_ODR(struct ad77681_dev *dev,
+ uint16_t *sinc3_dec_reg,
+ float sinc3_odr);
+int32_t ad77681_status(struct ad77681_dev *dev,
+ struct ad77681_status_registers *status);
+#endif /* SRC_AD77681_H_ */
+