AD7798 ADC driver

Dependents:   CN0396 CN0397

Files at this revision

API Documentation at this revision

Comitter:
adisuciu
Date:
Mon Nov 07 15:45:27 2016 +0000
Commit message:
Initial revision

Changed in this revision

AD7798.cpp Show annotated file Show diff for this revision Revisions of this file
AD7798.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r fb6fe6fa2835 AD7798.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AD7798.cpp	Mon Nov 07 15:45:27 2016 +0000
@@ -0,0 +1,350 @@
+/***************************************************************************//**
+ *   @file   AD7798.c
+ *   @brief  Implementation of AD7798 Driver.
+ *   @author
+********************************************************************************
+ * Copyright 2012(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.
+ *
+********************************************************************************
+ *   SVN Revision: 577
+*******************************************************************************/
+
+/******************************************************************************/
+/* Include Files                                                              */
+/******************************************************************************/
+#include "AD7798.h"				// AD7798 definitions.
+#include <stdio.h>
+
+
+/***************************************************************************//**
+ * @brief Initializes the AD7798 and checks if the device is present.
+ *
+ * @param None.
+ *
+ * @return status - Result of the initialization procedure.
+ *                  Example: 1 - if initialization was successful (ID is 0x0B).
+ *                           0 - if initialization was unsuccessful.
+*******************************************************************************/
+AD7798::AD7798( PinName CS, PinName MOSI, PinName MISO, PinName SCK):
+    /*miso(MISO),*/ ad7798(MOSI, MISO, SCK), cs(CS)
+{
+    cs = true; // cs is active low
+    ad7798.format(8, _SPI_MODE);
+}
+uint8_t AD7798::init(void)
+{
+    unsigned char status = 0x1;
+
+    if ((get_register_value (AD7798_REG_ID, 1) & 0x0F) != AD7798_ID) {
+        status = 0x0;
+    }
+
+    return(status);
+}
+
+/***************************************************************************//**
+ * @brief Sends 32 consecutive 1's on SPI in order to reset the part.
+ *
+ * @param None.
+ *
+ * @return  None.
+*******************************************************************************/
+void AD7798::frequency(int hz)
+{
+    ad7798.frequency(hz);
+}
+void AD7798::reset(void)
+{
+    unsigned char dataToSend[4] = {0xFF, 0xFF, 0xFF, 0xFF};
+
+    spi_write(dataToSend, 4);
+
+    wait_ms(500);
+
+}
+/***************************************************************************//**
+ * @brief Reads the value of the selected register
+ *
+ * @param regAddress - The address of the register to read.
+ * @param size - The size of the register to read.
+ *
+ * @return data - The value of the selected register register.
+*******************************************************************************/
+uint16_t AD7798::get_register_value(uint8_t regAddress, uint8_t size, bool toggle_cs)
+{
+    unsigned char data[size];
+    uint16_t receivedData = 0x00;
+    unsigned char byte;
+
+    data[0] = AD7798_COMM_READ |  AD7798_COMM_ADDR(regAddress);
+
+    spi_read(data, size, toggle_cs);
+
+    receivedData = data[0];
+
+    if(size > 1) {
+
+        for(byte = 1; byte < size; byte++) {
+            receivedData = (receivedData << (byte * 8) | data[byte]);
+        }
+    }
+    return receivedData;
+}
+/***************************************************************************//**
+ * @brief Writes the value to the register
+ *
+ * @param -  regAddress - The address of the register to write to.
+ * @param -  regValue - The value to write to the register.
+ * @param -  size - The size of the register to write.
+ *
+ * @return  None.
+*******************************************************************************/
+void AD7798::set_register_value(uint8_t regAddress, uint16_t regValue,
+                                uint8_t size, bool toggle_cs)
+{
+    uint8_t data[size + 1];
+    uint8_t byte;
+    uint16_t mask;
+
+    data[0] = AD7798_COMM_WRITE |  AD7798_COMM_ADDR(regAddress);
+
+    if(size == 1) {
+
+        mask = 0x00FF;
+
+    } else {
+
+        mask = 0xFF00;
+    }
+
+    for(byte = 1; byte <= size; byte++) {
+        data[byte] = (uint8_t)((regValue & mask) >> ((size - byte) * 8));
+        mask = mask >> (byte * 8);
+    }
+
+    spi_write(data, (1 + size), toggle_cs);
+
+
+}
+/***************************************************************************//**
+ * @brief Reads /RDY bit of status reg.
+ *
+ * @param None.
+ *
+ * @return rdy	- 0 if RDY is 1.
+ *              - 1 if RDY is 0.
+*******************************************************************************/
+uint8_t AD7798::ready(void)
+{
+
+    while((get_register_value( AD7798_REG_STAT, 1) & 0x80) != 0x80);
+
+    return(1);
+}
+
+/***************************************************************************//**
+ * @brief Sets the operating mode of AD7798.
+ *
+ * @param mode - Mode of operation.
+ *
+ * @return  None.
+*******************************************************************************/
+void AD7798::set_mode(uint8_t mode)
+{
+    unsigned long command;
+    command = get_register_value(AD7798_REG_MODE, 2);
+    command &= ~AD7798_MODE_SEL(0xFF);
+    command |= AD7798_MODE_SEL(mode);
+    set_register_value(
+        AD7798_REG_MODE,
+        command,
+        2
+    );
+}
+/***************************************************************************//**
+ * @brief Selects the channel of AD7798.
+ *
+ * @param  channel - ADC channel selection.
+ *
+ * @return  None.
+*******************************************************************************/
+void AD7798::set_channel(uint8_t channel)
+{
+    unsigned long command;
+    command = get_register_value(AD7798_REG_CONF, 2);
+    command &= ~AD7798_CONF_CHAN(0xFF);
+    command |= AD7798_CONF_CHAN(channel);
+    set_register_value(
+        AD7798_REG_CONF,
+        command,
+        2
+    );
+}
+
+/***************************************************************************//**
+ * @brief  Sets the gain of the In-Amp.
+ *
+ * @param  gain - Gain.
+ *
+ * @return  None.
+*******************************************************************************/
+void AD7798::set_gain(uint16_t gain)
+{
+    uint16_t command;
+    command = get_register_value(AD7798_REG_CONF, 2);
+    command &= ~AD7798_CONF_GAIN(0xFF);
+    command |= AD7798_CONF_GAIN(gain);
+    set_register_value(
+        AD7798_REG_CONF,
+        command,
+        2
+    );
+}
+
+void AD7798::set_filter(uint8_t filter)
+{
+    unsigned long command;
+    command = get_register_value(AD7798_REG_MODE, 2);
+    command &= ~AD7798_MODE_RATE(0x0F);
+    command |= AD7798_MODE_RATE(filter);
+    set_register_value(
+        AD7798_REG_MODE,
+        command,
+        2
+    );
+}
+/***************************************************************************//**
+ * @brief Enables or disables the reference detect function.
+ *
+ * @param state - State of the reference detect function.
+ *               Example: 0	- Reference detect disabled.
+ *                        1	- Reference detect enabled.
+ *
+ * @return None.
+*******************************************************************************/
+void AD7798::set_reference(uint8_t state)
+{
+    unsigned long command = 0;
+    command = get_register_value(AD7798_REG_CONF, 2);
+    command &= ~AD7798_CONF_REFDET(1);
+    command |= AD7798_CONF_REFDET(state);
+    set_register_value(AD7798_REG_CONF,
+                       command,
+                       2);
+}
+
+void AD7798::set_coding_mode(uint8_t mode)
+{
+    uint16_t command;
+
+    command = get_register_value(AD7798_REG_CONF, 2);
+
+    if(mode == AD7798_BIPOLAR) {
+
+        command &= ~AD7798_CONF_UNIPOLAR;
+
+    } else if(mode == AD7798_UNIPOLAR) {
+
+        command |= AD7798_CONF_UNIPOLAR;
+    }
+    set_register_value(
+        AD7798_REG_CONF,
+        command,
+        2
+    );
+}
+
+void AD7798::set_burnout_current(uint8_t select)
+{
+    uint16_t command;
+
+    command = get_register_value(AD7798_REG_CONF, 2);
+
+    if(select == AD7798_DISABLE)
+        command &= ~AD7798_CONF_BO_EN;
+    else if(select == AD7798_ENABLE)
+        command |= AD7798_CONF_BO_EN;
+
+    set_register_value(
+        AD7798_REG_CONF,
+        command,
+        2
+    );
+}
+
+uint8_t AD7798::spi_read(uint8_t *data, uint8_t bytes_number, bool toggle_cs)
+{
+    cs = false & toggle_cs;
+    data[0] = ad7798.write(data[0]);
+    for(uint8_t byte = 1; byte <= bytes_number; byte++) {
+        data[byte - 1] = ad7798.write(data[byte]);
+    }
+    cs = true & toggle_cs;
+    return bytes_number;
+}
+uint8_t AD7798::spi_write(uint8_t *data, uint8_t bytes_number, bool toggle_cs)
+{
+    cs = false & toggle_cs;
+    for(uint8_t byte = 0; byte < bytes_number; byte++) {
+        ad7798.write(data[byte]);
+    }
+    cs = true & toggle_cs;
+    return bytes_number;
+}
+
+void AD7798::read_data(uint8_t adcChannel, uint16_t *adcData)
+{
+
+    uint8_t channel;
+
+    channel = 0x80 | adcChannel;
+
+    cs = 0;
+
+    set_register_value(AD7798_REG_MODE, 0x200A, 2);//, false);
+    uint16_t regVal = 0;
+    while( (regVal & channel) != channel) {
+        regVal = get_register_value( AD7798_REG_STAT, 1);//, false);
+    }
+
+    //timer_sleep(200);
+    wait_ms(200); // ???
+
+    *adcData = get_register_value(AD7798_REG_DATA, 2);//, false);
+
+    cs = 1;
+
+
+
+}
diff -r 000000000000 -r fb6fe6fa2835 AD7798.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AD7798.h	Mon Nov 07 15:45:27 2016 +0000
@@ -0,0 +1,148 @@
+#ifndef _AD7798_H_
+#define _AD7798_H_
+
+#include <mbed.h>
+
+/******************************************************************************/
+/* AD7798                                                                   */
+/******************************************************************************/
+
+/*AD7798 Registers*/
+#define AD7798_REG_COMM		0 /* Communications Register(WO, 8-bit) */
+#define AD7798_REG_STAT	    0 /* Status Register	    (RO, 8-bit) */
+#define AD7798_REG_MODE	    1 /* Mode Register	     	(RW, 16-bit */
+#define AD7798_REG_CONF	    2 /* Configuration Register (RW, 16-bit)*/
+#define AD7798_REG_DATA	    3 /* Data Register	     	(RO, 16-/24-bit) */
+#define AD7798_REG_ID	    4 /* ID Register	     	(RO, 8-bit) */
+#define AD7798_REG_IO	    5 /* IO Register	     	(RO, 8-bit) */
+#define AD7798_REG_OFFSET   6 /* Offset Register	    (RW, 24-bit */
+#define AD7798_REG_FULLSCALE	7 /* Full-Scale Register	(RW, 24-bit */
+
+/* Communications Register Bit Designations (AD7798_REG_COMM) */
+#define AD7798_COMM_WEN		(1 << 7) 			/* Write Enable */
+#define AD7798_COMM_WRITE	(0 << 6) 			/* Write Operation */
+#define AD7798_COMM_READ    (1 << 6) 			/* Read Operation */
+#define AD7798_COMM_ADDR(x)	(((x) & 0x7) << 3)	/* Register Address */
+#define AD7798_COMM_CREAD	(1 << 2) 			/* Continuous Read of Data Register */
+
+/* Status Register Bit Designations (AD7798_REG_STAT) */
+#define AD7798_STAT_RDY		(1 << 7) /* Ready */
+#define AD7798_STAT_ERR		(1 << 6) /* Error (Overrange, Underrange) */
+#define AD7798_STAT_CH3		(1 << 2) /* Channel 3 */
+#define AD7798_STAT_CH2		(1 << 1) /* Channel 2 */
+#define AD7798_STAT_CH1		(1 << 0) /* Channel 1 */
+
+
+#define AD7798_CH3		(1 << 2) /* Channel 3 */
+#define AD7798_CH2		(1 << 1) /* Channel 2 */
+#define AD7798_CH1		(1 << 0) /* Channel 1 */
+
+/* Mode Register Bit Designations (AD7798_REG_MODE) */
+#define AD7798_MODE_SEL(x)		(((x) & 0x7) << 13)	/* Operation Mode Select */
+#define AD7798_MODE_PSW(x)		(1 << 12)			/* Power Switch Control Bit */
+#define AD7798_MODE_RATE(x)		((x) & 0xF) 		/* Filter Update Rate Select */
+
+/* AD7798_MODE_SEL(x) options */
+#define AD7798_MODE_CONT		 0 /* Continuous Conversion Mode */
+#define AD7798_MODE_SINGLE		 1 /* Single Conversion Mode */
+#define AD7798_MODE_IDLE		 2 /* Idle Mode */
+#define AD7798_MODE_PWRDN		 3 /* Power-Down Mode */
+#define AD7798_MODE_CAL_INT_ZERO 4 /* Internal Zero-Scale Calibration */
+#define AD7798_MODE_CAL_INT_FULL 5 /* Internal Full-Scale Calibration */
+#define AD7798_MODE_CAL_SYS_ZERO 6 /* System Zero-Scale Calibration */
+#define AD7798_MODE_CAL_SYS_FULL 7 /* System Full-Scale Calibration */
+
+/* Configuration Register Bit Designations (AD7798_REG_CONF) */
+#define AD7798_CONF_BO_EN	  (1 << 13) 			/* Burnout Current Enable */
+#define AD7798_CONF_UNIPOLAR  (1 << 12) 			/* Unipolar/Bipolar Enable */
+#define AD7798_CONF_GAIN(x)	  (((x) & 0x7) << 8) 	/* Gain Select */
+#define AD7798_CONF_REFDET(x) (((x) & 0x1) << 5) 	/* Reference detect function */
+#define AD7798_CONF_BUF		  (1 << 4) 				/* Buffered Mode Enable */
+#define AD7798_CONF_CHAN(x)	  ((x) & 0x7) 			/* Channel select */
+
+/* AD7798_CONF_GAIN(x) options */
+#define AD7798_GAIN_1       0
+#define AD7798_GAIN_2       1
+#define AD7798_GAIN_4       2
+#define AD7798_GAIN_8       3
+#define AD7798_GAIN_16      4
+#define AD7798_GAIN_32      5
+#define AD7798_GAIN_64      6
+#define AD7798_GAIN_128     7
+
+/* AD7798_CONF_REFDET(x) options */
+#define AD7798_REFDET_ENA   1
+#define AD7798_REFDET_DIS   0
+
+/* AD7798_CONF_CHAN(x) options */
+#define AD7798_CH_AIN1P_AIN1M	0 /* AIN1(+) - AIN1(-) */
+#define AD7798_CH_AIN2P_AIN2M	1 /* AIN2(+) - AIN2(-) */
+#define AD7798_CH_AIN3P_AIN3M	2 /* AIN3(+) - AIN3(-) */
+#define AD7798_CH_AIN1M_AIN1M	3 /* AIN1(-) - AIN1(-) */
+#define AD7798_CH_AVDD_MONITOR	7 /* AVDD Monitor */
+
+/* ID Register Bit Designations (AD7798_REG_ID) */
+#define AD7798_ID			0x8
+#define AD7798_ID_MASK		0xF
+
+/* IO (Excitation Current Sources) Register Bit Designations (AD7798_REG_IO) */
+#define AD7798_IOEN			(1 << 6)
+#define AD7798_IO1(x)		(((x) & 0x1) << 4)
+#define AD7798_IO2(x)		(((x) & 0x1) << 5)
+
+#define TRUE              1
+#define FALSE             0
+
+#define AD7798_UNIPOLAR     TRUE
+#define AD7798_BIPOLAR      FALSE
+
+#define AD7798_ENABLE       TRUE
+#define AD7798_DISABLE      FALSE
+
+/******************************************************************************/
+/* Functions Prototypes                                                       */
+/*****************************************************************************/
+
+class AD7798
+{
+public:
+    AD7798( PinName CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
+    /* Initialize AD7798 and check if the device is present*/
+    uint8_t init(void);
+    void frequency(int hz);
+    /* Sends 32 consecutive 1's on SPI in order to reset the part. */
+    void reset(void);
+    /* Reads the value of the selected register. */
+    uint16_t get_register_value(uint8_t regAddress, uint8_t size, bool toggle_cs = true);
+    /* Writes a value to the register. */
+    void set_register_value(uint8_t regAddress, uint16_t regValue, uint8_t size, bool toggle_cs = true);
+    /* Sets the operating mode of AD7798. */
+    void set_mode(uint8_t mode);
+    /* Reads /RDY bit of Status register. */
+    uint8_t ready(void);
+    /* Selects the channel of AD7798. */
+    void set_channel(uint8_t channel);
+    /* Sets the gain of the In-Amp. */
+    void set_gain(uint16_t gain);
+    /* Enables or disables the reference detect function. */
+    void set_reference(uint8_t state);
+
+    void set_filter(uint8_t filter);
+    void set_coding_mode(uint8_t mode);
+    void set_burnout_current(uint8_t select);
+
+    void read_data(uint8_t adcChannel, uint16_t *adcData);
+
+    uint8_t spi_read(uint8_t *data, uint8_t bytes_number, bool toggle_cs = true);
+    uint8_t spi_write(uint8_t *data, uint8_t bytes_number, bool toggle_cs = true);
+
+
+
+    //DigitalIn miso;///< DigitalIn must be initialized before SPI to prevent pin MUX overwrite
+    SPI ad7798;
+    DigitalOut cs;
+
+private:
+    const uint8_t _SPI_MODE = 0x03;
+};
+#endif	// _AD7798_H_