AD7768-1 Library Files
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_ */ +