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

Revision:
4:5c1b28aff7e1
Parent:
3:1a8c14043a4e
Child:
11:2e67c719ce37
--- 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
+
+
+