A collection of Analog Devices drivers for the mbed platform

For additional information check out the mbed page of the Analog Devices wiki: https://wiki.analog.com/resources/tools-software/mbed-drivers-all

Files at this revision

API Documentation at this revision

Comitter:
Adrian Suciu
Date:
Tue Apr 19 17:55:14 2016 +0300
Parent:
3:1a8c14043a4e
Child:
5:9221918730aa
Commit message:
Driver and application redesign

Changed in this revision

examples/cn0357_example/main.cpp Show annotated file Show diff for this revision Revisions of this file
libraries/ad5270/AD5270.cpp Show annotated file Show diff for this revision Revisions of this file
libraries/ad5270/AD5270.h Show annotated file Show diff for this revision Revisions of this file
libraries/ad7790/AD7790.cpp Show annotated file Show diff for this revision Revisions of this file
libraries/ad7790/AD7790.h Show annotated file Show diff for this revision Revisions of this file
libraries/cn0357/cn0357.cpp Show annotated file Show diff for this revision Revisions of this file
libraries/cn0357/cn0357.h Show annotated file Show diff for this revision Revisions of this file
--- a/examples/cn0357_example/main.cpp	Fri Apr 01 10:53:41 2016 +0300
+++ b/examples/cn0357_example/main.cpp	Tue Apr 19 17:55:14 2016 +0300
@@ -44,7 +44,6 @@
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ********************************************************************************/
-
 #include "mbed.h"
 #include "cn0357.h"
 
@@ -88,9 +87,9 @@
  @param fdata2   - Gas Concentration reading to be displayed
 
  **/
-void display_data(uint16_t ui16Data, float fData1, float fdata2)
+void display_data(uint8_t ui8Status_Reg, uint16_t ui16Data, float fData1, float fdata2)
 {
-
+    pc.printf("\r\nStatus Register value: 0x%x", ui8Status_Reg);
     pc.printf("\r\nADC Data Register Value = %#08x", ui16Data); /** Send valid ADC data register value*/
     pc.printf("\r\nADC Input Voltage input = %f V", fData1); /** Send valid voltage input value */
     pc.printf("\r\nGas Concentration = %f PPM", fdata2); /** Send valid gas concentration value */
@@ -98,35 +97,46 @@
     pc.printf("\r\n");
 }
 
-
 /**
  * Project entry-point - initializes the CN0357 shield, reads the data when the ADC is ready and outputs the sensor
  * value in PPM
  */
+
+#define SINGLE_CONVERSION
+//#define CONTINOUS_CONVERSION
+
 int main()
 {
     /* Main variables */
-
+    CN0357 cn0357;
+    uint8_t ui8Status_Reg = 0;
+#ifdef SINGLE_CONVERSION
+    cn0357.init(SENSOR_RANGE, SENSOR_SENSITIVITY);
+#elif defined CONTINOUS_CONVERSION
+    cn0357.init(SENSOR_RANGE, SENSOR_SENSITIVITY, CN0357::INTERNAL_AD7790, 0x00, 0x07);
+#else
+#error define SINGLE_CONVERSION or CONTINOUS_CONVERSION, but not both
+#endif
 
-    CN0357 cn0357;
-    cn0357.init(SENSOR_RANGE, SENSOR_SENSITIVITY);
 
     /* Infinite loop */
     while (1) {
+        wait_ms(1000);
+#ifdef CONTINOUS_CONVERSION
+        ui8Status_Reg = cn0357.read_adc_status(); //  Read ADC Status Register        //
 
-        uint8_t ui8Status_Reg = cn0357.read_adc_status(); //  Read ADC Status Register
-
-        if (ui8Status_Reg == 0x08) { //  Checks if ADC data is available
+        if (ui8Status_Reg != 0x08) { //  Checks if ADC data is available
+            pc.printf("\r\nStatus Register value: 0x%x", ui8Status_Reg);
+        } else
+#endif
+        {
             uint16_t ui16Adcdata = cn0357.read_sensor();
             float fAdcVoltage    = cn0357.data_to_voltage(ui16Adcdata); //  Convert ADC data to voltage
             float fConcentration = cn0357.calc_ppm(fAdcVoltage); //  Convert voltage to Gas concentration
-            display_data(ui16Adcdata, fAdcVoltage, fConcentration); //  Display data thru UART
-
-            // printf("OneshotRead: %f PPM \r\n", cn0357.readPPM());
+            display_data(ui8Status_Reg, ui16Adcdata, fAdcVoltage, fConcentration); //  Display data thru UART
         }
+    }
 
-        wait_ms(1000);
-    }
 
     /* Infinite loop, never returns. */
 }
