AD7124 no-OS library files

Files at this revision

API Documentation at this revision

Comitter:
MitchAD
Date:
Thu Sep 05 20:45:41 2019 +0000
Parent:
0:d18c9afa4bcb
Commit message:
Initial Commit for the AD7124 no-OS drivers

Changed in this revision

AD7124_no_OS.cpp Show diff for this revision Revisions of this file
AD7124_no_OS.h Show diff for this revision Revisions of this file
ad7124.cpp Show annotated file Show diff for this revision Revisions of this file
ad7124.h Show annotated file Show diff for this revision Revisions of this file
ad7124_regs.cpp Show annotated file Show diff for this revision Revisions of this file
ad7124_regs.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ad7124.cpp	Thu Sep 05 20:45:41 2019 +0000
@@ -0,0 +1,524 @@
+/***************************************************************************//**
+*   @file    AD7124.c
+*   @brief   AD7124 implementation file.
+*   @devices AD7124-4, AD7124-8
+*
+********************************************************************************
+* Copyright 2015(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 <stdlib.h>
+#include "ad7124.h"
+
+/* Error codes */
+#define INVALID_VAL -1 /* Invalid argument */
+#define COMM_ERR    -2 /* Communication error on receive */
+#define TIMEOUT     -3 /* A timeout has occured */
+
+/***************************************************************************//**
+ * @brief Reads the value of the specified register without checking if the
+ *        device is ready to accept user requests.
+ *
+ * @param dev   - The handler of the instance of the driver.
+ * @param p_reg - Pointer to the register structure holding info about the
+ *               register to be read. The read value is stored inside the
+ *               register structure.
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_no_check_read_register(struct ad7124_dev *dev,
+                      struct ad7124_st_reg* p_reg)
+{
+    int32_t ret = 0;
+    uint8_t buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    uint8_t i = 0;
+    uint8_t check8 = 0;
+    uint8_t msg_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+
+    if(!dev || !p_reg)
+        return INVALID_VAL;
+
+    /* Build the Command word */
+    buffer[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
+            AD7124_COMM_REG_RA(p_reg->addr);
+
+    /* Read data from the device */
+    ret = spi_write_and_read(dev->spi_desc,
+                 buffer,
+                 ((dev->use_crc != AD7124_DISABLE_CRC) ? p_reg->size + 1
+                  : p_reg->size) + 1);
+    if(ret < 0)
+        return ret;
+
+    /* Check the CRC */
+    if(dev->use_crc == AD7124_USE_CRC) {
+        msg_buf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_RD |
+                 AD7124_COMM_REG_RA(p_reg->addr);
+        for(i = 1; i < p_reg->size + 2; ++i) {
+            msg_buf[i] = buffer[i];
+        }
+        check8 = ad7124_compute_crc8(msg_buf, p_reg->size + 2);
+    }
+
+    if(check8 != 0) {
+        /* ReadRegister checksum failed. */
+        return COMM_ERR;
+    }
+
+    /* Build the result */
+    p_reg->value = 0;
+    for(i = 1; i < p_reg->size + 1; i++) {
+        p_reg->value <<= 8;
+        p_reg->value += buffer[i];
+    }
+
+    return ret;
+}
+
+/***************************************************************************//**
+ * @brief Writes the value of the specified register without checking if the
+ *        device is ready to accept user requests.
+ *
+ * @param dev - The handler of the instance of the driver.
+ * @param reg - Register structure holding info about the register to be written
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_no_check_write_register(struct ad7124_dev *dev,
+                       struct ad7124_st_reg reg)
+{
+    int32_t ret = 0;
+    int32_t reg_value = 0;
+    uint8_t wr_buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    uint8_t i = 0;
+    uint8_t crc8 = 0;
+
+    if(!dev)
+        return INVALID_VAL;
+
+    /* Build the Command word */
+    wr_buf[0] = AD7124_COMM_REG_WEN | AD7124_COMM_REG_WR |
+            AD7124_COMM_REG_RA(reg.addr);
+
+    /* Fill the write buffer */
+    reg_value = reg.value;
+    for(i = 0; i < reg.size; i++) {
+        wr_buf[reg.size - i] = reg_value & 0xFF;
+        reg_value >>= 8;
+    }
+
+    /* Compute the CRC */
+    if(dev->use_crc != AD7124_DISABLE_CRC) {
+        crc8 = ad7124_compute_crc8(wr_buf, reg.size + 1);
+        wr_buf[reg.size + 1] = crc8;
+    }
+
+    /* Write data to the device */
+    ret = spi_write_and_read(dev->spi_desc,
+                 wr_buf,
+                 (dev->use_crc != AD7124_DISABLE_CRC) ? reg.size + 2
+                 : reg.size + 1);
+
+    return ret;
+}
+
+/***************************************************************************//**
+ * @brief Reads the value of the specified register only when the device is ready
+ *        to accept user requests. If the device ready flag is deactivated the
+ *        read operation will be executed without checking the device state.
+ *
+ * @param dev   - The handler of the instance of the driver.
+ * @param p_reg - Pointer to the register structure holding info about the
+ *               register to be read. The read value is stored inside the
+ *               register structure.
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_read_register(struct ad7124_dev *dev,
+                 struct ad7124_st_reg* p_reg)
+{
+    int32_t ret;
+
+    if (p_reg->addr != AD7124_ERR_REG && dev->check_ready) {
+        ret = ad7124_wait_for_spi_ready(dev,
+                        dev->spi_rdy_poll_cnt);
+        if (ret < 0)
+            return ret;
+    }
+    ret = ad7124_no_check_read_register(dev,
+                        p_reg);
+
+    return ret;
+}
+
+/***************************************************************************//**
+ * @brief Writes the value of the specified register only when the device is
+ *        ready to accept user requests. If the device ready flag is deactivated
+ *        the write operation will be executed without checking the device state.
+ *
+ * @param dev - The handler of the instance of the driver.
+ * @param reg - Register structure holding info about the register to be written
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_write_register(struct ad7124_dev *dev,
+                  struct ad7124_st_reg p_reg)
+{
+    int32_t ret;
+
+    if (dev->check_ready) {
+        ret = ad7124_wait_for_spi_ready(dev,
+                        dev->spi_rdy_poll_cnt);
+        if (ret < 0)
+            return ret;
+    }
+    ret = ad7124_no_check_write_register(dev,
+                         p_reg);
+
+    return ret;
+}
+
+/***************************************************************************//**
+ * @brief Resets the device.
+ *
+ * @param dev - The handler of the instance of the driver.
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_reset(struct ad7124_dev *dev)
+{
+    int32_t ret = 0;
+    uint8_t wr_buf[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+
+    if(!dev)
+        return INVALID_VAL;
+
+    ret = spi_write_and_read(dev->spi_desc,
+                 wr_buf,
+                 8);
+
+    /* Wait for the reset to complete */
+    ret = ad7124_wait_to_power_on(dev,
+                      dev->spi_rdy_poll_cnt);
+
+    return ret;
+}
+
+/***************************************************************************//**
+ * @brief Waits until the device can accept read and write user actions.
+ *
+ * @param dev     - The handler of the instance of the driver.
+ * @param timeout - Count representing the number of polls to be done until the
+ *                  function returns.
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_wait_for_spi_ready(struct ad7124_dev *dev,
+                  uint32_t timeout)
+{
+    struct ad7124_st_reg *regs;
+    int32_t ret;
+    int8_t ready = 0;
+
+    if(!dev)
+        return INVALID_VAL;
+
+    regs = dev->regs;
+
+    while(!ready && --timeout) {
+        /* Read the value of the Error Register */
+        ret = ad7124_read_register(dev, &regs[AD7124_Error]);
+        if(ret < 0)
+            return ret;
+
+        /* Check the SPI IGNORE Error bit in the Error Register */
+        ready = (regs[AD7124_Error].value &
+             AD7124_ERR_REG_SPI_IGNORE_ERR) == 0;
+    }
+
+    return timeout ? 0 : TIMEOUT;
+}
+
+/***************************************************************************//**
+ * @brief Waits until the device finishes the power-on reset operation.
+ *
+ * @param dev     - The handler of the instance of the driver.
+ * @param timeout - Count representing the number of polls to be done until the
+ *                  function returns.
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_wait_to_power_on(struct ad7124_dev *dev,
+                uint32_t timeout)
+{
+    struct ad7124_st_reg *regs;
+    int32_t ret;
+    int8_t powered_on = 0;
+
+    if(!dev)
+        return INVALID_VAL;
+
+    regs = dev->regs;
+
+    while(!powered_on && timeout--) {
+        ret = ad7124_read_register(dev,
+                       &regs[AD7124_Status]);
+        if(ret < 0)
+            return ret;
+
+        /* Check the POR_FLAG bit in the Status Register */
+        powered_on = (regs[AD7124_Status].value &
+                  AD7124_STATUS_REG_POR_FLAG) == 0;
+    }
+
+    return (timeout || powered_on) ? 0 : TIMEOUT;
+}
+
+/***************************************************************************//**
+ * @brief Waits until a new conversion result is available.
+ *
+ * @param dev     - The handler of the instance of the driver.
+ * @param timeout - Count representing the number of polls to be done until the
+ *                  function returns if no new data is available.
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_wait_for_conv_ready(struct ad7124_dev *dev,
+                   uint32_t timeout)
+{
+    struct ad7124_st_reg *regs;
+    int32_t ret;
+    int8_t ready = 0;
+
+    if(!dev)
+        return INVALID_VAL;
+
+    regs = dev->regs;
+
+    while(!ready && --timeout) {
+        /* Read the value of the Status Register */
+        ret = ad7124_read_register(dev, &regs[AD7124_Status]);
+        if(ret < 0)
+            return ret;
+
+        /* Check the RDY bit in the Status Register */
+        ready = (regs[AD7124_Status].value &
+             AD7124_STATUS_REG_RDY) == 0;
+    }
+
+    return timeout ? 0 : TIMEOUT;
+}
+
+/***************************************************************************//**
+ * @brief Reads the conversion result from the device.
+ *
+ * @param dev     - The handler of the instance of the driver.
+ * @param p_data  - Pointer to store the read data.
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_read_data(struct ad7124_dev *dev,
+             int32_t* p_data)
+{
+    struct ad7124_st_reg *regs;
+    int32_t ret;
+
+    if(!dev)
+        return INVALID_VAL;
+
+    regs = dev->regs;
+
+    /* Read the value of the Status Register */
+    ret = ad7124_read_register(dev, &regs[AD7124_Data]);
+
+    /* Get the read result */
+    *p_data = regs[AD7124_Data].value;
+
+    return ret;
+}
+
+/***************************************************************************//**
+ * @brief Computes the CRC checksum for a data buffer.
+ *
+ * @param p_buf    - Data buffer
+ * @param buf_size - Data buffer size in bytes
+ *
+ * @return Returns the computed CRC checksum.
+*******************************************************************************/
+uint8_t ad7124_compute_crc8(uint8_t * p_buf, uint8_t buf_size)
+{
+    uint8_t i = 0;
+    uint8_t crc = 0;
+
+    while(buf_size) {
+        for(i = 0x80; i != 0; i >>= 1) {
+            bool cmp1 = (crc & 0x80) != 0;
+            bool cmp2 = (*p_buf & i) != 0;
+            if(cmp1 != cmp2) { /* MSB of CRC register XOR input Bit from Data */
+                crc <<= 1;
+                crc ^= AD7124_CRC8_POLYNOMIAL_REPRESENTATION;
+            } else {
+                crc <<= 1;
+            }
+        }
+        p_buf++;
+        buf_size--;
+    }
+    return crc;
+}
+
+/***************************************************************************//**
+ * @brief Updates the CRC settings.
+ *
+ * @param dev - The handler of the instance of the driver.
+ *
+ * @return None.
+*******************************************************************************/
+void ad7124_update_crcsetting(struct ad7124_dev *dev)
+{
+    struct ad7124_st_reg *regs;
+
+    if(!dev)
+        return;
+
+    regs = dev->regs;
+
+    /* Get CRC State. */
+    if (regs[AD7124_Error_En].value & AD7124_ERREN_REG_SPI_CRC_ERR_EN) {
+        dev->use_crc = AD7124_USE_CRC;
+    } else {
+        dev->use_crc = AD7124_DISABLE_CRC;
+    }
+}
+
+/***************************************************************************//**
+ * @brief Updates the device SPI interface settings.
+ *
+ * @param dev - The handler of the instance of the driver.
+ *
+ * @return None.
+*******************************************************************************/
+void ad7124_update_dev_spi_settings(struct ad7124_dev *dev)
+{
+    struct ad7124_st_reg *regs;
+
+    if(!dev)
+        return;
+
+    regs = dev->regs;
+
+    if (regs[AD7124_Error_En].value & AD7124_ERREN_REG_SPI_IGNORE_ERR_EN) {
+        dev->check_ready = 1;
+    } else {
+        dev->check_ready = 0;
+    }
+}
+
+/***************************************************************************//**
+ * @brief Initializes the AD7124.
+ *
+ * @param device     - The device structure.
+ * @param init_param - The structure that contains the device initial
+ *             parameters.
+ *
+ * @return Returns 0 for success or negative error code.
+*******************************************************************************/
+int32_t ad7124_setup(struct ad7124_dev **device,
+             struct ad7124_init_param init_param)
+{
+    int32_t ret;
+    int reg_nr;
+    struct ad7124_dev *dev;
+
+    dev = (struct ad7124_dev *)malloc(sizeof(*dev));
+    if (!dev)
+        return INVALID_VAL;
+
+    dev->regs = init_param.regs;
+    dev->spi_rdy_poll_cnt = init_param.spi_rdy_poll_cnt;
+
+    /* Initialize the SPI communication. */
+    ret = spi_init(&dev->spi_desc, &init_param.spi_init);
+    if (ret < 0)
+        return ret;
+
+    /*  Reset the device interface.*/
+    ret = ad7124_reset(dev);
+    if (ret < 0)
+        return ret;
+
+    /* Update the device structure with power-on/reset settings */
+    dev->check_ready = 1;
+
+    /* Initialize registers AD7124_ADC_Control through AD7124_Filter_7. */
+    for(reg_nr = AD7124_Status; (reg_nr < AD7124_Offset_0) && !(ret < 0);
+        reg_nr++) {
+        if (dev->regs[reg_nr].rw == AD7124_RW) {
+            ret = ad7124_write_register(dev, dev->regs[reg_nr]);
+            if (ret < 0)
+                break;
+        }
+
+        /* Get CRC State and device SPI interface settings */
+        if (reg_nr == AD7124_Error_En) {
+            ad7124_update_crcsetting(dev);
+            ad7124_update_dev_spi_settings(dev);
+        }
+    }
+
+    *device = dev;
+
+    return ret;
+}
+
+/***************************************************************************//**
+ * @brief Free the resources allocated by AD7124_Setup().
+ *
+ * @param dev - The device structure.
+ *
+ * @return SUCCESS in case of success, negative error code otherwise.
+*******************************************************************************/
+int32_t ad7124_remove(struct ad7124_dev *dev)
+{
+    int32_t ret;
+
+    ret = spi_remove(dev->spi_desc);
+
+    free(dev);
+
+    return ret;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ad7124.h	Thu Sep 05 20:45:41 2019 +0000
@@ -0,0 +1,423 @@
+/***************************************************************************//**
+*   @file    AD7124.h
+*   @brief   AD7124 header file.
+*   @devices AD7124-4, AD7124-8
+*
+********************************************************************************
+* Copyright 2015(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 __AD7124_H__
+#define __AD7124_H__
+
+/******************************************************************************/
+/***************************** Include Files **********************************/
+/******************************************************************************/
+#include <stdint.h>
+#include "platform_drivers.h"
+
+/******************************************************************************/
+/******************* Register map and register definitions ********************/
+/******************************************************************************/
+
+#define AD7124_RW 1   /* Read and Write */
+#define AD7124_R  2   /* Read only */
+#define AD7124_W  3   /* Write only */
+
+/* AD7124 Register Map */
+#define AD7124_COMM_REG      0x00
+#define AD7124_STATUS_REG    0x00
+#define AD7124_ADC_CTRL_REG  0x01
+#define AD7124_DATA_REG      0x02
+#define AD7124_IO_CTRL1_REG  0x03
+#define AD7124_IO_CTRL2_REG  0x04
+#define AD7124_ID_REG        0x05
+#define AD7124_ERR_REG       0x06
+#define AD7124_ERREN_REG     0x07
+#define AD7124_CH0_MAP_REG   0x09
+#define AD7124_CH1_MAP_REG   0x0A
+#define AD7124_CH2_MAP_REG   0x0B
+#define AD7124_CH3_MAP_REG   0x0C
+#define AD7124_CH4_MAP_REG   0x0D
+#define AD7124_CH5_MAP_REG   0x0E
+#define AD7124_CH6_MAP_REG   0x0F
+#define AD7124_CH7_MAP_REG   0x10
+#define AD7124_CH8_MAP_REG   0x11
+#define AD7124_CH9_MAP_REG   0x12
+#define AD7124_CH10_MAP_REG  0x13
+#define AD7124_CH11_MAP_REG  0x14
+#define AD7124_CH12_MAP_REG  0x15
+#define AD7124_CH13_MAP_REG  0x16
+#define AD7124_CH14_MAP_REG  0x17
+#define AD7124_CH15_MAP_REG  0x18
+#define AD7124_CFG0_REG      0x19
+#define AD7124_CFG1_REG      0x1A
+#define AD7124_CFG2_REG      0x1B
+#define AD7124_CFG3_REG      0x1C
+#define AD7124_CFG4_REG      0x1D
+#define AD7124_CFG5_REG      0x1E
+#define AD7124_CFG6_REG      0x1F
+#define AD7124_CFG7_REG      0x20
+#define AD7124_FILT0_REG     0x21
+#define AD7124_FILT1_REG     0x22
+#define AD7124_FILT2_REG     0x23
+#define AD7124_FILT3_REG     0x24
+#define AD7124_FILT4_REG     0x25
+#define AD7124_FILT5_REG     0x26
+#define AD7124_FILT6_REG     0x27
+#define AD7124_FILT7_REG     0x28
+#define AD7124_OFFS0_REG     0x29
+#define AD7124_OFFS1_REG     0x2A
+#define AD7124_OFFS2_REG     0x2B
+#define AD7124_OFFS3_REG     0x2C
+#define AD7124_OFFS4_REG     0x2D
+#define AD7124_OFFS5_REG     0x2E
+#define AD7124_OFFS6_REG     0x2F
+#define AD7124_OFFS7_REG     0x30
+#define AD7124_GAIN0_REG     0x31
+#define AD7124_GAIN1_REG     0x32
+#define AD7124_GAIN2_REG     0x33
+#define AD7124_GAIN3_REG     0x34
+#define AD7124_GAIN4_REG     0x35
+#define AD7124_GAIN5_REG     0x36
+#define AD7124_GAIN6_REG     0x37
+#define AD7124_GAIN7_REG     0x38
+
+/* Communication Register bits */
+#define AD7124_COMM_REG_WEN    (0 << 7)
+#define AD7124_COMM_REG_WR     (0 << 6)
+#define AD7124_COMM_REG_RD     (1 << 6)
+#define AD7124_COMM_REG_RA(x)  ((x) & 0x3F)
+
+/* Status Register bits */
+#define AD7124_STATUS_REG_RDY          (1 << 7)
+#define AD7124_STATUS_REG_ERROR_FLAG   (1 << 6)
+#define AD7124_STATUS_REG_POR_FLAG     (1 << 4)
+#define AD7124_STATUS_REG_CH_ACTIVE(x) ((x) & 0xF)
+
+/* ADC_Control Register bits */
+#define AD7124_ADC_CTRL_REG_DOUT_RDY_DEL   (1 << 12)
+#define AD7124_ADC_CTRL_REG_CONT_READ      (1 << 11)
+#define AD7124_ADC_CTRL_REG_DATA_STATUS    (1 << 10)
+#define AD7124_ADC_CTRL_REG_CS_EN          (1 << 9)
+#define AD7124_ADC_CTRL_REG_REF_EN         (1 << 8)
+#define AD7124_ADC_CTRL_REG_POWER_MODE(x)  (((x) & 0x3) << 6)
+#define AD7124_ADC_CTRL_REG_MODE(x)        (((x) & 0xF) << 2)
+#define AD7124_ADC_CTRL_REG_CLK_SEL(x)     (((x) & 0x3) << 0)
+
+/* IO_Control_1 Register bits */
+#define AD7124_IO_CTRL1_REG_GPIO_DAT2     (1 << 23)
+#define AD7124_IO_CTRL1_REG_GPIO_DAT1     (1 << 22)
+#define AD7124_IO_CTRL1_REG_GPIO_CTRL2    (1 << 19)
+#define AD7124_IO_CTRL1_REG_GPIO_CTRL1    (1 << 18)
+#define AD7124_IO_CTRL1_REG_PDSW          (1 << 15)
+#define AD7124_IO_CTRL1_REG_IOUT1(x)      (((x) & 0x7) << 11)
+#define AD7124_IO_CTRL1_REG_IOUT0(x)      (((x) & 0x7) << 8)
+#define AD7124_IO_CTRL1_REG_IOUT_CH1(x)   (((x) & 0xF) << 4)
+#define AD7124_IO_CTRL1_REG_IOUT_CH0(x)   (((x) & 0xF) << 0)
+
+/* IO_Control_1 AD7124-8 specific bits */
+#define AD7124_8_IO_CTRL1_REG_GPIO_DAT4     (1 << 23)
+#define AD7124_8_IO_CTRL1_REG_GPIO_DAT3     (1 << 22)
+#define AD7124_8_IO_CTRL1_REG_GPIO_DAT2     (1 << 21)
+#define AD7124_8_IO_CTRL1_REG_GPIO_DAT1     (1 << 20)
+#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL4    (1 << 19)
+#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL3    (1 << 18)
+#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL2    (1 << 17)
+#define AD7124_8_IO_CTRL1_REG_GPIO_CTRL1    (1 << 16)
+
+/* IO_Control_2 Register bits */
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS7   (1 << 15)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS6   (1 << 14)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS5   (1 << 11)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS4   (1 << 10)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS3   (1 << 5)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS2   (1 << 4)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS1   (1 << 1)
+#define AD7124_IO_CTRL2_REG_GPIO_VBIAS0   (1 << 0)
+
+/* IO_Control_2 AD7124-8 specific bits */
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS15  (1 << 15)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS14  (1 << 14)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS13  (1 << 13)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS12  (1 << 12)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS11  (1 << 11)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS10  (1 << 10)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS9   (1 << 9)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS8   (1 << 8)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS7   (1 << 7)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS6   (1 << 6)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS5   (1 << 5)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS4   (1 << 4)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS3   (1 << 3)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS2   (1 << 2)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS1   (1 << 1)
+#define AD7124_8_IO_CTRL2_REG_GPIO_VBIAS0   (1 << 0)
+
+/* ID Register bits */
+#define AD7124_ID_REG_DEVICE_ID(x)   (((x) & 0xF) << 4)
+#define AD7124_ID_REG_SILICON_REV(x) (((x) & 0xF) << 0)
+
+/* Error Register bits */
+#define AD7124_ERR_REG_LDO_CAP_ERR        (1 << 19)
+#define AD7124_ERR_REG_ADC_CAL_ERR        (1 << 18)
+#define AD7124_ERR_REG_ADC_CONV_ERR       (1 << 17)
+#define AD7124_ERR_REG_ADC_SAT_ERR        (1 << 16)
+#define AD7124_ERR_REG_AINP_OV_ERR        (1 << 15)
+#define AD7124_ERR_REG_AINP_UV_ERR        (1 << 14)
+#define AD7124_ERR_REG_AINM_OV_ERR        (1 << 13)
+#define AD7124_ERR_REG_AINM_UV_ERR        (1 << 12)
+#define AD7124_ERR_REG_REF_DET_ERR        (1 << 11)
+#define AD7124_ERR_REG_DLDO_PSM_ERR       (1 << 9)
+#define AD7124_ERR_REG_ALDO_PSM_ERR       (1 << 7)
+#define AD7124_ERR_REG_SPI_IGNORE_ERR     (1 << 6)
+#define AD7124_ERR_REG_SPI_SLCK_CNT_ERR   (1 << 5)
+#define AD7124_ERR_REG_SPI_READ_ERR       (1 << 4)
+#define AD7124_ERR_REG_SPI_WRITE_ERR      (1 << 3)
+#define AD7124_ERR_REG_SPI_CRC_ERR        (1 << 2)
+#define AD7124_ERR_REG_MM_CRC_ERR         (1 << 1)
+
+/* Error_En Register bits */
+#define AD7124_ERREN_REG_MCLK_CNT_EN           (1 << 22)
+#define AD7124_ERREN_REG_LDO_CAP_CHK_TEST_EN   (1 << 21)
+#define AD7124_ERREN_REG_LDO_CAP_CHK(x)        (((x) & 0x3) << 19)
+#define AD7124_ERREN_REG_ADC_CAL_ERR_EN        (1 << 18)
+#define AD7124_ERREN_REG_ADC_CONV_ERR_EN       (1 << 17)
+#define AD7124_ERREN_REG_ADC_SAT_ERR_EN        (1 << 16)
+#define AD7124_ERREN_REG_AINP_OV_ERR_EN        (1 << 15)
+#define AD7124_ERREN_REG_AINP_UV_ERR_EN        (1 << 14)
+#define AD7124_ERREN_REG_AINM_OV_ERR_EN        (1 << 13)
+#define AD7124_ERREN_REG_AINM_UV_ERR_EN        (1 << 12)
+#define AD7124_ERREN_REG_REF_DET_ERR_EN        (1 << 11)
+#define AD7124_ERREN_REG_DLDO_PSM_TRIP_TEST_EN (1 << 10)
+#define AD7124_ERREN_REG_DLDO_PSM_ERR_ERR      (1 << 9)
+#define AD7124_ERREN_REG_ALDO_PSM_TRIP_TEST_EN (1 << 8)
+#define AD7124_ERREN_REG_ALDO_PSM_ERR_EN       (1 << 7)
+#define AD7124_ERREN_REG_SPI_IGNORE_ERR_EN     (1 << 6)
+#define AD7124_ERREN_REG_SPI_SCLK_CNT_ERR_EN   (1 << 5)
+#define AD7124_ERREN_REG_SPI_READ_ERR_EN       (1 << 4)
+#define AD7124_ERREN_REG_SPI_WRITE_ERR_EN      (1 << 3)
+#define AD7124_ERREN_REG_SPI_CRC_ERR_EN        (1 << 2)
+#define AD7124_ERREN_REG_MM_CRC_ERR_EN         (1 << 1)
+
+/* Channel Registers 0-15 bits */
+#define AD7124_CH_MAP_REG_CH_ENABLE    (1 << 15)
+#define AD7124_CH_MAP_REG_SETUP(x)     (((x) & 0x7) << 12)
+#define AD7124_CH_MAP_REG_AINP(x)      (((x) & 0x1F) << 5)
+#define AD7124_CH_MAP_REG_AINM(x)      (((x) & 0x1F) << 0)
+
+/* Configuration Registers 0-7 bits */
+#define AD7124_CFG_REG_BIPOLAR     (1 << 11)
+#define AD7124_CFG_REG_BURNOUT(x)  (((x) & 0x3) << 9)
+#define AD7124_CFG_REG_REF_BUFP    (1 << 8)
+#define AD7124_CFG_REG_REF_BUFM    (1 << 7)
+#define AD7124_CFG_REG_AIN_BUFP    (1 << 6)
+#define AD7124_CFG_REG_AINN_BUFM   (1 << 5)
+#define AD7124_CFG_REG_REF_SEL(x)  ((x) & 0x3) << 3
+#define AD7124_CFG_REG_PGA(x)      (((x) & 0x7) << 0)
+
+/* Filter Register 0-7 bits */
+#define AD7124_FILT_REG_FILTER(x)         (((x) & 0x7) << 21)
+#define AD7124_FILT_REG_REJ60             (1 << 20)
+#define AD7124_FILT_REG_POST_FILTER(x)    (((x) & 0x7) << 17)
+#define AD7124_FILT_REG_SINGLE_CYCLE      (1 << 16)
+#define AD7124_FILT_REG_FS(x)             (((x) & 0x7FF) << 0)
+
+/******************************************************************************/
+/*************************** Types Declarations *******************************/
+/******************************************************************************/
+
+/*! Device register info */
+struct ad7124_st_reg {
+    int32_t addr;
+    int32_t value;
+    int32_t size;
+    int32_t rw;
+};
+
+/*! AD7124 registers list*/
+enum ad7124_registers {
+    AD7124_Status = 0x00,
+    AD7124_ADC_Control,
+    AD7124_Data,
+    AD7124_IOCon1,
+    AD7124_IOCon2,
+    AD7124_ID,
+    AD7124_Error,
+    AD7124_Error_En,
+    AD7124_Mclk_Count,
+    AD7124_Channel_0,
+    AD7124_Channel_1,
+    AD7124_Channel_2,
+    AD7124_Channel_3,
+    AD7124_Channel_4,
+    AD7124_Channel_5,
+    AD7124_Channel_6,
+    AD7124_Channel_7,
+    AD7124_Channel_8,
+    AD7124_Channel_9,
+    AD7124_Channel_10,
+    AD7124_Channel_11,
+    AD7124_Channel_12,
+    AD7124_Channel_13,
+    AD7124_Channel_14,
+    AD7124_Channel_15,
+    AD7124_Config_0,
+    AD7124_Config_1,
+    AD7124_Config_2,
+    AD7124_Config_3,
+    AD7124_Config_4,
+    AD7124_Config_5,
+    AD7124_Config_6,
+    AD7124_Config_7,
+    AD7124_Filter_0,
+    AD7124_Filter_1,
+    AD7124_Filter_2,
+    AD7124_Filter_3,
+    AD7124_Filter_4,
+    AD7124_Filter_5,
+    AD7124_Filter_6,
+    AD7124_Filter_7,
+    AD7124_Offset_0,
+    AD7124_Offset_1,
+    AD7124_Offset_2,
+    AD7124_Offset_3,
+    AD7124_Offset_4,
+    AD7124_Offset_5,
+    AD7124_Offset_6,
+    AD7124_Offset_7,
+    AD7124_Gain_0,
+    AD7124_Gain_1,
+    AD7124_Gain_2,
+    AD7124_Gain_3,
+    AD7124_Gain_4,
+    AD7124_Gain_5,
+    AD7124_Gain_6,
+    AD7124_Gain_7,
+    AD7124_REG_NO
+};
+
+/*
+ * The structure describes the device and is used with the ad7124 driver.
+ * @spi_desc: A reference to the SPI configuration of the device.
+ * @regs: A reference to the register list of the device that the user must
+ *       provide when calling the Setup() function.
+ * @userCRC: Whether to do or not a cyclic redundancy check on SPI transfers.
+ * @check_ready: When enabled all register read and write calls will first wait
+ *               until the device is ready to accept user requests.
+ * @spi_rdy_poll_cnt: Number of times the driver should read the Error register
+ *                    to check if the device is ready to accept user requests,
+ *                    before a timeout error will be issued.
+ */
+struct ad7124_dev {
+    /* SPI */
+    spi_desc        *spi_desc;
+    /* Device Settings */
+    struct ad7124_st_reg    *regs;
+    int16_t use_crc;
+    int16_t check_ready;
+    int16_t spi_rdy_poll_cnt;
+};
+
+struct ad7124_init_param {
+    /* SPI */
+    spi_init_param      spi_init;
+    /* Device Settings */
+    struct ad7124_st_reg    *regs;
+    int16_t spi_rdy_poll_cnt;
+};
+
+/******************************************************************************/
+/******************* AD7124 Constants *****************************************/
+/******************************************************************************/
+#define AD7124_CRC8_POLYNOMIAL_REPRESENTATION 0x07 /* x8 + x2 + x + 1 */
+#define AD7124_DISABLE_CRC 0
+#define AD7124_USE_CRC 1
+
+/******************************************************************************/
+/************************ Functions Declarations ******************************/
+/******************************************************************************/
+
+/*! Reads the value of the specified register. */
+int32_t ad7124_read_register(struct ad7124_dev *dev,
+                 struct ad7124_st_reg* p_reg);
+
+/*! Writes the value of the specified register. */
+int32_t ad7124_write_register(struct ad7124_dev *dev,
+                  struct ad7124_st_reg reg);
+
+/*! Reads the value of the specified register without a device state check. */
+int32_t ad7124_no_check_read_register(struct ad7124_dev *dev,
+                      struct ad7124_st_reg* p_reg);
+
+/*! Writes the value of the specified register without a device state check. */
+int32_t ad7124_no_check_write_register(struct ad7124_dev *dev,
+                       struct ad7124_st_reg reg);
+
+/*! Resets the device. */
+int32_t ad7124_reset(struct ad7124_dev *dev);
+
+/*! Waits until the device can accept read and write user actions. */
+int32_t ad7124_wait_for_spi_ready(struct ad7124_dev *dev,
+                  uint32_t timeout);
+
+/*! Waits until the device finishes the power-on reset operation. */
+int32_t ad7124_wait_to_power_on(struct ad7124_dev *dev,
+                uint32_t timeout);
+
+/*! Waits until a new conversion result is available. */
+int32_t ad7124_wait_for_conv_ready(struct ad7124_dev *dev,
+                   uint32_t timeout);
+
+/*! Reads the conversion result from the device. */
+int32_t ad7124_read_data(struct ad7124_dev *dev,
+             int32_t* p_data);
+
+/*! Computes the CRC checksum for a data buffer. */
+uint8_t ad7124_compute_crc8(uint8_t* p_buf,
+                uint8_t buf_size);
+
+/*! Updates the CRC settings. */
+void ad7124_update_crcsetting(struct ad7124_dev *dev);
+
+/*! Updates the device SPI interface settings. */
+void ad7124_update_dev_spi_settings(struct ad7124_dev *dev);
+
+/*! Initializes the AD7124. */
+int32_t ad7124_setup(struct ad7124_dev **device,
+             struct ad7124_init_param init_param);
+/*! Free the resources allocated by AD7124_Setup(). */
+int32_t ad7124_remove(struct ad7124_dev *dev);
+
+#endif /* __AD7124_H__ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ad7124_regs.cpp	Thu Sep 05 20:45:41 2019 +0000
@@ -0,0 +1,61 @@
+#include "ad7124_regs.h"
+
+struct ad7124_st_reg ad7124_regs[AD7124_REG_NO] = {
+    {0x00, 0x00,   1, 2}, /* AD7124_Status */
+    {0x01, 0x0000, 2, 1}, /* AD7124_ADC_Control */
+    {0x02, 0x0000, 3, 2}, /* AD7124_Data */
+    {0x03, 0x0000, 3, 1}, /* AD7124_IOCon1 */
+    {0x04, 0x0000, 2, 1}, /* AD7124_IOCon2 */
+    {0x05, 0x02,   1, 2}, /* AD7124_ID */
+    {0x06, 0x0000, 3, 2}, /* AD7124_Error */
+    {0x07, 0x0040, 3, 1}, /* AD7124_Error_En */
+    {0x08, 0x00,   1, 2}, /* AD7124_Mclk_Count */
+    {0x09, 0x8001, 2, 1}, /* AD7124_Channel_0 */
+    {0x0A, 0x0001, 2, 1}, /* AD7124_Channel_1 */
+    {0x0B, 0x0001, 2, 1}, /* AD7124_Channel_2 */
+    {0x0C, 0x0001, 2, 1}, /* AD7124_Channel_3 */
+    {0x0D, 0x0001, 2, 1}, /* AD7124_Channel_4 */
+    {0x0E, 0x0001, 2, 1}, /* AD7124_Channel_5 */
+    {0x0F, 0x0001, 2, 1}, /* AD7124_Channel_6 */
+    {0x10, 0x0001, 2, 1}, /* AD7124_Channel_7 */
+    {0x11, 0x0001, 2, 1}, /* AD7124_Channel_8 */
+    {0x12, 0x0001, 2, 1}, /* AD7124_Channel_9 */
+    {0x13, 0x0001, 2, 1}, /* AD7124_Channel_10 */
+    {0x14, 0x0001, 2, 1}, /* AD7124_Channel_11 */
+    {0x15, 0x0001, 2, 1}, /* AD7124_Channel_12 */
+    {0x16, 0x0001, 2, 1}, /* AD7124_Channel_13 */
+    {0x17, 0x0001, 2, 1}, /* AD7124_Channel_14 */
+    {0x18, 0x0001, 2, 1}, /* AD7124_Channel_15 */
+    {0x19, 0x0860, 2, 1}, /* AD7124_Config_0 */
+    {0x1A, 0x0860, 2, 1}, /* AD7124_Config_1 */
+    {0x1B, 0x0860, 2, 1}, /* AD7124_Config_2 */
+    {0x1C, 0x0860, 2, 1}, /* AD7124_Config_3 */
+    {0x1D, 0x0860, 2, 1}, /* AD7124_Config_4 */
+    {0x1E, 0x0860, 2, 1}, /* AD7124_Config_5 */
+    {0x1F, 0x0860, 2, 1}, /* AD7124_Config_6 */
+    {0x20, 0x0860, 2, 1}, /* AD7124_Config_7 */
+    {0x21, 0x060180, 3, 1}, /* AD7124_Filter_0 */
+    {0x22, 0x060180, 3, 1}, /* AD7124_Filter_1 */
+    {0x23, 0x060180, 3, 1}, /* AD7124_Filter_2 */
+    {0x24, 0x060180, 3, 1}, /* AD7124_Filter_3 */
+    {0x25, 0x060180, 3, 1}, /* AD7124_Filter_4 */
+    {0x26, 0x060180, 3, 1}, /* AD7124_Filter_5 */
+    {0x27, 0x060180, 3, 1}, /* AD7124_Filter_6 */
+    {0x28, 0x060180, 3, 1}, /* AD7124_Filter_7 */
+    {0x29, 0x800000, 3, 1}, /* AD7124_Offset_0 */
+    {0x2A, 0x800000, 3, 1}, /* AD7124_Offset_1 */
+    {0x2B, 0x800000, 3, 1}, /* AD7124_Offset_2 */
+    {0x2C, 0x800000, 3, 1}, /* AD7124_Offset_3 */
+    {0x2D, 0x800000, 3, 1}, /* AD7124_Offset_4 */
+    {0x2E, 0x800000, 3, 1}, /* AD7124_Offset_5 */
+    {0x2F, 0x800000, 3, 1}, /* AD7124_Offset_6 */
+    {0x30, 0x800000, 3, 1}, /* AD7124_Offset_7 */
+    {0x31, 0x500000, 3, 1}, /* AD7124_Gain_0 */
+    {0x32, 0x500000, 3, 1}, /* AD7124_Gain_1 */
+    {0x33, 0x500000, 3, 1}, /* AD7124_Gain_2 */
+    {0x34, 0x500000, 3, 1}, /* AD7124_Gain_3 */
+    {0x35, 0x500000, 3, 1}, /* AD7124_Gain_4 */
+    {0x36, 0x500000, 3, 1}, /* AD7124_Gain_5 */
+    {0x37, 0x500000, 3, 1}, /* AD7124_Gain_6 */
+    {0x38, 0x500000, 3, 1}, /* AD7124_Gain_7 */
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ad7124_regs.h	Thu Sep 05 20:45:41 2019 +0000
@@ -0,0 +1,10 @@
+#ifndef __AD7124_REGS_H__
+#define __AD7124_REGS_H__
+
+#include "ad7124.h"
+
+/*! Array holding the info for the ad7124 registers - address, initial value,
+    size and access type. */
+extern struct ad7124_st_reg ad7124_regs[AD7124_REG_NO];
+
+#endif /* __AD7124_REGS_H__ */
\ No newline at end of file