From: Kevin Townsend Date: Sat, 23 Jun 2012 11:14:10 +0000 (+0200) Subject: First commit X-Git-Url: http://git.rohieb.name/hackover2013-badge-firmware.git/commitdiff_plain/6c53c4bb1043958aaf68848f1cd7d41610a69c15 First commit --- diff --git a/drivers/adc/ads1015/ads1015.c b/drivers/adc/ads1015/ads1015.c new file mode 100644 index 0000000..7f37cc2 --- /dev/null +++ b/drivers/adc/ads1015/ads1015.c @@ -0,0 +1,301 @@ +/**************************************************************************/ +/*! + @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; +} + diff --git a/drivers/adc/ads1015/ads1015.h b/drivers/adc/ads1015/ads1015.h new file mode 100644 index 0000000..d083c64 --- /dev/null +++ b/drivers/adc/ads1015/ads1015.h @@ -0,0 +1,135 @@ +/**************************************************************************/ +/*! + @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 + +