--- a/libraries/ad5270/AD5270.cpp	Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/ad5270/AD5270.cpp	Tue Apr 19 17:55:14 2016 +0300
@@ -60,8 +60,8 @@
 AD5270::AD5270(PinName CS, float max_resistance, PinName MOSI, PinName MISO, PinName SCK):
     ad5270(MOSI, MISO, SCK), cs(CS), _max_resistance(max_resistance)
 {
-    ad5270.format(8, 3);
     cs = true;
+    ad5270.format(8, _SPI_MODE);
 }
 
 /**
@@ -75,12 +75,37 @@
 }
 
 /**
+ * @brief sets a new value for the RDAC
+ * @param resistance new value for the resistance
+ * @return actual value of the resistance in the RDAC
+ */
+float AD5270::write_RDAC(float resistance)
+{
+    // Compute for the RDAC code nearest to the required feedback resistance
+    uint16_t RDAC_val = calc_RDAC(resistance);
+    float RDAC_Value = ((static_cast<float> (RDAC_val) * _max_resistance) / 1024.0); // inverse operation to get actual resistance in the RDAC
+    write_wiper_reg(RDAC_val);
+    return RDAC_Value;
+}
+
+/**
+ * Reads the RDAC register
+ * @return RDAC resistor value
+ */
+float AD5270::read_RDAC()
+{
+    uint16_t RDAC_val = read_wiper_reg();
+    return ((static_cast<float> (RDAC_val) * _max_resistance) / 1024.0);
+}
+
+/**
  *	@brief Puts the AD5270 SDO line in to Hi-Z mode
  *	@return none
  */
 void AD5270::set_SDO_HiZ(void)
 {
     write_reg(HI_Z_Cmd);
+    wait_us(2);
     write_reg(NO_OP_cmd);
 }
 
@@ -108,6 +133,33 @@
 }
 
 /**
+ *  Enables the 50TP memory programming
+ */
+void AD5270::enable_50TP_programming()
+{
+    uint8_t regVal = read_ctrl_reg();
+    write_cmd(WRITE_CTRL_REG, regVal | PROGRAM_50TP_ENABLE); // RDAC register write protect -  allow update of wiper position through digital interface
+}
+
+/**
+ *  Stores current RDAC content to the 50TP memory
+ */
+void AD5270::store_50TP()
+{
+    write_cmd(STORE_50TP);
+    wait_ms(_WRITE_OPERATION_50TP_TIMEOUT);
+}
+
+/**
+ * Disables the 50TP memory programming
+ */
+void AD5270::disable_50TP_programming()
+{
+    uint8_t regVal = read_ctrl_reg();
+    write_cmd(WRITE_CTRL_REG, regVal & (~PROGRAM_50TP_ENABLE));
+}
+
+/**
  * @brief Writes 16bit data to the AD5270 SPI interface
  * @param data to be written
  * @return data returned by the AD5270
@@ -117,6 +169,7 @@
     uint16_t result;
     uint8_t upper_byte = (data >> 8) & 0xFF;
     uint8_t lower_byte =  data & 0xFF;
+    ad5270.format(8, _SPI_MODE);
     cs = false;
     result  = ((ad5270.write(upper_byte)) << 8);
     result |=   ad5270.write(lower_byte);
@@ -132,3 +185,99 @@
 {
     return _max_resistance;
 }
+
+/**
+ * Writes the wiper register. This includes reading the control register,
+ * setting write protect off, writing the wiper, and reverting the settings
+ * to the control reg.
+ * @param data to be written
+ */
+void AD5270::write_wiper_reg(uint16_t data)
+{
+    uint8_t reg_val = read_ctrl_reg();
+    write_cmd(WRITE_CTRL_REG, reg_val | RDAC_WRITE_PROTECT); // RDAC register write protect -  allow update of wiper position through digital interface
+    write_cmd(WRITE_RDAC, data); // write data to the RDAC register
+    write_cmd(WRITE_CTRL_REG, reg_val); // RDAC register write protect -  allow update of wiper position through digital interface
+}
+
+/**
+ * Reads the wiper register value
+ * @return value of the wiper register
+ */
+uint16_t AD5270::read_wiper_reg(void)
+{
+    uint16_t RDAC_val;
+    write_cmd(READ_RDAC);
+    wait_us(_REG_OPERATION_TIMEOUT);
+    RDAC_val = write_cmd(NO_OP);
+    return RDAC_val;
+}
+
+/**
+ * Reads the last programmed value of the 50TP memory
+ * @return last programmed value
+ */
+uint8_t AD5270::read_50TP_last_address(void)
+{
+    uint8_t ret_val;
+    write_cmd(READ_50TP_ADDRESS);
+    wait_us(_MEMORY_OPERATION_TIMEOUT);
+    ret_val = write_cmd(NO_OP);
+    return ret_val;
+}
+
+/**
+ * Reads the content of a 50TP memory address
+ * @param address memory to be read
+ * @return value stored in the 50TP address
+ */
+uint16_t AD5270::read_50TP_memory(uint8_t address)
+{
+    uint16_t ret_val;
+    write_cmd(READ_50TP_CONTENTS, address);
+    wait_us(_MEMORY_OPERATION_TIMEOUT);
+    ret_val = write_cmd(NO_OP);
+    return ret_val;
+}
+
+/**
+ * Writes the control register
+ * @param data to be written
+ */
+void AD5270::write_ctrl_reg(uint8_t data)
+{
+    write_cmd(WRITE_CTRL_REG, data);
+}
+
+/**
+ * Reads the control register
+ * @return value of the control register
+ */
+uint8_t AD5270::read_ctrl_reg(void)
+{
+    uint8_t ret_val;
+    write_cmd(READ_CTRL_REG);
+    wait_us(_REG_OPERATION_TIMEOUT);
+    ret_val = write_cmd(NO_OP);
+    return ret_val;
+}
+
+/**
+ * Resets the wiper register value to the data last written in the 50TP
+ */
+void AD5270::reset_RDAC(void)
+{
+    write_cmd(SW_RST);
+}
+
+/**
+ * Changes the device mode, enabled or shutdown
+ * @param mode - new mode of the device
+ */
+void AD5270::change_mode(AD5270Modes_t mode)
+{
+    write_cmd(SW_SHUTDOWN, static_cast<uint8_t>(mode));
+}
+
+
+
--- a/libraries/ad5270/AD5270.h	Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/ad5270/AD5270.h	Tue Apr 19 17:55:14 2016 +0300
@@ -59,36 +59,77 @@
 
     /// AD5270 commands
     typedef enum {
-        NO_OP               =  0x00,   ///< No data
-        NO_OP_cmd           =  0x0000, ///< 16 bit no data
-        WRITE_RDAC          =  0x04,   ///< Write to the RDAC Register
-        READ_RDAC           =  0x08,   ///< Read from the RDAC Register
-        STORE_50TP          =  0x0C,   ///< Write to the RDAC to memory
-        SW_RST              =  0x10,   ///< Software reset to last memory location
-        READ_50TP_CONTENTS  =  0x14,   ///< Read the last memory contents
-        READ_50TP_ADDRESS   =  0x18,   ///< Read the last memory address
-        WRITE_CTRL_REG      =  0x1C,   ///< Write to the control Register
-        READ_CTRL_REG       =  0x20,   ///< Read from the control Register
-        SW_SHUTDOWN         =  0x24,   ///< Software shutdown (0) - Normal, (1) - Shutdown
-        HI_Zupper           =  0x80,   ///< Get the SDO line ready for High Z
-        HI_Zlower           =  0x01,   ///< Puts AD5270 into High Z mode
+        NO_OP               =  0x00,    ///< No data
+        NO_OP_cmd           =  0x0000,  ///< 16 bit no data
+        WRITE_RDAC          =  0x04,    ///< Write to the RDAC Register
+        READ_RDAC           =  0x08,    ///< Read from the RDAC Register
+        STORE_50TP          =  0x0C,    ///< Write from RDAC to memory
+        SW_RST              =  0x10,    ///< Software reset to last memory location
+        READ_50TP_CONTENTS  =  0x14,    ///< Read the last memory contents
+        READ_50TP_ADDRESS   =  0x18,    ///< Read the last memory address
+        WRITE_CTRL_REG      =  0x1C,    ///< Write to the control Register
+        READ_CTRL_REG       =  0x20,    ///< Read from the control Register
+        SW_SHUTDOWN         =  0x24,    ///< Software shutdown (0) - Normal, (1) - Shutdown
+        HI_Zupper           =  0x80,    ///< Get the SDO line ready for High Z
+        HI_Zlower           =  0x01,    ///< Puts AD5270 into High Z mode
         HI_Z_Cmd            =  0x8001   ///< Puts AD5270 into High Z mode*/
     } AD5270Commands_t;
 
