--- /dev/null
+/**************************************************************************/
+/*!
+ @file ads1015.c
+ @author K. Townsend (microBuilder.eu)
+
+ @brief Drivers for the TI ADS1015 12-Bit I2C ADC
+
+ @section DESCRIPTION
+
+ The ADS1015 is a 4-channel, 12-bit I2C ADC with a programmable
+ comparator and an internal PGA (from 2/3 to 16x gain). It can be
+ configured for four single-ended channels or two differential inputs.
+ The comparator can be used in both traditional and windowed mode.
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2012, K. Townsend
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. 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.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, 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 "ads1015.h"
+#include "core/systick/systick.h"
+
+extern volatile uint8_t I2CMasterBuffer[I2C_BUFSIZE];
+extern volatile uint8_t I2CSlaveBuffer[I2C_BUFSIZE];
+extern volatile uint32_t I2CReadLength, I2CWriteLength;
+
+static bool _ads1015Initialised = false;
+
+/**************************************************************************/
+/*!
+ @brief Sends a single command byte over I2C
+*/
+/**************************************************************************/
+static ads1015Error_t ads1015WriteRegister (uint8_t reg, uint16_t value)
+{
+ ads1015Error_t error = ADS1015_ERROR_OK;
+
+ // Clear write buffers
+ uint32_t i;
+ for ( i = 0; i < I2C_BUFSIZE; i++ )
+ {
+ I2CMasterBuffer[i] = 0x00;
+ }
+
+ I2CWriteLength = 4;
+ I2CReadLength = 0;
+ I2CMasterBuffer[0] = ADS1015_ADDRESS; // I2C device address
+ I2CMasterBuffer[1] = reg; // Register
+ I2CMasterBuffer[2] = value >> 8; // Upper 8-bits
+ I2CMasterBuffer[3] = value & 0xFF; // Lower 8-bits
+ i2cEngine();
+
+ // ToDo: Add in proper I2C error-checking
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads a 16 bit values over I2C
+*/
+/**************************************************************************/
+static ads1015Error_t ina219Read16(uint8_t reg, uint16_t *value)
+{
+ ads1015Error_t error = ADS1015_ERROR_OK;
+
+ // Clear write buffers
+ uint32_t i;
+ for ( i = 0; i < I2C_BUFSIZE; i++ )
+ {
+ I2CMasterBuffer[i] = 0x00;
+ }
+
+ I2CWriteLength = 2;
+ I2CReadLength = 2;
+ I2CMasterBuffer[0] = ADS1015_ADDRESS; // I2C device address
+ I2CMasterBuffer[1] = reg; // Command register
+ // Append address w/read bit
+ I2CMasterBuffer[2] = ADS1015_ADDRESS | ADS1015_READBIT;
+ i2cEngine();
+
+ // Shift values to create properly formed integer
+ *value = ((I2CSlaveBuffer[0] << 8) | I2CSlaveBuffer[1]);
+
+ // ToDo: Add in proper I2C error-checking
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Initialises the I2C block
+*/
+/**************************************************************************/
+ads1015Error_t ads1015Init(void)
+{
+ ads1015Error_t error = ADS1015_ERROR_OK;
+
+ // Initialise I2C
+ if (i2cInit(I2CMASTER) == false)
+ {
+ return ADS1015_ERROR_I2CINIT; /* Fatal error */
+ }
+
+ _ads1015Initialised = true;
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads the 12-bit conversion results from the specified channel
+*/
+/**************************************************************************/
+ads1015Error_t ads1015ReadADC_SingleEnded(uint8_t channel, uint16_t *value)
+{
+ ads1015Error_t error = ADS1015_ERROR_OK;
+
+ if (!(_ads1015Initialised))
+ {
+ ads1015Init();
+ }
+
+ if (channel > 3)
+ {
+ *value = 0;
+ return ADS1015_ERROR_INVALIDCHANNEL;
+ }
+
+ // Start with default values
+ uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
+ ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
+ ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
+ ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
+ ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default)
+ ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)
+
+ // Set PGA/voltage range
+ config |= ADS1015_REG_CONFIG_PGA_6_144V; // +/- 6.144V range (limited to VDD +0.3V max!)
+
+ // Set single-ended input channel
+ switch (channel)
+ {
+ case (0):
+ config |= ADS1015_REG_CONFIG_MUX_SINGLE_0;
+ break;
+ case (1):
+ config |= ADS1015_REG_CONFIG_MUX_SINGLE_1;
+ break;
+ case (2):
+ config |= ADS1015_REG_CONFIG_MUX_SINGLE_2;
+ break;
+ case (3):
+ config |= ADS1015_REG_CONFIG_MUX_SINGLE_3;
+ break;
+ }
+
+ // Set 'start single-conversion' bit
+ config |= ADS1015_REG_CONFIG_OS_SINGLE;
+
+ // Write config register to the ADC
+ error = ads1015WriteRegister(ADS1015_REG_POINTER_CONFIG, config);
+ if (error) return error;
+
+ // Wait for the conversion to complete
+ systickDelay(1);
+
+ // Read the conversion results
+ error = ina219Read16(ADS1015_REG_POINTER_CONVERT, value);
+ if (error) return error;
+
+ // Shift results 4-bits to the right
+ *value = *value >> 4;
+
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads the 12-bit conversion results, measuring the voltage
+ difference between the P (AIN0) and N (AIN1) input. Generates
+ a signed 12-bit value since the difference can be either
+ positive or negative.
+*/
+/**************************************************************************/
+ads1015Error_t ads1015ReadADC_Differential_0_1(int16_t *value)
+{
+ ads1015Error_t error = ADS1015_ERROR_OK;
+
+ if (!(_ads1015Initialised))
+ {
+ ads1015Init();
+ }
+
+ // Start with default values
+ uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
+ ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
+ ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
+ ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
+ ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default)
+ ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)
+
+ // Set PGA/voltage range
+ config |= ADS1015_REG_CONFIG_PGA_6_144V; // +/- 6.144V range (limited to VDD +0.3V max!)
+
+ // Set channels
+ config |= ADS1015_REG_CONFIG_MUX_DIFF_0_1; // AIN0 = P, AIN1 = N
+
+ // Set 'start single-conversion' bit
+ config |= ADS1015_REG_CONFIG_OS_SINGLE;
+
+ // Write config register to the ADC
+ error = ads1015WriteRegister(ADS1015_REG_POINTER_CONFIG, config);
+ if (error) return error;
+
+ // Wait for the conversion to complete
+ systickDelay(1);
+
+ // Read the conversion results
+ error = ina219Read16(ADS1015_REG_POINTER_CONVERT, value);
+ if (error) return error;
+
+ // Shift results 4-bits to the right
+ *value = *value >> 4;
+
+ return error;
+}
+
+/**************************************************************************/
+/*!
+ @brief Reads the 12-bit conversion results, measuring the voltage
+ difference between the P (AIN2) and N (AIN3) input. Generates
+ a signed 12-bit value since the difference can be either
+ positive or negative.
+*/
+/**************************************************************************/
+ads1015Error_t ads1015ReadADC_Differential_2_3(int16_t *value)
+{
+ ads1015Error_t error = ADS1015_ERROR_OK;
+
+ if (!(_ads1015Initialised))
+ {
+ ads1015Init();
+ }
+
+ // Start with default values
+ uint16_t config = ADS1015_REG_CONFIG_CQUE_NONE | // Disable the comparator (default val)
+ ADS1015_REG_CONFIG_CLAT_NONLAT | // Non-latching (default val)
+ ADS1015_REG_CONFIG_CPOL_ACTVLOW | // Alert/Rdy active low (default val)
+ ADS1015_REG_CONFIG_CMODE_TRAD | // Traditional comparator (default val)
+ ADS1015_REG_CONFIG_DR_1600SPS | // 1600 samples per second (default)
+ ADS1015_REG_CONFIG_MODE_SINGLE; // Single-shot mode (default)
+
+ // Set PGA/voltage range
+ config |= ADS1015_REG_CONFIG_PGA_6_144V; // +/- 6.144V range (limited to VDD +0.3V max!)
+
+ // Set channels
+ config |= ADS1015_REG_CONFIG_MUX_DIFF_2_3; // AIN2 = P, AIN3 = N
+
+ // Set 'start single-conversion' bit
+ config |= ADS1015_REG_CONFIG_OS_SINGLE;
+
+ // Write config register to the ADC
+ error = ads1015WriteRegister(ADS1015_REG_POINTER_CONFIG, config);
+ if (error) return error;
+
+ // Wait for the conversion to complete
+ systickDelay(1);
+
+ // Read the conversion results
+ error = ina219Read16(ADS1015_REG_POINTER_CONVERT, value);
+ if (error) return error;
+
+ // Shift results 4-bits to the right
+ *value = *value >> 4;
+
+ return error;
+}
+
--- /dev/null
+/**************************************************************************/
+/*!
+ @file ads1015.h
+ @author K. Townsend (microBuilder.eu)
+
+ @section LICENSE
+
+ Software License Agreement (BSD License)
+
+ Copyright (c) 2012, K. Townsend
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. 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.
+ 3. Neither the name of the copyright holders nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, 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 _ADS1015_H_
+#define _ADS1015_H_
+
+#include "projectconfig.h"
+#include "core/i2c/i2c.h"
+
+/*=========================================================================
+ I2C ADDRESS/BITS
+ -----------------------------------------------------------------------*/
+ #define ADS1015_ADDRESS (0x90) // 1001 000 shifted left 1 bit = 0x90 (ADDR = GND)
+ #define ADS1015_READBIT (0x01)
+/*=========================================================================*/
+
+/*=========================================================================
+ POINTER REGISTER
+ -----------------------------------------------------------------------*/
+ #define ADS1015_REG_POINTER_MASK (0x03)
+ #define ADS1015_REG_POINTER_CONVERT (0x00)
+ #define ADS1015_REG_POINTER_CONFIG (0x01)
+ #define ADS1015_REG_POINTER_LOWTHRESH (0x02)
+ #define ADS1015_REG_POINTER_HITHRESH (0x03)
+/*=========================================================================*/
+
+/*=========================================================================
+ CONFIG REGISTER
+ -----------------------------------------------------------------------*/
+ #define ADS1015_REG_CONFIG_OS_MASK (0x8000)
+ #define ADS1015_REG_CONFIG_OS_SINGLE (0x8000) // Write: Set to start a single-conversion
+ #define ADS1015_REG_CONFIG_OS_BUSY (0x0000) // Read: Bit = 0 when conversion is in progress
+ #define ADS1015_REG_CONFIG_OS_NOTBUSY (0x8000) // Read: Bit = 1 when device is not performing a conversion
+
+ #define ADS1015_REG_CONFIG_MUX_MASK (0x7000)
+ #define ADS1015_REG_CONFIG_MUX_DIFF_0_1 (0x0000) // Differential P = AIN0, N = AIN1 (default)
+ #define ADS1015_REG_CONFIG_MUX_DIFF_0_3 (0x1000) // Differential P = AIN0, N = AIN3
+ #define ADS1015_REG_CONFIG_MUX_DIFF_1_3 (0x2000) // Differential P = AIN1, N = AIN3
+ #define ADS1015_REG_CONFIG_MUX_DIFF_2_3 (0x3000) // Differential P = AIN2, N = AIN3
+ #define ADS1015_REG_CONFIG_MUX_SINGLE_0 (0x4000) // Single-ended AIN0
+ #define ADS1015_REG_CONFIG_MUX_SINGLE_1 (0x5000) // Single-ended AIN1
+ #define ADS1015_REG_CONFIG_MUX_SINGLE_2 (0x6000) // Single-ended AIN2
+ #define ADS1015_REG_CONFIG_MUX_SINGLE_3 (0x7000) // Single-ended AIN3
+
+ #define ADS1015_REG_CONFIG_PGA_MASK (0x0E00)
+ #define ADS1015_REG_CONFIG_PGA_6_144V (0x0000) // +/-6.144V range
+ #define ADS1015_REG_CONFIG_PGA_4_096V (0x0200) // +/-4.096V range
+ #define ADS1015_REG_CONFIG_PGA_2_048V (0x0400) // +/-2.048V range (default)
+ #define ADS1015_REG_CONFIG_PGA_1_024V (0x0600) // +/-1.024V range
+ #define ADS1015_REG_CONFIG_PGA_0_512V (0x0800) // +/-0.512V range
+ #define ADS1015_REG_CONFIG_PGA_0_256V (0x0A00) // +/-0.256V range
+
+ #define ADS1015_REG_CONFIG_MODE_MASK (0x0100)
+ #define ADS1015_REG_CONFIG_MODE_CONTIN (0x0000) // Continuous conversion mode
+ #define ADS1015_REG_CONFIG_MODE_SINGLE (0x0100) // Power-down single-shot mode (default)
+
+ #define ADS1015_REG_CONFIG_DR_MASK (0x00E0)
+ #define ADS1015_REG_CONFIG_DR_128SPS (0x0000) // 128 samples per second
+ #define ADS1015_REG_CONFIG_DR_250SPS (0x0020) // 250 samples per second
+ #define ADS1015_REG_CONFIG_DR_490SPS (0x0040) // 490 samples per second
+ #define ADS1015_REG_CONFIG_DR_920SPS (0x0050) // 920 samples per second
+ #define ADS1015_REG_CONFIG_DR_1600SPS (0x0080) // 1600 samples per second (default)
+ #define ADS1015_REG_CONFIG_DR_2400SPS (0x00A0) // 2400 samples per second
+ #define ADS1015_REG_CONFIG_DR_3300SPS (0x00C0) // 3300 samples per second
+
+ #define ADS1015_REG_CONFIG_CMODE_MASK (0x0010)
+ #define ADS1015_REG_CONFIG_CMODE_TRAD (0x0000) // Traditional comparator with hysteresis (default)
+ #define ADS1015_REG_CONFIG_CMODE_WINDOW (0x0010) // Window comparator
+
+ #define ADS1015_REG_CONFIG_CPOL_MASK (0x0008)
+ #define ADS1015_REG_CONFIG_CPOL_ACTVLOW (0x0000) // ALERT/RDY pin is low when active (default)
+ #define ADS1015_REG_CONFIG_CPOL_ACTVHI (0x0008) // ALERT/RDY pin is high when active
+
+ #define ADS1015_REG_CONFIG_CLAT_MASK (0x0004) // Determines if ALERT/RDY pin latches once asserted
+ #define ADS1015_REG_CONFIG_CLAT_NONLAT (0x0000) // Non-latching comparator (default)
+ #define ADS1015_REG_CONFIG_CLAT_LATCH (0x0004) // Latching comparator
+
+ #define ADS1015_REG_CONFIG_CQUE_MASK (0x0003)
+ #define ADS1015_REG_CONFIG_CQUE_1CONV (0x0000) // Assert ALERT/RDY after one conversions
+ #define ADS1015_REG_CONFIG_CQUE_2CONV (0x0001) // Assert ALERT/RDY after two conversions
+ #define ADS1015_REG_CONFIG_CQUE_4CONV (0x0002) // Assert ALERT/RDY after four conversions
+ #define ADS1015_REG_CONFIG_CQUE_NONE (0x0003) // Disable the comparator and put ALERT/RDY in high state (default)
+/*=========================================================================*/
+
+typedef enum
+{
+ ADS1015_ERROR_OK = 0, // Everything executed normally
+ ADS1015_ERROR_I2CINIT, // Unable to initialise I2C
+ ADS1015_ERROR_I2CBUSY, // I2C already in use
+ ADS1015_ERROR_INVALIDCHANNEL, // Invalid channel specified
+ ADS1015_ERROR_LAST
+}
+ads1015Error_t;
+
+ads1015Error_t ads1015Init(void);
+ads1015Error_t ads1015ReadADC_SingleEnded(uint8_t channel, uint16_t *value);
+ads1015Error_t ads1015ReadADC_Differential_0_1(int16_t *value);
+ads1015Error_t ads1015ReadADC_Differential_2_3(int16_t *value);
+
+#endif
+
+