+    typedef enum {
+        NORMAL_MODE = 0,
+        SHUTDOWN_MODE = 1
+    } AD5270Modes_t;
+
+    typedef enum {
+        PROGRAM_50TP_ENABLE = 1,
+        RDAC_WRITE_PROTECT = 2,
+        R_PERFORMANCE_ENABLE = 4,
+        MEMORY_PROGRAM_SUCCESFUL = 8
+    } AD5270ControlRegisterBits_t;
+
+    // SPI configuration & constructor
     AD5270(PinName CS = SPI_CS, float max_resistance = 20000.0, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
+    void frequency(int hz);
+
+    /* RDAC commands */
+    void write_ctrl_reg(uint8_t data);
+    uint8_t read_ctrl_reg(void);
+    void change_mode(AD5270Modes_t mode);
     void set_SDO_HiZ(void);
-    void frequency(int hz);
-    uint16_t calc_RDAC(float resistance);
+
+    /* Wiper R/W methods*/
+    void reset_RDAC(void);
+    void write_wiper_reg(uint16_t data);
+    uint16_t read_wiper_reg(void);
+
+
+    /* Low level methods */
     uint16_t write_cmd(uint8_t command, uint16_t data = 0x00);
     uint16_t write_reg(uint16_t data);
+
+    /* Methods that deal with resistance in float format*/
+    uint16_t calc_RDAC(float resistance);
+    float write_RDAC(float resistance);
+    float read_RDAC(void);
     float get_max_resistance(void);
 
+    /* 50 TP methods */
+    void enable_50TP_programming(void);
+    void store_50TP(void);
+    void disable_50TP_programming(void);
+    uint8_t read_50TP_last_address(void);
+    uint16_t read_50TP_memory(uint8_t address);
+
     SPI ad5270;    ///< SPI instance of the AD5270
-    DigitalOut cs; ///< DigitalOut instance for the chipselect of the AD5270
+    DigitalOut cs; ///< DigitalOut instance for the chip select of the AD5270
 
 private:
     const static int _RESET = 0xff;
+    const static int _REG_OPERATION_TIMEOUT = 2;
+    const static int _MEMORY_OPERATION_TIMEOUT = 6;
+    const static int _WRITE_OPERATION_50TP_TIMEOUT = 350;
     const static int _DUMMY_BYTE = 0xAA;
+    const static uint8_t _SPI_MODE = 1;
     float _max_resistance;
 };
 
--- a/libraries/ad7790/AD7790.cpp	Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/ad7790/AD7790.cpp	Tue Apr 19 17:55:14 2016 +0300
@@ -49,7 +49,6 @@
 #include "mbed.h"
 #include "ad7790.h"
 
-
 /**
  * @brief AD7790 constructor, sets CS pin and SPI format
  * @param CS - (optional)chip select of the AD7790
@@ -57,14 +56,17 @@
  * @param MISO - (optional)pin of the SPI interface
  * @param SCK  - (optional)pin of the SPI interface
  */
-AD7790::AD7790(PinName CS,
+AD7790::AD7790(float reference_voltage,
+               PinName CS,
                PinName MOSI,
                PinName MISO,
                PinName SCK) :
-    ad7790(MOSI, MISO, SCK), cs(CS)
+    ad7790(MOSI, MISO, SCK), cs(CS), miso(MISO), _vref(reference_voltage), _PGA_gain(1)
 {
-    ad7790.format(8, 3);
     cs = true; // cs is active low
+    ad7790.format(8, _SPI_MODE);
+    _continous_conversion = true;
+    _channel = DIFFERENTIAL;
 }
 
 /**
@@ -83,74 +85,314 @@
  */
 void AD7790::reset()
 {
+    ad7790.format(8, _SPI_MODE);
     cs = false;
+    wait_us(_DELAY_TIMING);
     ad7790.write(_RESET);
     ad7790.write(_RESET);
     ad7790.write(_RESET);
     ad7790.write(_RESET);
+    wait_us(_DELAY_TIMING);
     cs = true;
+    _continous_conversion = true;
+}
+
+/**
+ * Sets the mode register. Also sets continous mode and range based on the value
+ * written in reg_val
+ * @param reg_val
+ */
+void AD7790::write_mode_reg(uint8_t reg_val)
+{
+    write_reg(MODE_REG, reg_val);
+    uint8_t continous_mode = (reg_val & 0xC0);
+    if(continous_mode == 0x00) {
+        _continous_conversion = true;
+    } else {
+        _continous_conversion = false;
+    }
+    uint8_t range = (reg_val & 0x30);
+    _PGA_gain = 1 << (range >> 4);
+}
+
+/**
+ * Reads the mode register and returns its value
+ * @return value of the mode register
+ */
+uint8_t AD7790::read_mode_reg()
+{
+    return read_reg(MODE_REG);
+}
+
+/**
+ * Writes the filter register
+ * @param regValue value to be written.
+ */
+void AD7790::write_filter_reg(uint8_t reg_val)
+{
+    write_reg(FILTER_REG, reg_val);
+}
+
+/**
+ * Reads the filter register and returns its value
+ * @return the value of the filter register
+ */
+uint8_t AD7790::read_filter_reg()
+{
+    return read_reg(FILTER_REG);
+}
+
+/**
+ * Reads the data register and returns its value
+ * @return value of the data register
+ */
+uint16_t AD7790::read_data_reg()
+{
+    uint16_t data_result;
+    ad7790.format(8, _SPI_MODE);
+    cs = false;
+    ad7790.write(_DATA_READ | (static_cast<uint8_t>(_channel)));
+    data_result  = ((ad7790.write(_DUMMY_BYTE)) << 8);
+    data_result |=  (ad7790.write(_DUMMY_BYTE));
+    cs = true;
+    return data_result;
 }
 
 /**
- * @brief Reads the data register of the AD7790
- * @return value of the register
+ * Reads the status register of the ADC and returns its value
+ * @return value of the status reg
  */
-uint16_t AD7790::read_data(void)
+uint8_t AD7790::read_status_reg()
 {
-    uint16_t dataResult = 0;
+    return read_reg(STATUS_REG);
+}
+
+
+/**
+ * @brief Enables/disables continous_conversion mode
+ * In Single Conversion mode, read_u16 method will read the MODE register of the ADC,
+ * then write the Start single conversion bit and wait for the DOUT/RDY pin to go low,
+ * When the pin is driven low, data register is read back from the ADC.
+ *
+ * In Continous conversion mode, read_u16 method will poll the DOUT/RDY pin, if it is low,
+ * the data register is read back from the ADC.
+ *
+ * @param mode
+ * true - continous conversion mode enabled
+ * false - single conversion mode enabled
+ */
+void AD7790::set_conversion_mode(AD7790Mode_t mode)
+{
+    uint8_t mode_reg_val;
+    mode_reg_val = read_mode_reg() & 0x3F;
+    mode_reg_val = mode_reg_val | (static_cast<uint8_t>(mode));
+    write_mode_reg(mode);
+}
 
+/**
+ *  - From mbed AnalogIn API -
+ * @brief Read the input voltage, represented as an unsigned short in the range [0x0, 0xFFFF]
+ * Depending on the conversion mode, this method will have different behavior. Conversion mode is set using
+ * set_continous_conversion_mode(bool).
+ *
+ * In Single Conversion mode, read_u16 method will read the MODE register of the ADC,
+ * then write the Start single conversion bit and wait for the DOUT/RDY pin to go low,
+ * When the pin is driven low, data register is read back from the ADC.
+ *
+ * In Continous conversion mode, read_u16 method will poll the DOUT/RDY pin, if it is low,
+ * the data register is read back from the ADC.
+ *
+ * @return 16-bit unsigned short representing the current input voltage, normalised to a 16-bit value
+ * returns -1 (0xFFFF) along with a debug message if conversion failed.
+ */
+uint16_t AD7790::read_u16(void)
+{
+    uint16_t data_result = 0;
+    ad7790.format(8, _SPI_MODE);
     cs = false;
-    ad7790.write(_DATA_READ);
-    dataResult  = ((ad7790.write(_DUMMY_BYTE)) << 8);
-    dataResult |=  (ad7790.write(_DUMMY_BYTE));
+    uint16_t timeout_cnt = 0;
+    if(_continous_conversion == false) {
+
+        uint8_t mode_reg = read_mode_reg();
+        wait_us(_DELAY_TIMING);
+
+        cs = false;
+        mode_reg = (mode_reg & 0x3F) | MD1; // mask single conversion bits
+        ad7790.write((MODE_REG << 4) | (static_cast<uint8_t>(_channel))); // start single conversion
+        ad7790.write(mode_reg);
+        timeout_cnt = _SINGLE_CONVERSION_TIMEOUT; // starts timeout
+    } else {
+        timeout_cnt = _CONTINOUS_CONVERSION_TIMEOUT; // starts timeout
+    }
+
+    while(miso) { // wait for the MISO pin to go low.
+        if(timeout_cnt) {
+            timeout_cnt--;
+        } else {
+            cs = true;
+#ifdef AD7790_DEBUG_MODE
+            printf("timeout occurred reading the AD7790. "); // error, MISO line didn't toggle
+#endif
+            return -1; // ERROR
+        }
+        wait_us(10);
+    }
+
+    ad7790.write(_DATA_READ |  (static_cast<uint8_t>(_channel)));
+    data_result  = ((ad7790.write(_DUMMY_BYTE)) << 8);
+    data_result |=  (ad7790.write(_DUMMY_BYTE));
     cs = true;
-
-    return dataResult;
+    return data_result;
 }
 
 /**
  * @brief Reads a register of the AD7790
- * @param  regAddress - address of the register
+ * @param  address - address of the register
  * @return value of the register
  */
-uint16_t AD7790::read_reg(AD7790Registers_t regAddress)
+uint16_t AD7790::read_reg(AD7790Register_t address)
 {
-    uint16_t data = regAddress << 12;
+    uint16_t data = address << 12;
     data |= _DUMMY_BYTE;
     data |= _READ_FLAG;
+    data |= (static_cast<uint8_t>(_channel) << 8);
     return	write_spi(data);
 }
 
 /**
  * @brief Writes a register of the AD7790
- * @param regAddress - address of the register
- * @param regValue - value to be written
+ * @param address - address of the register
+ * @param reg_val - value to be written
  * @return none
  *
  */
-void AD7790::write_reg(AD7790Registers_t regAddress, uint8_t regValue)
+void AD7790::write_reg(AD7790Register_t address, uint8_t reg_val)
 {
-    uint16_t data = regAddress << 12;
-    data |= regValue;
-    write_spi(data);
+    uint16_t spi_data = address << 12;
+    spi_data |= reg_val;
+    spi_data |= (static_cast<uint8_t>(_channel) << 8);
+    write_spi(spi_data);
 }
 
 /**
  * @brief Writes 16bit data to the AD7790 SPI interface
- * @param data to be written
+ * @param reg_val to be written
  * @return data returned by the AD7790
  */
-uint16_t AD7790::write_spi(uint16_t data)
+uint16_t AD7790::write_spi(uint16_t reg_val)
 {
-    uint16_t result;
-    uint8_t upper_byte = (data >> 8) & 0xFF;
-    uint8_t lower_byte = data & 0xFF;
+    uint16_t data_result;
+    uint8_t upper_byte = (reg_val >> 8) & 0xFF;
+    uint8_t lower_byte = reg_val & 0xFF;
+    ad7790.format(8, _SPI_MODE);
     cs = false;
-    result  =  (ad7790.write(upper_byte) << 8);
-    result |=   ad7790.write(lower_byte);
+    data_result  =  (ad7790.write(upper_byte) << 8);
+    data_result |=   ad7790.write(lower_byte);
     cs = true;
-    return result;
+    return data_result;
 }
 
 
+/**
+ * Sets the AnalogInputRange to be used by the AD7790
+ * @param range AnalogInputRange_t to be used in voltage computations
+ */
+void AD7790::set_range(AnalogInputRange_t range)
+{
 
+    uint8_t mode_reg_val;
+    mode_reg_val = read_mode_reg() & 0xCF;
+    mode_reg_val = mode_reg_val | (range << 4);
+    write_mode_reg(mode_reg_val);
+}
+
+/**
+ * Sets the reference voltage of the AD7790
+ * @param ref reference voltage to be set
+ */
+void AD7790::set_reference_voltage(float ref)
+{
+    _vref = ref;
+}
+
+/**
+ * Gets the reference voltage of the AD7790
+ * @return reference voltage
+ */
+float AD7790::get_reference_voltage(void)
+{
+    return _vref;
+}
+
+/**
+ * Reads the data register of the ADC and converts the result to volts
+ * Gain needs to be correctly set using set_gain in order to get accurate results
+ * @return voltage of the ADC input
+ */
+float AD7790::read_voltage(void)
+{
+    return data_to_voltage(read_u16());
+}
+
+/**
+ * Converts an uint16_t to voltage.
+ * Gain needs to be correctly set using set_gain in order to get accurate results
+ * @param data in uint16_t format
+ * @return float value of voltage (in V)
+ */
+float AD7790::data_to_voltage(uint16_t data)
+{
+    return ((data / static_cast<float>(_RESOLUTION / 2)) - 1) * (_vref / _PGA_gain);
+}
+
+/**
+ * Converts voltage to an uint16_t.
+ * Gain needs to be correctly set using set_gain in order to get accurate results
+ * @param voltage to be converted
+ * @return data in uint16_t format
+ */
+uint16_t AD7790::voltage_to_data(float voltage)
+{
+    return (((voltage * _PGA_gain / _vref) + 1)   * static_cast<float>(_RESOLUTION / 2));
+}
+
+/**
+ * Sets the conversion channel.
+ * @param channel
+ */
+void AD7790::set_channel(AD7790Channel_t channel)
+{
+    _channel = channel;
+}
+
+/**
+ *  - From mbed AnalogIn API -
+ *  Read the input voltage, represented as a float in the range [0.0, 1.0] - uses the read_u16 method
+ *  @returns A floating-point value representing the current input voltage, measured as a percentage
+ *  returns 1.0 along with a debug message if the conversion failed
+ */
+float AD7790::read(void)
+{
+    float percent;
+    uint16_t data;
+    data = read_u16();
+    percent = (data / static_cast<float>(_RESOLUTION) ); // translate bipolar conversion to [0.0, 1.0] domain
+    return percent;
+}
+
+#ifdef MBED_OPERATORS
+
+/**
+ *  - From mbed AnalogIn API -
+ *  An operator shorthand for read()
+ *  The float() operator can be used as a shorthand for read() to simplify common code sequences
+ */
+AD7790::operator float()
+{
+    return read();
+}
+
+#endif
+
+
+
--- a/libraries/ad7790/AD7790.h	Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/ad7790/AD7790.h	Tue Apr 19 17:55:14 2016 +0300
@@ -53,6 +53,13 @@
 /**
  * @brief Analog Devices AD7790 SPI 16-bit Buffered Sigma-Delta ADC
  */
+
+/**
+ * Comment this line if you want to turn off the debug mode.
+ * The debug mode will send a message if an exception occurs within AD7790 driver
+ */
+#define AD7790_DEBUG_MODE
+
 class AD7790
 {
 public:
@@ -63,33 +70,105 @@
         MODE_REG,              ///< Mode register
         FILTER_REG,            ///< Filter Register
         DATA_REG               ///< Data register
-    } AD7790Registers_t;
+    } AD7790Register_t;
 
     /// AD7790 channel configuration
     typedef enum {
-        DIFFERENTIAL, ///< AIN(+)-AIN(-)
+        DIFFERENTIAL = 0, ///< AIN(+)-AIN(-)
         RESERVED,     ///< reserved
         SHORT,        ///< AIN(-)-AIN(-)
         VDDMONITOR    ///< Monitor VDD
     } AD7790Channel_t;
 
-    AD7790(PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
+    typedef enum {
+        CONTINOUS_CONVERSION_MODE = 0,
+        SINGLE_CONVERSION_MODE = 0x80,
+        SHUTDOWN_MODE = 0xC0
+    } AD7790Mode_t;
+
+    typedef enum    {
+        MD1 = 0x80, ///< Mode Select Bit 1
+        MD0 = 0x40, ///< Mode Select Bit 0
+        G1 = 0x20,  ///< Range bit 1
+        G0 = 0x10,  ///< Range bit 0
+        BO = 0x08,  ///< Burnout Current Enable bit
+        BUF = 0x02, ///< Buffered mode bit
+    } ModeRegisterBits_t;
+
+    typedef enum {
+        CLKDIV1 = 0x40, ///< Clock divider bit 1
+        CLKDIV0 = 0x20, ///< Clock divider bit 0
+        FS2 = 0x04, ///< Update rate bit 2
+        FS1 = 0x02, ///< Update rate bit 1
+        FS0 = 0x01, ///< Update rate bit 0
+    } FilterRegisterBits_t;
+
+    typedef enum    {
+        RANGE_VREF = 0,
+        RANGE_VREF_DIV_2,
+        RANGE_VREF_DIV_4,
+        RANGE_VREF_DIV_8,
+    } AnalogInputRange_t;
+
+    /** SPI configuration & constructor */
+    AD7790( float reference_voltage, PinName CS = SPI_CS, PinName MOSI = SPI_MOSI, PinName MISO = SPI_MISO, PinName SCK = SPI_SCK);
     void frequency(int hz);
+
+    /** Low level SPI bus comm methods */
     void reset(void);
-    void write_reg(AD7790Registers_t regAddress, uint8_t regValue);
-    uint16_t write_spi(uint16_t data);
-    uint16_t read_reg (AD7790Registers_t regAddress);
-    uint16_t read_data(void);
+
+    /** Register access methods*/
+    void set_channel(AD7790Channel_t channel);
+    void set_conversion_mode(AD7790Mode_t mode);
+    uint16_t read_data_reg();
+    uint8_t read_status_reg(void);
+    void write_filter_reg(uint8_t regVal);
+    uint8_t read_filter_reg(void);
+    void write_mode_reg(uint8_t regVal);
+    uint8_t read_mode_reg(void);
+    void  set_range(AnalogInputRange_t range);
+    AnalogInputRange_t get_range(void);
+
+    /** Reference voltage methods */
+    void  set_reference_voltage(float ref);
+    float get_reference_voltage(void);
+
+    /** Voltage read methods */
+    float read_voltage(void);
+    float data_to_voltage(uint16_t data);
+    uint16_t voltage_to_data(float voltage);
+
+    /** AnalogIn API */
+    float read(void);
+    uint16_t read_u16(void);
+
+#ifdef MBED_OPERATORS
+    operator float();
+#endif
 
     SPI ad7790;    ///< SPI instance of the AD7790
     DigitalOut cs; ///< DigitalOut instance for the chipselect of the AD7790
 
 private:
+    DigitalIn miso;
+    float _vref;
+    uint8_t _PGA_gain;
+    bool _continous_conversion;
+    AD7790Channel_t _channel;
 
-    const static int _RESET = 0xFF;
-    const static int _DUMMY_BYTE = 0xAA;
-    const static int _READ_FLAG = 0x0800;
-    const static int _DATA_READ    = 0x38;             // Read from the Data Register
+    void write_reg(AD7790Register_t regAddress, uint8_t regValue);
+    uint16_t write_spi(uint16_t data);
+    uint16_t read_reg (AD7790Register_t regAddress);
+
+    const static uint16_t _SINGLE_CONVERSION_TIMEOUT = 0xFFFF; // in 10us = 100ms
+    const static uint16_t _CONTINOUS_CONVERSION_TIMEOUT = 0xFFFF;
+    const static uint16_t _RESOLUTION = 0xFFFF;
+    const static uint8_t _RESET = 0xFF;
+    const static uint8_t _DUMMY_BYTE = 0xFF;
+    const static uint16_t _READ_FLAG = 0x0800;
+    const static uint8_t _DATA_READ    = 0x38;             // Read from the Data Register
+    const static uint8_t _DELAY_TIMING = 0x02;
+    const static uint8_t _SPI_MODE = 3;
 };
 
 #endif
--- a/libraries/cn0357/cn0357.cpp	Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/cn0357/cn0357.cpp	Tue Apr 19 17:55:14 2016 +0300
@@ -60,8 +60,9 @@
  */
 CN0357::CN0357(PinName CSAD7790, PinName CSAD5270, PinName MOSI, PinName MISO,
                PinName SCK) :
-    ad7790(CSAD7790, MOSI, MISO, SCK), ad5270(CSAD5270, 20000.0, MOSI, MISO, SCK) ,
-    _sensor_sensitivity(0), _sensor_range(0), _RDACvalue(0)
+    _vref(1.2), _sensor_sensitivity(0), _sensor_range(0), _RDACvalue(0),
+    ad7790(_vref, CSAD7790, MOSI, MISO, SCK), ad5270(CSAD5270, 20000.0, MOSI, MISO, SCK)
+
 {
 }
 
@@ -79,11 +80,11 @@
     ad7790.frequency(500000);
 
     float resistance = set_sensor_parameters(range, sensitivity);
-    _rdac_init(resistance);
+
     if(jp == INTERNAL_AD7790) {
         _AD7790_init(mode_val, filter_val);
     }
-
+    _rdac_init(resistance);
 }
 
 /**
@@ -108,10 +109,13 @@
 void CN0357::_AD7790_init(uint8_t mode_val, uint8_t filter_val)
 {
     ad7790.reset();
-    // wait_ms(1000);
-    ad7790.write_reg(AD7790::MODE_REG, mode_val);
-    ad7790.write_reg(AD7790::FILTER_REG, filter_val);
+    wait_ms(50);
 
+    ad7790.write_mode_reg(mode_val);
+    wait_us(2);
+
+    ad7790.write_filter_reg(filter_val);
+    wait_ms(50);
 }
 
 /**
@@ -120,7 +124,7 @@
  */
 uint8_t CN0357::read_adc_status(void)
 {
-    return ad7790.read_reg(AD7790::STATUS_REG);
+    return ad7790.read_status_reg();
 }
 
 /**
@@ -129,7 +133,7 @@
  */
 float CN0357::read_sensor_voltage(void)
 {
-    return data_to_voltage(read_sensor());
+    return ad7790.read_voltage();
 }
 
 /**
@@ -138,7 +142,7 @@
  */
 uint16_t CN0357::read_sensor(void)
 {
-    return ad7790.read_data();
+    return ad7790.read_u16();
 }
 
 /**
@@ -147,7 +151,7 @@
  */
 float CN0357::read_ppm()
 {
-    return calc_ppm(read_sensor_voltage()); /* Convert voltage to Gas concentration*/
+    return calc_ppm(ad7790.read_voltage()); /* Convert voltage to Gas concentration*/
 }
 
 /**
@@ -169,7 +173,7 @@
  */
 float CN0357::data_to_voltage(uint16_t data)
 {
-    return ((static_cast<float>(data) / pow(2, 15)) - 1) * 1.2; /* Bipolar voltage computation from ADC code */
+    return ad7790.data_to_voltage(data);
 }
 
 /**
@@ -179,12 +183,7 @@
  */
 void CN0357::set_RDAC_value(float resistance)
 {
-    // Compute for the RDAC code nearest to the required feedback resistance
-    uint16_t RDAC_val = (resistance / 20000.0) * 1024.0;
-    // Compute for the constants used in voltage and PPM conversion computation
-    _RDACvalue = ((static_cast<float> (RDAC_val) * 20000.0) / 1024.0);
-    ad5270.write_cmd(AD5270::WRITE_CTRL_REG, 0x02); // RDAC register write protect -  allow update of wiper position through digital interface
-    ad5270.write_cmd(AD5270::WRITE_RDAC, RDAC_val); // write data to the RDAC register
+    _RDACvalue = ad5270.write_RDAC(resistance);
 }
 
 /**
@@ -208,7 +207,7 @@
 {
     _sensor_sensitivity = static_cast<float>(sensitivity);
     _sensor_range = range;
-    return (1.2 / (static_cast<float>(_sensor_range * _sensor_sensitivity)));
+    return (_vref / (static_cast<float>(_sensor_range * _sensor_sensitivity)));
 }
 
 /**
--- a/libraries/cn0357/cn0357.h	Fri Apr 01 10:53:41 2016 +0300
+++ b/libraries/cn0357/cn0357.h	Tue Apr 19 17:55:14 2016 +0300
@@ -59,6 +59,15 @@
 {
 public:
 
+private:
+    float _vref;
+    float _sensor_sensitivity;
+    float _sensor_range;
+    float _RDACvalue;
+public:
+    AD7790 ad7790; ///< AD7790 instance - can be used for manual overriding
+    AD5270 ad5270; ///< AD5270 instance - can be used for manual overriding
+
     /// CN0357 shield jumper configuration
     typedef enum {
         INTERNAL_AD7790 = 0, 	///< The shield's AD7790 is used
@@ -75,27 +84,22 @@
     float calc_ppm(float adcVoltage);
     float read_ppm(void);
 
+    void set_vref(float vref);
+    float get_vref(void);
+
     void  set_RDAC_value(float resistor_val);
     float get_RDAC_value(void);
     float set_sensor_parameters(float range, float sensitivity);
     float get_sensor_range(void);
     float get_sensor_sensitivity(void);
 
-
-    AD7790 ad7790; ///< AD7790 instance - can be used for manual overriding
-    AD5270 ad5270; ///< AD5270 instance - can be used for manual overriding
-
 private:
     const static int _RESET = 0xff;
-    const static int _DEFAULT_MODE_VAL = 0x00;
-    const static int _DEFAULT_FILTER_VAL = 0x07;
-    float _sensor_sensitivity;
-    float _sensor_range;
-    float _RDACvalue;
+    const static int _DEFAULT_MODE_VAL = AD7790::MD1 | AD7790::MD0; // POWERDOWN MODE
+    const static int _DEFAULT_FILTER_VAL = AD7790::FS0 | AD7790::FS1 | AD7790::FS2;
     void _rdac_init(float resistanceValue);
     void _AD7790_init(uint8_t mode_val, uint8_t filter_val);
 
-
 };
 
 #endif // CN0357_H