From 4085ae3ddfbbf10c8ccbd3dccd43452c40a1fe40 Mon Sep 17 00:00:00 2001 From: Yuval Adam Date: Fri, 13 Mar 2015 12:24:52 +0200 Subject: Add bootloader, nfclib and sensorlib --- sensorlib/Makefile | 88 + sensorlib/ak8963.c | 666 ++++++ sensorlib/ak8963.h | 160 ++ sensorlib/ak8975.c | 558 +++++ sensorlib/ak8975.h | 148 ++ sensorlib/bmp180.c | 919 ++++++++ sensorlib/bmp180.h | 207 ++ sensorlib/bq27510g3.c | 1398 ++++++++++++ sensorlib/bq27510g3.h | 210 ++ sensorlib/ccs/.ccsproject | 9 + sensorlib/ccs/.cproject | 147 ++ sensorlib/ccs/.project | 140 ++ .../ccs/.settings/org.eclipse.cdt.codan.core.prefs | 3 + sensorlib/ccs/Debug/sensorlib.lib | Bin 0 -> 953848 bytes sensorlib/ccs/macros.ini_initial | 1 + sensorlib/cm3218.c | 468 ++++ sensorlib/cm3218.h | 149 ++ sensorlib/comp_dcm.c | 634 ++++++ sensorlib/comp_dcm.h | 120 ++ sensorlib/ewarm/Exe/sensorlib.a | Bin 0 -> 740558 bytes sensorlib/gcc/libsensor.a | Bin 0 -> 87204 bytes sensorlib/hw_ak8963.h | 209 ++ sensorlib/hw_ak8975.h | 177 ++ sensorlib/hw_bmp180.h | 349 +++ sensorlib/hw_bq27510g3.h | 148 ++ sensorlib/hw_cm3218.h | 96 + sensorlib/hw_isl29023.h | 128 ++ sensorlib/hw_kxti9.h | 619 ++++++ sensorlib/hw_l3gd20h.h | 468 ++++ sensorlib/hw_lsm303d.h | 1017 +++++++++ sensorlib/hw_lsm303dlhc.h | 1034 +++++++++ sensorlib/hw_mpu6050.h | 1313 ++++++++++++ sensorlib/hw_mpu9150.h | 1454 +++++++++++++ sensorlib/hw_sht21.h | 76 + sensorlib/hw_tmp006.h | 75 + sensorlib/hw_tmp100.h | 93 + sensorlib/i2cm_drv.c | 2256 ++++++++++++++++++++ sensorlib/i2cm_drv.h | 544 +++++ sensorlib/isl29023.c | 668 ++++++ sensorlib/isl29023.h | 166 ++ sensorlib/kxti9.c | 777 +++++++ sensorlib/kxti9.h | 170 ++ sensorlib/l3gd20h.c | 722 +++++++ sensorlib/l3gd20h.h | 158 ++ sensorlib/lsm303d.c | 835 ++++++++ sensorlib/lsm303d.h | 186 ++ sensorlib/lsm303dlhc_accel.c | 662 ++++++ sensorlib/lsm303dlhc_accel.h | 163 ++ sensorlib/lsm303dlhc_mag.c | 615 ++++++ sensorlib/lsm303dlhc_mag.h | 164 ++ sensorlib/magneto.c | 248 +++ sensorlib/magneto.h | 92 + sensorlib/mpu6050.c | 879 ++++++++ sensorlib/mpu6050.h | 174 ++ sensorlib/mpu9150.c | 1180 ++++++++++ sensorlib/mpu9150.h | 187 ++ sensorlib/quaternion.c | 286 +++ sensorlib/quaternion.h | 70 + sensorlib/readme.txt | 21 + sensorlib/rvmdk/sensorlib.lib | Bin 0 -> 879928 bytes sensorlib/sensorlib.ewp | 833 ++++++++ sensorlib/sensorlib.uvopt | 524 +++++ sensorlib/sensorlib.uvproj | 510 +++++ sensorlib/sht21.c | 564 +++++ sensorlib/sht21.h | 156 ++ sensorlib/tmp006.c | 606 ++++++ sensorlib/tmp006.h | 157 ++ sensorlib/tmp100.c | 582 +++++ sensorlib/tmp100.h | 156 ++ sensorlib/vector.c | 139 ++ sensorlib/vector.h | 61 + 71 files changed, 28792 insertions(+) create mode 100644 sensorlib/Makefile create mode 100644 sensorlib/ak8963.c create mode 100644 sensorlib/ak8963.h create mode 100644 sensorlib/ak8975.c create mode 100644 sensorlib/ak8975.h create mode 100644 sensorlib/bmp180.c create mode 100644 sensorlib/bmp180.h create mode 100644 sensorlib/bq27510g3.c create mode 100644 sensorlib/bq27510g3.h create mode 100644 sensorlib/ccs/.ccsproject create mode 100644 sensorlib/ccs/.cproject create mode 100644 sensorlib/ccs/.project create mode 100644 sensorlib/ccs/.settings/org.eclipse.cdt.codan.core.prefs create mode 100644 sensorlib/ccs/Debug/sensorlib.lib create mode 100644 sensorlib/ccs/macros.ini_initial create mode 100644 sensorlib/cm3218.c create mode 100644 sensorlib/cm3218.h create mode 100644 sensorlib/comp_dcm.c create mode 100644 sensorlib/comp_dcm.h create mode 100644 sensorlib/ewarm/Exe/sensorlib.a create mode 100644 sensorlib/gcc/libsensor.a create mode 100644 sensorlib/hw_ak8963.h create mode 100644 sensorlib/hw_ak8975.h create mode 100644 sensorlib/hw_bmp180.h create mode 100644 sensorlib/hw_bq27510g3.h create mode 100644 sensorlib/hw_cm3218.h create mode 100644 sensorlib/hw_isl29023.h create mode 100644 sensorlib/hw_kxti9.h create mode 100644 sensorlib/hw_l3gd20h.h create mode 100644 sensorlib/hw_lsm303d.h create mode 100644 sensorlib/hw_lsm303dlhc.h create mode 100644 sensorlib/hw_mpu6050.h create mode 100644 sensorlib/hw_mpu9150.h create mode 100644 sensorlib/hw_sht21.h create mode 100644 sensorlib/hw_tmp006.h create mode 100644 sensorlib/hw_tmp100.h create mode 100644 sensorlib/i2cm_drv.c create mode 100644 sensorlib/i2cm_drv.h create mode 100644 sensorlib/isl29023.c create mode 100644 sensorlib/isl29023.h create mode 100644 sensorlib/kxti9.c create mode 100644 sensorlib/kxti9.h create mode 100644 sensorlib/l3gd20h.c create mode 100644 sensorlib/l3gd20h.h create mode 100644 sensorlib/lsm303d.c create mode 100644 sensorlib/lsm303d.h create mode 100644 sensorlib/lsm303dlhc_accel.c create mode 100644 sensorlib/lsm303dlhc_accel.h create mode 100644 sensorlib/lsm303dlhc_mag.c create mode 100644 sensorlib/lsm303dlhc_mag.h create mode 100644 sensorlib/magneto.c create mode 100644 sensorlib/magneto.h create mode 100644 sensorlib/mpu6050.c create mode 100644 sensorlib/mpu6050.h create mode 100644 sensorlib/mpu9150.c create mode 100644 sensorlib/mpu9150.h create mode 100644 sensorlib/quaternion.c create mode 100644 sensorlib/quaternion.h create mode 100644 sensorlib/readme.txt create mode 100644 sensorlib/rvmdk/sensorlib.lib create mode 100644 sensorlib/sensorlib.ewp create mode 100644 sensorlib/sensorlib.uvopt create mode 100644 sensorlib/sensorlib.uvproj create mode 100644 sensorlib/sht21.c create mode 100644 sensorlib/sht21.h create mode 100644 sensorlib/tmp006.c create mode 100644 sensorlib/tmp006.h create mode 100644 sensorlib/tmp100.c create mode 100644 sensorlib/tmp100.h create mode 100644 sensorlib/vector.c create mode 100644 sensorlib/vector.h (limited to 'sensorlib') diff --git a/sensorlib/Makefile b/sensorlib/Makefile new file mode 100644 index 0000000..3b8f43c --- /dev/null +++ b/sensorlib/Makefile @@ -0,0 +1,88 @@ +#****************************************************************************** +# +# Makefile - Rules for building the sensor library. +# +# Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +# Software License Agreement +# +# Texas Instruments (TI) is supplying this software for use solely and +# exclusively on TI's microcontroller products. The software is owned by +# TI and/or its suppliers, and is protected under applicable copyright +# laws. You may not combine this software with "viral" open-source +# software in order to form a larger program. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +# NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +# NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +# CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +# DAMAGES, FOR ANY REASON WHATSOEVER. +# +# This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +# +#****************************************************************************** + +# +# The base directory for TivaWare. +# +ROOT=.. + +# +# Include the common make definitions. +# +include ${ROOT}/makedefs + +# +# Where to find header files that do not live in the source directory. +# +IPATH=.. + +# +# The default rule, which causes the sensor library to be built. +# +all: ${COMPILER} +all: ${COMPILER}/libsensor.a + +# +# The rule to clean out all the build products. +# +clean: + @rm -rf ${COMPILER} ${wildcard *~} + +# +# The rule to create the target directory. +# +${COMPILER}: + @mkdir -p ${COMPILER} + +# +# Rules for building the sensor library. +# +${COMPILER}/libsensor.a: ${COMPILER}/ak8963.o +${COMPILER}/libsensor.a: ${COMPILER}/ak8975.o +${COMPILER}/libsensor.a: ${COMPILER}/bmp180.o +${COMPILER}/libsensor.a: ${COMPILER}/bq27510g3.o +${COMPILER}/libsensor.a: ${COMPILER}/cm3218.o +${COMPILER}/libsensor.a: ${COMPILER}/comp_dcm.o +${COMPILER}/libsensor.a: ${COMPILER}/i2cm_drv.o +${COMPILER}/libsensor.a: ${COMPILER}/isl29023.o +${COMPILER}/libsensor.a: ${COMPILER}/kxti9.o +${COMPILER}/libsensor.a: ${COMPILER}/l3gd20h.o +${COMPILER}/libsensor.a: ${COMPILER}/lsm303d.o +${COMPILER}/libsensor.a: ${COMPILER}/lsm303dlhc_accel.o +${COMPILER}/libsensor.a: ${COMPILER}/lsm303dlhc_mag.o +${COMPILER}/libsensor.a: ${COMPILER}/magneto.o +${COMPILER}/libsensor.a: ${COMPILER}/mpu6050.o +${COMPILER}/libsensor.a: ${COMPILER}/mpu9150.o +${COMPILER}/libsensor.a: ${COMPILER}/quaternion.o +${COMPILER}/libsensor.a: ${COMPILER}/sht21.o +${COMPILER}/libsensor.a: ${COMPILER}/tmp006.o +${COMPILER}/libsensor.a: ${COMPILER}/tmp100.o +${COMPILER}/libsensor.a: ${COMPILER}/vector.o + +# +# Include the automatically generated dependency files. +# +ifneq (${MAKECMDGOALS},clean) +-include ${wildcard ${COMPILER}/*.d} __dummy__ +endif diff --git a/sensorlib/ak8963.c b/sensorlib/ak8963.c new file mode 100644 index 0000000..5b605a6 --- /dev/null +++ b/sensorlib/ak8963.c @@ -0,0 +1,666 @@ +//***************************************************************************** +// +// ak8963.c - Driver for the AK8963 magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_ak8963.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/ak8963.h" + +//***************************************************************************** +// +//! \addtogroup ak8963_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the AK8963 state machine. +// +//***************************************************************************** +#define AK8963_STATE_IDLE 0 // State machine is idle +#define AK8963_STATE_READ 1 // Waiting for read +#define AK8963_STATE_WRITE 2 // Waiting for write +#define AK8963_STATE_RMW 3 // Waiting for read-modify-write + +//***************************************************************************** +// +// The factors used to convert the magnetometer readings from the AK8963 into +// floating point values in tesla +// +//***************************************************************************** +static const float g_fAK8963Factors[] = +{ + 0.0000006, // 14-bit = .6 uT/LSB + 0.00000015, // 16-bit = .15 uT/LSB +}; + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// AK8963 have completed. +// +//***************************************************************************** +static void +AK8963Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tAK8963 *psInst; + + // + // Convert the instance data into a pointer to a tAK8963 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate + // the error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = AK8963_STATE_IDLE; + } + + // + // Determine the current state of the AK8963 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case AK8963_STATE_READ: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = AK8963_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A write has just completed. + // + case AK8963_STATE_WRITE: + { + // + // Set the bit width to the new value. If the register was not + // modified, the values will be the same so this has no effect. + // + psInst->ui8BitOutput = psInst->ui8NewBitOutput; + + // + // The state machine is now idle. + // + psInst->ui8State = AK8963_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read-modify-write just completed + // + case AK8963_STATE_RMW: + { + // + // See if the AK8963_O_CNTL2 register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + AK8963_O_CNTL2) + { + // + // Extract the AK8963_CNTL2_SRST field + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + AK8963_CNTL2_SRST) + { + // + // A soft reset has happened. Reset the bitoutput + // tracking variable + // + psInst->ui8BitOutput = 0; + } + } + + // + // See if the AK8963_O_CNTL register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + AK8963_O_CNTL) + { + // + // Extract the BITM field + // + psInst->ui8BitOutput = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + AK8963_CNTL_BITM_M) >> AK8963_CNTL_BITM_S); + } + + // + // The state machine is now idle. + // + psInst->ui8State = AK8963_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == AK8963_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the AK8963 driver. +//! +//! \param psInst is a pointer to the AK8963 instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the AK8963 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the AK8963 driver, preparing it for operation. +//! +//! \return Returns 1 if the AK8963 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +AK8963Init(tAK8963 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Initialize the AK8963 instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = AK8963_STATE_IDLE; + psInst->ui8BitOutput = AK8963_CNTL_BITM_14BIT >> AK8963_CNTL_BITM_S; + psInst->ui8NewBitOutput = AK8963_CNTL_BITM_14BIT >> AK8963_CNTL_BITM_S; + + // + // The default settings are ok. Return success and call the callback. + // + if(pfnCallback) + { + pfnCallback(pvCallbackData, 0); + } + + return(1); +} + +//***************************************************************************** +// +//! Reads data from AK8963 registers. +//! +//! \param psInst is a pointer to the AK8963 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the AK8963. +//! +//! \return Returns 1 if the read was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +AK8963Read(tAK8963 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the AK8963 driver is not idle (in other words, there + // is already an outstanding request to the AK8963). + // + if(psInst->ui8State != AK8963_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = AK8963_STATE_READ; + + // + // Read the requested registers from the AK8963. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + AK8963Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = AK8963_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to AK8963 registers. +//! +//! \param psInst is a pointer to the AK8963 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the AK8963. The first byte of the \e pui8Data buffer contains the value to +//! be written into the \e ui8Reg register, the second value contains the data +//! to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +AK8963Write(tAK8963 *psInst, uint_fast8_t ui8Reg, const uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the AK8963 driver is not idle (in other words, there + // is already an outstanding request to the AK8963). + // + if(psInst->ui8State != AK8963_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the CNTL2 register is being written. + // + if((ui8Reg <= AK8963_O_CNTL2) && ((ui8Reg + ui16Count) > AK8963_O_CNTL2)) + { + // + // See if a soft reset is being requested. + // + if(pui8Data[ui8Reg - AK8963_O_CNTL2] & AK8963_CNTL2_SRST) + { + // + // Update the bit width based on the soft reset. + // + psInst->ui8NewBitOutput = 0; + } + } + + // + // See if the CNTL register is being written. + // + if((ui8Reg <= AK8963_O_CNTL) && ((ui8Reg + ui16Count) > AK8963_O_CNTL)) + { + // + // Extract the new value of the BITM field from the CNTL register + // value. + // + psInst->ui8NewBitOutput = ((pui8Data[ui8Reg - AK8963_O_CNTL] & + AK8963_CNTL_BITM_M) >> AK8963_CNTL_BITM_S); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = AK8963_STATE_WRITE; + + // + // Write the requested registers to the AK8963. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, AK8963Callback, + psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = AK8963_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of an AK8963 register. +//! +//! \param psInst is a pointer to the AK8963 instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the AK8963 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! AK8963. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +AK8963ReadModifyWrite(tAK8963 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the AK8963 driver is not idle (in other words, there + // is already an outstanding request to the AK8963). + // + if(psInst->ui8State != AK8963_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = AK8963_STATE_RMW; + + // + // Submit the read-modify-write request to the AK8963. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, AK8963Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = AK8963_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the magnetometer data from the AK8963. +//! +//! \param psInst is a pointer to the AK8963 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the AK8963 data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - AK8963DataMagnetoGetRaw() +//! - AK8963DataMagnetoGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +AK8963DataRead(tAK8963 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the AK8963 driver is not idle (in other words, there + // is already an outstanding request to the AK8963). + // + if(psInst->ui8State != AK8963_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = AK8963_STATE_READ; + + // + // Read the data registers from the AK8963. + // + // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2 = 8 bytes + // + psInst->pui8Data[0] = AK8963_O_ST1; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 1, + psInst->pui8Data, 8, AK8963Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = AK8963_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw magnetometer data from the most recent data read. +//! +//! \param psInst is a pointer to the AK8963 instance data. +//! \param pui16MagnetoX is a pointer to the value into which the raw X-axis +//! magnetometer data is stored. +//! \param pui16MagnetoY is a pointer to the value into which the raw Y-axis +//! magnetometer data is stored. +//! \param pui16MagnetoZ is a pointer to the value into which the raw Z-axis +//! magnetometer data is stored. +//! +//! This function returns the raw magnetometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +AK8963DataMagnetoGetRaw(tAK8963 *psInst, uint_fast16_t *pui16MagnetoX, + uint_fast16_t *pui16MagnetoY, + uint_fast16_t *pui16MagnetoZ) +{ + // + // Return the raw magnetometer values. + // + if(pui16MagnetoX) + { + *pui16MagnetoX = (psInst->pui8Data[2] << 8) | psInst->pui8Data[1]; + } + if(pui16MagnetoY) + { + *pui16MagnetoY = (psInst->pui8Data[4] << 8) | psInst->pui8Data[3]; + } + if(pui16MagnetoZ) + { + *pui16MagnetoZ = (psInst->pui8Data[6] << 8) | psInst->pui8Data[5]; + } +} + +//***************************************************************************** +// +//! Gets the magnetometer data from the most recent data read. +//! +//! \param psInst is a pointer to the AK8963 instance data. +//! \param pfMagnetoX is a pointer to the value into which the X-axis +//! magnetometer data is stored. +//! \param pfMagnetoY is a pointer to the value into which the Y-axis +//! magnetometer data is stored. +//! \param pfMagnetoZ is a pointer to the value into which the Z-axis +//! magnetometer data is stored. +//! +//! This function returns the magnetometer data from the most recent data read, +//! converted into tesla. If any of the output data pointers are \b NULL, the +//! corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +AK8963DataMagnetoGetFloat(tAK8963 *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ) +{ + float fFactor; + + // + // Get the conversion factor for the current data format. + // + fFactor = g_fAK8963Factors[psInst->ui8BitOutput]; + + // + // Convert the magnetometer values into floating-point tesla values. + // + if(pfMagnetoX) + { + *pfMagnetoX = ((float)(int16_t)((psInst->pui8Data[2] << 8) | + psInst->pui8Data[1]) * fFactor); + } + if(pfMagnetoY) + { + *pfMagnetoY = ((float)(int16_t)((psInst->pui8Data[4] << 8) | + psInst->pui8Data[3]) * fFactor); + } + if(pfMagnetoZ) + { + *pfMagnetoZ = ((float)(int16_t)((psInst->pui8Data[6] << 8) | + psInst->pui8Data[5]) * fFactor); + } +} + +//***************************************************************************** +// +//! Gets the status registers from the most recent data read. +//! +//! \param psInst is a pointer to the AK8963 instance data. +//! \param pui8Status1 is a pointer to the value into which the ST1 data is +//! stored. +//! \param pui8Status2 is a pointer to the value into which the ST2 data is +//! stored. +//! +//! This function returns the magnetometer status registers from the most +//! recent data read. If any of the output data pointers are \b NULL, the +//! corresponding data is not be provided. +//! +//! Note that the AKM comp routines require ST1 and ST2, so we read them for +//! that reason. +//! +//! \return None. +// +//***************************************************************************** +void +AK8963DataGetStatus(tAK8963 *psInst, uint_fast8_t *pui8Status1, + uint_fast8_t *pui8Status2) +{ + // + // Return the status registers + // + if(pui8Status1) + { + *pui8Status1 = psInst->pui8Data[0]; + } + if(pui8Status2) + { + *pui8Status2 = psInst->pui8Data[7]; + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/ak8963.h b/sensorlib/ak8963.h new file mode 100644 index 0000000..4be56dd --- /dev/null +++ b/sensorlib/ak8963.h @@ -0,0 +1,160 @@ +//***************************************************************************** +// +// ak8963.h - Prototypes for the AK8963 magnetometer driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_AK8963_H__ +#define __SENSORLIB_AK8963_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the AK8963 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the AK8963. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the AK8963. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the AK8963. + // + uint8_t ui8State; + + // + // The data output bit width. + // + uint8_t ui8BitOutput; + + // + // The new data output bit width, which is used when a register write + // succeeds. + // + uint8_t ui8NewBitOutput; + + // + // The data buffer used for sending/receiving data to/from the AK8963. + // + uint8_t pui8Data[8]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tAK8963; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t AK8963Init(tAK8963 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t AK8963Read(tAK8963 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t AK8963Write(tAK8963 *psInst, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t AK8963ReadModifyWrite(tAK8963 *psInst, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t AK8963DataRead(tAK8963 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void AK8963DataMagnetoGetRaw(tAK8963 *psInst, + uint_fast16_t *pui16MagnetoX, + uint_fast16_t *pui16MagnetoY, + uint_fast16_t *pui16MagnetoZ); +extern void AK8963DataMagnetoGetFloat(tAK8963 *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ); +extern void AK8963DataGetStatus(tAK8963 *psInst, uint_fast8_t *pui8Status1, + uint_fast8_t *pui8Status2); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_AK8963_H__ diff --git a/sensorlib/ak8975.c b/sensorlib/ak8975.c new file mode 100644 index 0000000..776229c --- /dev/null +++ b/sensorlib/ak8975.c @@ -0,0 +1,558 @@ +//***************************************************************************** +// +// ak8975.c - Driver for the AK8975 magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_ak8975.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/ak8975.h" + +//***************************************************************************** +// +//! \addtogroup ak8975_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the AK8975 state machine. +// +//***************************************************************************** +#define AK8975_STATE_IDLE 0 // State machine is idle +#define AK8975_STATE_READ 1 // Waiting for read +#define AK8975_STATE_WRITE 2 // Waiting for write +#define AK8975_STATE_RMW 3 // Waiting for read-modify-write + +//***************************************************************************** +// +// Converting sensor data to tesla (0.3 uT per LSB) +// +//***************************************************************************** +#define CONVERT_TO_TESLA 0.0000003 + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// AK8975 have completed. +// +//***************************************************************************** +static void +AK8975Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tAK8975 *psInst; + + // + // Convert the instance data into a pointer to a tAK8975 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = AK8975_STATE_IDLE; + } + + // + // Determine the current state of the AK8975 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case AK8975_STATE_READ: + case AK8975_STATE_WRITE: + case AK8975_STATE_RMW: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = AK8975_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == AK8975_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the AK8975 driver. +//! +//! \param psInst is a pointer to the AK8975 instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the AK8975 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the AK8975 driver, preparing it for operation. +//! +//! \return Returns 1 if the AK8975 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +AK8975Init(tAK8975 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Initialize the AK8975 instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = AK8975_STATE_IDLE; + + // + // The default settings are ok. Return success and call the callback. + // + if(pfnCallback) + { + pfnCallback(pvCallbackData, 0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from AK8975 registers. +//! +//! \param psInst is a pointer to the AK8975 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the AK8975. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +AK8975Read(tAK8975 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the AK8975 driver is not idle (in other words, there + // is already an outstanding request to the AK8975). + // + if(psInst->ui8State != AK8975_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = AK8975_STATE_READ; + + // + // Read the requested registers from the AK8975. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + AK8975Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = AK8975_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to AK8975 registers. +//! +//! \param psInst is a pointer to the AK8975 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the AK8975. The first byte of the \e pui8Data buffer contains the value to +//! be written into the \e ui8Reg register, the second value contains the data +//! to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +AK8975Write(tAK8975 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the AK8975 driver is not idle (in other words, there + // is already an outstanding request to the AK8975). + // + if(psInst->ui8State != AK8975_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = AK8975_STATE_WRITE; + + // + // Write the requested registers to the AK8975. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, AK8975Callback, + psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = AK8975_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of an AK8975 register. +//! +//! \param psInst is a pointer to the AK8975 instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the AK8975 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! AK8975. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +AK8975ReadModifyWrite(tAK8975 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the AK8975 driver is not idle (in other words, there + // is already an outstanding request to the AK8975). + // + if(psInst->ui8State != AK8975_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = AK8975_STATE_RMW; + + // + // Submit the read-modify-write request to the AK8975. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, AK8975Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = AK8975_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the magnetometer data from the AK8975. +//! +//! \param psInst is a pointer to the AK8975 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the AK8975 data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - AK8975DataMagnetoGetRaw() +//! - AK8975DataMagnetoGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +AK8975DataRead(tAK8975 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the AK8975 driver is not idle (in other words, there + // is already an outstanding request to the AK8975). + // + if(psInst->ui8State != AK8975_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = AK8975_STATE_READ; + + // + // Read the data registers from the AK8975. + // + // ST1 + (HXL + HXH) + (HYL + HYH) + (HZL + HZH) + ST2 = 8 bytes + // + psInst->pui8Data[0] = AK8975_O_ST1; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 1, + psInst->pui8Data, 8, AK8975Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = AK8975_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw magnetometer data from the most recent data read. +//! +//! \param psInst is a pointer to the AK8975 instance data. +//! \param pui16MagnetoX is a pointer to the value into which the raw X-axis +//! magnetometer data is stored. +//! \param pui16MagnetoY is a pointer to the value into which the raw Y-axis +//! magnetometer data is stored. +//! \param pui16MagnetoZ is a pointer to the value into which the raw Z-axis +//! magnetometer data is stored. +//! +//! This function returns the raw magnetometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +AK8975DataMagnetoGetRaw(tAK8975 *psInst, uint_fast16_t *pui16MagnetoX, + uint_fast16_t *pui16MagnetoY, + uint_fast16_t *pui16MagnetoZ) +{ + // + // Return the raw magnetometer values. + // + if(pui16MagnetoX) + { + *pui16MagnetoX = (psInst->pui8Data[2] << 8) | psInst->pui8Data[1]; + } + if(pui16MagnetoY) + { + *pui16MagnetoY = (psInst->pui8Data[4] << 8) | psInst->pui8Data[3]; + } + if(pui16MagnetoZ) + { + *pui16MagnetoZ = (psInst->pui8Data[6] << 8) | psInst->pui8Data[5]; + } +} + +//***************************************************************************** +// +//! Gets the magnetometer data from the most recent data read. +//! +//! \param psInst is a pointer to the AK8975 instance data. +//! \param pfMagnetoX is a pointer to the value into which the X-axis +//! magnetometer data is stored. +//! \param pfMagnetoY is a pointer to the value into which the Y-axis +//! magnetometer data is stored. +//! \param pfMagnetoZ is a pointer to the value into which the Z-axis +//! magnetometer data is stored. +//! +//! This function returns the magnetometer data from the most recent data read, +//! converted into tesla. If any of the output data pointers are +//! \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +AK8975DataMagnetoGetFloat(tAK8975 *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ) +{ + // + // Convert the magnetometer values into floating-point tesla values. + // + if(pfMagnetoX) + { + *pfMagnetoX = ((float)(int16_t)((psInst->pui8Data[2] << 8) | + psInst->pui8Data[1]) * + CONVERT_TO_TESLA); + } + if(pfMagnetoY) + { + *pfMagnetoY = ((float)(int16_t)((psInst->pui8Data[4] << 8) | + psInst->pui8Data[3]) * + CONVERT_TO_TESLA); + } + if(pfMagnetoZ) + { + *pfMagnetoZ = ((float)(int16_t)((psInst->pui8Data[6] << 8) | + psInst->pui8Data[5]) * + CONVERT_TO_TESLA); + } +} + +//***************************************************************************** +// +//! Gets the status registers from the most recent data read. +//! +//! \param psInst is a pointer to the AK8975 instance data. +//! \param pui8Status1 is a pointer to the value into which the ST1 data is +//! stored. +//! \param pui8Status2 is a pointer to the value into which the ST2 data is +//! stored. +//! +//! This function returns the magnetometer status registers from the most +//! recent data read. If any of the output data pointers are \b NULL, the +//! corresponding data is not provided. +//! +//! Note that the AKM comp routines require ST1 and ST2, so we read +//! them for that reason. +//! +//! \return None. +// +//***************************************************************************** +void +AK8975DataGetStatus(tAK8975 *psInst, uint_fast8_t *pui8Status1, + uint_fast8_t *pui8Status2) +{ + // + // Return the status registers + // + if(pui8Status1) + { + *pui8Status1 = psInst->pui8Data[0]; + } + if(pui8Status2) + { + *pui8Status2 = psInst->pui8Data[7]; + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/ak8975.h b/sensorlib/ak8975.h new file mode 100644 index 0000000..97c2893 --- /dev/null +++ b/sensorlib/ak8975.h @@ -0,0 +1,148 @@ +//***************************************************************************** +// +// ak8975.h - Prototypes for the AK8975 magnetometer driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_AK8975_H__ +#define __SENSORLIB_AK8975_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the AK8975 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the AK8975. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the AK8975. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the AK8975. + // + uint8_t ui8State; + + // + // The data buffer used for sending/receiving data to/from the AK8975. + // + uint8_t pui8Data[8]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tAK8975; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t AK8975Init(tAK8975 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t AK8975Read(tAK8975 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t AK8975Write(tAK8975 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t AK8975ReadModifyWrite(tAK8975 *psInst, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t AK8975DataRead(tAK8975 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void AK8975DataMagnetoGetRaw(tAK8975 *psInst, + uint_fast16_t *pui16MagnetoX, + uint_fast16_t *pui16MagnetoY, + uint_fast16_t *pui16MagnetoZ); +extern void AK8975DataMagnetoGetFloat(tAK8975 *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ); +extern void AK8975DataGetStatus(tAK8975 *psInst, uint_fast8_t *pui8Status1, + uint_fast8_t *pui8Status2); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_AK8975_H__ diff --git a/sensorlib/bmp180.c b/sensorlib/bmp180.c new file mode 100644 index 0000000..a25701e --- /dev/null +++ b/sensorlib/bmp180.c @@ -0,0 +1,919 @@ +//***************************************************************************** +// +// bmp180.c - Driver for the BMP180 pressure sensor. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include +#include "sensorlib/hw_bmp180.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/bmp180.h" + +//***************************************************************************** +// +//! \addtogroup bmp180_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the BMP180 state machine. +// +//***************************************************************************** +#define BMP180_STATE_IDLE 0 // State machine is idle +#define BMP180_STATE_INIT1 1 // Waiting for initialization 1 +#define BMP180_STATE_INIT2 2 // Waiting for initialization 2 +#define BMP180_STATE_READ 3 // Waiting for read +#define BMP180_STATE_WRITE 4 // Waiting for write +#define BMP180_STATE_RMW 5 // Waiting for read-modify-write +#define BMP180_STATE_REQ_TEMP 6 // Requested temperature +#define BMP180_STATE_WAIT_TEMP 7 // Waiting for temperature ready +#define BMP180_STATE_READ_TEMP 8 // Reading temperature value +#define BMP180_STATE_REQ_PRES 9 // Requested pressure +#define BMP180_STATE_WAIT_PRES 10 // Waiting for pressure ready +#define BMP180_STATE_READ_PRES 11 // Reading pressure value + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// BMP180 have completed. +// +//***************************************************************************** +static void +BMP180Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tBMP180 *psInst; + uint16_t ui16ReadVerify; + + // + // Convert the instance data into a pointer to a tBMP180 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = BMP180_STATE_IDLE; + } + + // + // Determine the current state of the BMP180 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case BMP180_STATE_READ: + case BMP180_STATE_READ_PRES: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = BMP180_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // The first step of initialization has just completed. + // + case BMP180_STATE_INIT1: + { + // + // Read the calibration data from the BMP180. + // + psInst->pui8Data[0] = BMP180_O_AC1_MSB; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 1, + psInst->uCommand.pui8Buffer, 22, BMP180Callback, psInst); + + // + // Move to the wait for initialization step 2 state. + // + psInst->ui8State = BMP180_STATE_INIT2; + + // + // Done. + // + break; + } + + // + // The second step of initialization has just completed. + // + case BMP180_STATE_INIT2: + { + // + // Data communication is checked by verifying that the calibration + // data is neither 0 nor 0xFFFF. This is used to check that reset + // is complete and the part is ready. It also verifies that we + // have valid calibration data before proceeding. + // + ui16ReadVerify = psInst->uCommand.pui8Buffer[0]; + ui16ReadVerify <<= 8; + ui16ReadVerify |= psInst->uCommand.pui8Buffer[1]; + if((ui16ReadVerify == 0) || (ui16ReadVerify == 0xFFFF)) + { + // + // Reread the calibration data from the BMP180. + // + psInst->pui8Data[0] = BMP180_O_AC1_MSB; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, + 1, psInst->uCommand.pui8Buffer, 22, BMP180Callback, + psInst); + } + else + { + // + // Extract the calibration data from the data that was read. + // + psInst->i16AC1 = + (int16_t)((psInst->uCommand.pui8Buffer[0] << 8) | + psInst->uCommand.pui8Buffer[1]); + psInst->i16AC2 = + (int16_t)((psInst->uCommand.pui8Buffer[2] << 8) | + psInst->uCommand.pui8Buffer[3]); + psInst->i16AC3 = + (int16_t)((psInst->uCommand.pui8Buffer[4] << 8) | + psInst->uCommand.pui8Buffer[5]); + psInst->ui16AC4 = + (uint16_t)((psInst->uCommand.pui8Buffer[6] << 8) | + psInst->uCommand.pui8Buffer[7]); + psInst->ui16AC5 = + (uint16_t)((psInst->uCommand.pui8Buffer[8] << 8) | + psInst->uCommand.pui8Buffer[9]); + psInst->ui16AC6 = + (uint16_t)((psInst->uCommand.pui8Buffer[10] << 8) | + psInst->uCommand.pui8Buffer[11]); + psInst->i16B1 = + (int16_t)((psInst->uCommand.pui8Buffer[12] << 8) | + psInst->uCommand.pui8Buffer[13]); + psInst->i16B2 = + (int16_t)((psInst->uCommand.pui8Buffer[14] << 8) | + psInst->uCommand.pui8Buffer[15]); + psInst->i16MC = + (int16_t)((psInst->uCommand.pui8Buffer[18] << 8) | + psInst->uCommand.pui8Buffer[19]); + psInst->i16MD = + (int16_t)((psInst->uCommand.pui8Buffer[20] << 8) | + psInst->uCommand.pui8Buffer[21]); + + // + // The state machine is now idle. + // + psInst->ui8State = BMP180_STATE_IDLE; + } + + // + // Done. + // + break; + } + + // + // A write has just completed. + // + case BMP180_STATE_WRITE: + { + // + // Set the mode to the new mode. If the register was not modified, + // the values will be the same so this has no effect. + // + psInst->ui8Mode = psInst->ui8NewMode; + + // + // The state machine is now idle. + // + psInst->ui8State = BMP180_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read-modify-write has just completed. + // + case BMP180_STATE_RMW: + { + // + // See if the CTRL_MEAS register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + BMP180_O_CTRL_MEAS) + { + // + // Extract the measurement mode from the CTRL_MEAS register + // value. + // + psInst->ui8Mode = + (psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + BMP180_CTRL_MEAS_OSS_M); + } + + // + // The state machine is now idle. + // + psInst->ui8State = BMP180_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // The temperature has been requested. + // + case BMP180_STATE_REQ_TEMP: + { + // + // Read the control register to see if the temperature reading is + // available. + // + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, + psInst->uCommand.pui8Buffer + 1, 1, BMP180Callback, + psInst); + + // + // Move to the wait for temperature state. + // + psInst->ui8State = BMP180_STATE_WAIT_TEMP; + + // + // Done. + // + break; + } + + // + // Waiting for the temperature reading to be available. + // + case BMP180_STATE_WAIT_TEMP: + { + // + // See if the temperature reading is available. + // + if(psInst->uCommand.pui8Buffer[1] & BMP180_CTRL_MEAS_SCO) + { + // + // The temperature reading is not ready yet, so read the + // control register again. + // + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, + psInst->uCommand.pui8Buffer + 1, 1, BMP180Callback, + psInst); + } + else + { + // + // The temperature reading is ready, so read it now. + // + psInst->uCommand.pui8Buffer[0] = BMP180_O_OUT_MSB; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 2, + BMP180Callback, psInst); + + // + // Move to the temperature reading state. + // + psInst->ui8State = BMP180_STATE_READ_TEMP; + } + + // + // Done. + // + break; + } + + // + // The temperature reading has been retrieved. + // + case BMP180_STATE_READ_TEMP: + { + // + // Request the pressure reading from the BMP180. + // + psInst->uCommand.pui8Buffer[0] = BMP180_O_CTRL_MEAS; + psInst->uCommand.pui8Buffer[1] = (BMP180_CTRL_MEAS_SCO | + BMP180_CTRL_MEAS_PRESSURE | + psInst->ui8Mode); + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, BMP180Callback, psInst); + + // + // Move to the pressure reading request state. + // + psInst->ui8State = BMP180_STATE_REQ_PRES; + + // + // Done. + // + break; + } + + // + // The pressure has been requested. + // + case BMP180_STATE_REQ_PRES: + { + // + // Read the control register to see if the pressure reading is + // available. + // + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, + psInst->uCommand.pui8Buffer + 1, 1, BMP180Callback, + psInst); + + // + // Move to the wait for pressure state. + // + psInst->ui8State = BMP180_STATE_WAIT_PRES; + + // + // Done. + // + break; + } + + // + // Waiting for the pressure reading to be available. + // + case BMP180_STATE_WAIT_PRES: + { + // + // See if the pressure reading is available. + // + if(psInst->uCommand.pui8Buffer[1] & BMP180_CTRL_MEAS_SCO) + { + // + // The pressure reading is not ready yet, so read the control + // register again. + // + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, + psInst->uCommand.pui8Buffer + 1, 1, BMP180Callback, + psInst); + } + else + { + // + // The pressure reading is ready, so read it now. + // + psInst->uCommand.pui8Buffer[0] = BMP180_O_OUT_MSB; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data + 2, + 3, BMP180Callback, psInst); + + // + // Move to the pressure reading state. + // + psInst->ui8State = BMP180_STATE_READ_PRES; + } + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == BMP180_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the BMP180 driver. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the BMP180 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the BMP180 driver, preparing it for operation. +//! +//! \return Returns 1 if the BMP180 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +BMP180Init(tBMP180 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Initialize the BMP180 instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = BMP180_STATE_INIT1; + psInst->ui8Mode = 0; + psInst->ui8NewMode = 0; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Perform a soft reset of the BMP180. + // + psInst->pui8Data[0] = BMP180_O_SOFT_RESET; + psInst->pui8Data[1] = BMP180_SOFT_RESET_VALUE; + if(I2CMWrite(psI2CInst, ui8I2CAddr, psInst->pui8Data, 2, BMP180Callback, + psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = BMP180_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from BMP180 registers. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the BMP180. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +BMP180Read(tBMP180 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the BMP180 driver is not idle (in other words, there + // is already an outstanding request to the BMP180). + // + if(psInst->ui8State != BMP180_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = BMP180_STATE_READ; + + // + // Read the requested registers from the BMP180. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + BMP180Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = BMP180_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to BMP180 registers. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the BMP180. The first byte of the \e pui8Data buffer contains the value to +//! be written into the \e ui8Reg register, the second value contains the data +//! to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +BMP180Write(tBMP180 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the BMP180 driver is not idle (in other words, there + // is already an outstanding request to the BMP180). + // + if(psInst->ui8State != BMP180_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the CTRL_MEAS register is being written. + // + if((ui8Reg <= BMP180_O_CTRL_MEAS) && + ((ui8Reg + ui16Count) > BMP180_O_CTRL_MEAS)) + { + // + // Extract the measurement mode from the CTRL_MEAS register value. + // + psInst->ui8NewMode = (pui8Data[ui8Reg - BMP180_O_CTRL_MEAS] & + BMP180_CTRL_MEAS_OSS_M); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = BMP180_STATE_WRITE; + + // + // Write the requested registers to the BMP180. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, BMP180Callback, + psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = BMP180_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a BMP180 register. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the BMP180 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! BMP180. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +BMP180ReadModifyWrite(tBMP180 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the BMP180 driver is not idle (in other words, there + // is already an outstanding request to the BMP180). + // + if(psInst->ui8State != BMP180_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = BMP180_STATE_RMW; + + // + // Submit the read-modify-write request to the BMP180. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, BMP180Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = BMP180_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the pressure data from the BMP180. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the BMP180 data registers. When the +//! read has completed (as indicated by calling the callback function), the +//! new temperature and pressure readings can be obtained via: +//! +//! - BMP180DataPressureGetRaw() +//! - BMP180DataPressureGetFloat() +//! - BMP180DataTemperatureGetRaw() +//! - BMP180DataTemperatureGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +BMP180DataRead(tBMP180 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the BMP180 driver is not idle (in other words, there + // is already an outstanding request to the BMP180). + // + if(psInst->ui8State != BMP180_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the temperature reading request state. + // + psInst->ui8State = BMP180_STATE_REQ_TEMP; + + // + // Request the temperature reading from the BMP180. + // + psInst->uCommand.pui8Buffer[0] = BMP180_O_CTRL_MEAS; + psInst->uCommand.pui8Buffer[1] = (BMP180_CTRL_MEAS_SCO | + BMP180_CTRL_MEAS_TEMPERATURE); + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, BMP180Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = BMP180_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw pressure data from the most recent data read. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param pui32Pressure is a pointer to the value into which the raw pressure +//! data is stored. +//! +//! This function returns the raw pressure data from the most recent data read. +//! The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BMP180DataPressureGetRaw(tBMP180 *psInst, uint_fast32_t *pui32Pressure) +{ + // + // Return the raw pressure value. + // + *pui32Pressure = ((psInst->pui8Data[2] << 16) | + (psInst->pui8Data[3] << 8) | + (psInst->pui8Data[4] & BMP180_OUT_XLSB_M)); +} + +//***************************************************************************** +// +//! Gets the pressure data from the most recent data read. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param pfPressure is a pointer to the value into which the pressure data is +//! stored. +//! +//! This function returns the pressure data from the most recent data read, +//! converted into pascals. +//! +//! \return None. +// +//***************************************************************************** +void +BMP180DataPressureGetFloat(tBMP180 *psInst, float *pfPressure) +{ + float fUT, fUP, fX1, fX2, fX3, fB3, fB4, fB5, fB6, fB7, fP; + int_fast8_t i8Oss; + + // + // Get the oversampling ratio. + // + i8Oss = psInst->ui8Mode >> BMP180_CTRL_MEAS_OSS_S; + + // + // Retrieve the uncompensated temperature and pressure. + // + fUT = (float)(uint16_t)((psInst->pui8Data[0] << 8) | + psInst->pui8Data[1]); + fUP = ((float)(int32_t)((psInst->pui8Data[2] << 16) | + (psInst->pui8Data[3] << 8) | + (psInst->pui8Data[4] & BMP180_OUT_XLSB_M)) / + (1 << (8 - i8Oss))); + + // + // Calculate the true temperature. + // + fX1 = ((fUT - (float)psInst->ui16AC6) * (float)psInst->ui16AC5) / 32768.f; + fX2 = ((float)psInst->i16MC * 2048.f) / (fX1 + (float)psInst->i16MD); + fB5 = fX1 + fX2; + + // + // Calculate the true pressure. + // + fB6 = fB5 - 4000; + fX1 = ((float)psInst->i16B2 * ((fB6 * fB6) / 4096)) / 2048; + fX2 = ((float)psInst->i16AC2 * fB6) / 2048; + fX3 = fX1 + fX2; + fB3 = ((((float)psInst->i16AC1 * 4) + fX3) * (1 << i8Oss)) / 4; + fX1 = ((float)psInst->i16AC3 * fB6) / 8192; + fX2 = ((float)psInst->i16B1 * ((fB6 * fB6) / 4096)) / 65536; + fX3 = (fX1 + fX2) / 4; + fB4 = (float)psInst->ui16AC4 * ((fX3 / 32768) + 1); + fB7 = (fUP - fB3) * (50000 >> i8Oss); + fP = (fB7 * 2) / fB4; + fX1 = (fP / 256) * (fP / 256); + fX1 = (fX1 * 3038) / 65536; + fX2 = (fP * -7357) / 65536; + fP += (fX1 + fX2 + 3791) / 16; + *pfPressure = fP; +} + +//***************************************************************************** +// +//! Gets the raw temperature data from the most recent data read. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param pui16Temperature is a pointer to the value into which the raw +//! temperature data is stored. +//! +//! This function returns the raw temperature data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BMP180DataTemperatureGetRaw(tBMP180 *psInst, uint_fast16_t *pui16Temperature) +{ + // + // Return the raw temperature value. + // + *pui16Temperature = (psInst->pui8Data[0] << 8) | psInst->pui8Data[1]; +} + +//***************************************************************************** +// +//! Gets the temperature data from the most recent data read. +//! +//! \param psInst is a pointer to the BMP180 instance data. +//! \param pfTemperature is a pointer to the value into which the temperature +//! data is stored. +//! +//! This function returns the temperature data from the most recent data read, +//! converted into Celsius. +//! +//! \return None. +// +//***************************************************************************** +void +BMP180DataTemperatureGetFloat(tBMP180 *psInst, float *pfTemperature) +{ + float fUT, fX1, fX2, fB5; + + // + // Get the uncompensated temperature. + // + fUT = (float)(uint16_t)((psInst->pui8Data[0] << 8) | + psInst->pui8Data[1]); + + // + // Calculate the true temperature. + // + fX1 = ((fUT - (float)psInst->ui16AC6) * (float)psInst->ui16AC5) / 32768.f; + fX2 = ((float)psInst->i16MC * 2048.f) / (fX1 + (float)psInst->i16MD); + fB5 = fX1 + fX2; + *pfTemperature = fB5 / 160.f; +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/bmp180.h b/sensorlib/bmp180.h new file mode 100644 index 0000000..c56b4df --- /dev/null +++ b/sensorlib/bmp180.h @@ -0,0 +1,207 @@ +//***************************************************************************** +// +// bmp180.h - Prototypes for the BMP180 pressure sensor driver. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_BMP180_H__ +#define __SENSORLIB_BMP180_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the BMP180 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the BMP180. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the BMP180. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the BMP180. + // + uint8_t ui8State; + + // + // The sampling mode to be used by the BMP180. + // + uint8_t ui8Mode; + + // + // The new sampling mode, which is used when a register write succeeds. + // + uint8_t ui8NewMode; + + // + // The AC1 calibration from the BMP180. + // + int16_t i16AC1; + + // + // The AC2 calibration from the BMP180. + // + int16_t i16AC2; + + // + // The AC3 calibration from the BMP180. + // + int16_t i16AC3; + + // + // The AC4 calibration from the BMP180. + // + uint16_t ui16AC4; + + // + // The AC5 calibration from the BMP180. + // + uint16_t ui16AC5; + + // + // The AC6 calibration from the BMP180. + // + uint16_t ui16AC6; + + // + // The B1 calibration from the BMP180. + // + int16_t i16B1; + + // + // The B2 calibration from the BMP180. + // + int16_t i16B2; + + // + // The MC calibration from the BMP180. + // + int16_t i16MC; + + // + // The MD calibration from the BMP180. + // + int16_t i16MD; + + // + // The data buffer used for sending/receiving data to/from the BMP180. + // + uint8_t pui8Data[5]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. This + // is also used to read back the calibration data from the device. + // + uint8_t pui8Buffer[22]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tBMP180; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t BMP180Init(tBMP180 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t BMP180Read(tBMP180 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t BMP180Write(tBMP180 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t BMP180ReadModifyWrite(tBMP180 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t BMP180DataRead(tBMP180 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void BMP180DataPressureGetRaw(tBMP180 *psInst, + uint_fast32_t *pui32Pressure); +extern void BMP180DataPressureGetFloat(tBMP180 *psInst, float *pfPressure); +extern void BMP180DataTemperatureGetRaw(tBMP180 *psInst, + uint_fast16_t *pui16Temperature); +extern void BMP180DataTemperatureGetFloat(tBMP180 *psInst, + float *pfTemperature); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_BMP180_H__ diff --git a/sensorlib/bq27510g3.c b/sensorlib/bq27510g3.c new file mode 100644 index 0000000..b9453b3 --- /dev/null +++ b/sensorlib/bq27510g3.c @@ -0,0 +1,1398 @@ +//***************************************************************************** +// +// bq27510g3.c - Driver for the TI BQ27510G3 Battery Fuel Gauge +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include +#include "sensorlib/hw_bq27510g3.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/bq27510g3.h" + +//***************************************************************************** +// +//! \addtogroup bq27510g3_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the BQ27510G3 state machine. +// +//***************************************************************************** +#define BQ27510G3_STATE_IDLE 0 +#define BQ27510G3_STATE_INIT 1 +#define BQ27510G3_STATE_READ 2 +#define BQ27510G3_STATE_WRITE 3 +#define BQ27510G3_STATE_RMW 4 +#define BQ27510G3_STATE_READ_DATA_1 5 +#define BQ27510G3_STATE_READ_DATA_2 6 +#define BQ27510G3_STATE_READ_DATA_3 7 + +//***************************************************************************** +// +// The constants used to calculate object temperature. +// +//***************************************************************************** +#define T_REF 273 + +//***************************************************************************** +// +// The callback function that is called when I2C transactions to/from the +// BQ27510G3 have completed. +// +//***************************************************************************** +static void +BQ27510G3Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tBQ27510G3 *psInst; + + // + // Convert the instance data into a pointer to a tBQ27510G3 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = BQ27510G3_STATE_IDLE; + } + + // + // Determine the current state of the BQ27510G3 state machine. + // + switch(psInst->ui8State) + { + // + // The first data read state, has finished setup and trigger data read + // state 2. + // + case BQ27510G3_STATE_READ_DATA_1: + { + // + // Move the state machine to the next read state. + // + psInst->ui8State = BQ27510G3_STATE_READ_DATA_2; + + // + // Read the requested data from the BQ27510G3. + // + psInst->uCommand.pui8Buffer[0] = BQ27510G3_O_NOM_AV_CAP_LSB; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data + 6, + 24, BQ27510G3Callback, psInst); + + // + // break + // + break; + } + + // + // The 2nd data read state, has finished setup and trigger data read + // state 3. Read state 3 is the final state and when done will return + // to idle and trigger the application level callback. + // + case BQ27510G3_STATE_READ_DATA_2: + { + // + // Move the state machine to the next read state. + // + psInst->ui8State = BQ27510G3_STATE_READ_DATA_3; + + // + // Read the requested data from the BQ27510G3. + // + psInst->uCommand.pui8Buffer[0] = BQ27510G3_O_INT_TEMP_LSB; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data + 30, + 2, BQ27510G3Callback, psInst); + + // + // break + // + break; + } + + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case BQ27510G3_STATE_INIT: + case BQ27510G3_STATE_READ: + case BQ27510G3_STATE_WRITE: + case BQ27510G3_STATE_READ_DATA_3: + case BQ27510G3_STATE_RMW: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = BQ27510G3_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == BQ27510G3_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the BQ27510G3 driver. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param psI2CInst is a pointer to the I2C driver instance data. +//! \param ui8I2CAddr is the I2C address of the BQ27510G3 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the BQ27510G3 driver, preparing it for operation. +//! +//! \return Returns 1 if the BQ27510G3 driver was successfully initialized and +//! 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +BQ27510G3Init(tBQ27510G3 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Initialize the BQ27510G3 instance structure + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = BQ27510G3_STATE_IDLE; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // The default settings are ok. Return success and call the callback. + // + if(pfnCallback) + { + pfnCallback(pvCallbackData, 0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from BQ27510G3 registers. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui16Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count the number of register values to read. +//! \param pfnCallback is the function to be called when data read is complete +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the BQ27510G3. +//! +//! \note The BQ27510G3 does not auto-increment the register pointer, so reads +//! of more than one value returns garbage for the subsequent values. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +BQ27510G3Read(tBQ27510G3 *psInst, uint_fast8_t ui8Reg, uint16_t *pui16Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the BQ27510G3 driver is not idle (in other words, + // there is already an outstanding request to the BQ27510G3). + // + if(psInst->ui8State != BQ27510G3_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = BQ27510G3_STATE_READ; + + // + // Read the requested registers from the BQ27510G3. + // + if(I2CMRead16BE(&(psInst->uCommand.sReadState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, + BQ27510G3Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = BQ27510G3_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to BQ27510G3 registers. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui16Data is a pointer to the 16-bit register data to write. +//! \param ui16Count is the number of 16-bit registers to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the BQ27510G3. The first value in the \e pui16Data buffer contains the +//! data to be written into the \e ui8Reg register, the second value contains +//! the data to be written into the next register, and so on. +//! +//! \note The BQ27510G3 does not auto-increment the register pointer, so writes +//! of more than one register are rejected by the BQ27510G3. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +BQ27510G3Write(tBQ27510G3 *psInst, uint_fast8_t ui8Reg, + const uint16_t *pui16Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the BQ27510G3 driver is not idle (in other words, + // there is already an outstanding request to the BQ27510G3). + // + if(psInst->ui8State != BQ27510G3_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = BQ27510G3_STATE_WRITE; + + // + // Write the requested registers to the BQ27510G3. + // + if(I2CMWrite16BE(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, + BQ27510G3Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = BQ27510G3_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a BQ27510G3 register. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param ui8Reg is the register offset to read modify and write +//! \param ui16Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui16Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the BQ27510G3 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui16Mask, ORed with \e ui16Value, and then written back to the +//! BQ27510G3. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +BQ27510G3ReadModifyWrite(tBQ27510G3 *psInst, uint_fast8_t ui8Reg, + uint_fast16_t ui16Mask, uint_fast16_t ui16Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the BQ27510G3 driver is not idle (in other words, + // there is already an outstanding request to the BQ27510G3). + // + if(psInst->ui8State != BQ27510G3_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = BQ27510G3_STATE_RMW; + + // + // Submit the read-modify-write request to the BQ27510G3. + // + if(I2CMReadModifyWrite16BE(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui16Mask, ui16Value, BQ27510G3Callback, + psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = BQ27510G3_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read of a BQ27510G3 data register. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the BQ27510G3 data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via functions like: +//! +//! - BQ27510G3DataTCurrentInstantaneousGetRaw() +//! - BQ27510G3DataTCurrentInstantaneousGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +BQ27510G3DataRead(tBQ27510G3 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the BQ27510G3 driver is not idle (in other words, + // there is already an outstanding request to the BQ27510G3). + // + if(psInst->ui8State != BQ27510G3_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the first read state. Reads are done in three + // parts based on address ranges of the information being read. + // + psInst->ui8State = BQ27510G3_STATE_READ_DATA_1; + + // + // Read the requested data from the BQ27510G3. + // + psInst->uCommand.pui8Buffer[0] = BQ27510G3_O_AT_RATE_TTE_LSB; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 6, + BQ27510G3Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = BQ27510G3_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw "at rate time to empty" data. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataAtRateTimeToEmptyGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[1] << 8) | psInst->pui8Data[0]; +} + +//***************************************************************************** +// +//! Gets the "at rate time to empty" data as a floating point value. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are minutes. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataAtRateTimeToEmptyGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataAtRateTimeToEmptyGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + +} + +//***************************************************************************** +// +//! Gets the raw battery temperature from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataTemperatureBatteryGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[3] << 8) | psInst->pui8Data[2]; +} + +//***************************************************************************** +// +//! Gets the battery temperature measurement data from the most recent data +//! read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are degrees Celsius. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataTemperatureBatteryGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataTemperatureBatteryGetRaw(psInst, &i16Data); + + // + // Device returns the units as 0.1 degrees K. Convert first to whole + // degrees then from K to C + // + *pfData = (float)(i16Data); + *pfData = *pfData / 10.0f; + *pfData -= 272.15f; + + +} + +//***************************************************************************** +// +//! Gets the raw battery voltage measurement data from the most recent data +//! read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataVoltageBatteryGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[5] << 8) | psInst->pui8Data[4]; +} + +//***************************************************************************** +// +//! Gets the battery voltage measurement from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are volts. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataVoltageBatteryGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataVoltageBatteryGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + *pfData = *pfData / 1000.0f; + +} + +//***************************************************************************** +// +//! Gets the raw nominal available capacity measurement from the most recent +//! data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCapacityNominalAvailableGetRaw(tBQ27510G3 *psInst, + int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[7] << 8) | psInst->pui8Data[6]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are amp-hours (Ah). +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCapacityNominalAvailableGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataCapacityNominalAvailableGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + *pfData = *pfData / 1000.0f; + +} + +//***************************************************************************** +// +//! Gets the raw available capacity of a new battery from the most recent data +//! read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCapacityFullAvailableGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[9] << 8) | psInst->pui8Data[8]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are amp-hours (Ah). +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCapacityFullAvailableGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataCapacityFullAvailableGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + *pfData = *pfData / 1000.0f; + +} + +//***************************************************************************** +// +//! Gets the raw remaining capacity of measurement from the most recent data +//! read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCapacityRemainingGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[11] << 8) | psInst->pui8Data[10]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are amp-hours (Ah). +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCapacityRemainingGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataCapacityRemainingGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + *pfData = *pfData / 1000.0f; + +} + +//***************************************************************************** +// +//! Gets the raw full charge capacity from the most recent data +//! read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCapacityFullChargeGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[13] << 8) | psInst->pui8Data[12]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are amp-hours (Ah). +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCapacityFullChargeGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataCapacityFullChargeGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + *pfData = *pfData / 1000.0f; + +} + + +//***************************************************************************** +// +//! Gets the raw average current measurement from the most recent data +//! read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCurrentAverageGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[15] << 8) | psInst->pui8Data[14]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are amps. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCurrentAverageGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataCurrentAverageGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + *pfData = *pfData / 1000.0f; + +} + + +//***************************************************************************** +// +//! Gets the raw time to empty estimate from the most recent data +//! read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataTimeToEmptyGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[17] << 8) | psInst->pui8Data[16]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are minutes. Value of 65,535 indicates +//! battery is not being discharged. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataTimeToEmptyGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataTimeToEmptyGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + +} + +//***************************************************************************** +// +//! Gets the raw standby current from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCurrentStandbyGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[19] << 8) | psInst->pui8Data[18]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are amps. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCurrentStandbyGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataCurrentStandbyGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + *pfData = *pfData / 1000.0f; + +} + +//***************************************************************************** +// +//! Gets the raw standby time to empty data from the most recent data +//! read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataTimeToEmptyStandbyGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[21] << 8) | psInst->pui8Data[20]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, +//! converted into float value. Units are minutes. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataTimeToEmptyStandbyGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataTimeToEmptyStandbyGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + +} + +//***************************************************************************** +// +//! Gets the raw cycle count data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCycleCountGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[25] << 8) | psInst->pui8Data[24]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the data from the most recent data read, converted +//! into float value. This data does not have units. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCycleCountGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataCycleCountGetRaw(psInst, &i16Data); + + // + // Covert to float. + // + *pfData = (float)(i16Data); + +} + +//***************************************************************************** +// +//! Gets the raw health data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataHealthGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[23] << 8) | psInst->pui8Data[22]; +} + +//***************************************************************************** +// +//! Gets the health data from the most recent health data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfHealth is a pointer to the value into which the battery +//! health data is stored as floating point ratio of current/design capacity. +//! +//! This function returns the health data from the most recent data read, +//! converted into percent health. The health status bits are dropped. These +//! can be obtained with BQ27510G3DataHealthGetRaw function. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataHealthGetFloat(tBQ27510G3 *psInst, float *pfHealth) +{ + int16_t i16Health; + + // + // Get the raw readings. + // + BQ27510G3DataHealthGetRaw(psInst, &i16Health); + + // + // Mask off health bit field + // + *pfHealth = (float)(i16Health & 0xFF); + +} + +//***************************************************************************** +// +//! Gets the raw charge state data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataChargeStateGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[27] << 8) | psInst->pui8Data[26]; +} + +//***************************************************************************** +// +//! Gets the charge state from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the charge state from the most recent data read, +//! converted into percent charged. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataChargeStateGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataChargeStateGetRaw(psInst, &i16Data); + + // + // Convert to floating point. + // + *pfData = (float)(i16Data); + +} + +//***************************************************************************** +// +//! Gets the instantaneous current data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCurrentInstantaneousGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[29] << 8) | psInst->pui8Data[28]; +} + +//***************************************************************************** +// +//! Gets the instantaneous current data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the current measurement from the most recent data +//! read, converted into floating point amps. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataCurrentInstantaneousGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataCurrentInstantaneousGetRaw(psInst, &i16Data); + + // + // Convert to floating point. + // + *pfData = (float)(i16Data); + *pfData /= 1000.0f; + +} + +//***************************************************************************** +// +//! Gets the raw internal temparature data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pi16Data is a pointer to the value into which the raw data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataTemperatureInternalGetRaw(tBQ27510G3 *psInst, int16_t *pi16Data) +{ + // + // Return the raw data value. + // + *pi16Data = ((int16_t)psInst->pui8Data[31] << 8) | psInst->pui8Data[30]; +} + +//***************************************************************************** +// +//! Gets the internal temperature data from the most recent data read. +//! +//! \param psInst is a pointer to the BQ27510G3 instance data. +//! \param pfData is a pointer to the value into which the data is stored as +//! floating point. +//! +//! This function returns the internal temperature from the most recent data +//! read. +//! +//! \return None. +// +//***************************************************************************** +void +BQ27510G3DataTemperatureInternalGetFloat(tBQ27510G3 *psInst, float *pfData) +{ + int16_t i16Data; + + // + // Get the raw readings. + // + BQ27510G3DataTemperatureInternalGetRaw(psInst, &i16Data); + + // + // Convert to floating point Kelvin, then Celsius. + // + *pfData = (float)(i16Data); + *pfData = *pfData / 10.0f; + *pfData -= 272.15f; + + + +} +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/bq27510g3.h b/sensorlib/bq27510g3.h new file mode 100644 index 0000000..928da94 --- /dev/null +++ b/sensorlib/bq27510g3.h @@ -0,0 +1,210 @@ +//***************************************************************************** +// +// bq27510g3.c - Prototypes for the TI BQ27510G3 Battery Fuel Guage +// driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_BQ27510G3_H__ +#define __SENSORLIB_BQ27510G3_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the BQ27510G3 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the BQ27510G3. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the BQ27510G3. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the BQ27510G3. + // + uint8_t ui8State; + + // + // The data buffer used for sending/receiving data to/from the BQ27510G3. + // + uint8_t pui8Data[32]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[4]; + + // + // The read state used to read register values. + // + tI2CMRead16BE sReadState; + + // + // The write state used to write register values. + // + tI2CMWrite16BE sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite16 sReadModifyWriteState; + } + uCommand; +} +tBQ27510G3; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t BQ27510G3Init(tBQ27510G3 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t BQ27510G3Read(tBQ27510G3 *psInst, uint_fast8_t ui8Reg, + uint16_t *pui16Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t BQ27510G3Write(tBQ27510G3 *psInst, uint_fast8_t ui8Reg, + const uint16_t *pui16Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t BQ27510G3ReadModifyWrite(tBQ27510G3 *psInst, + uint_fast8_t ui8Reg, + uint_fast16_t ui16Mask, + uint_fast16_t ui16Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t BQ27510G3DataRead(tBQ27510G3 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); + +extern void BQ27510G3DataAtRateTimeToEmptyGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataAtRateTimeToEmptyGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataTemperatureBatteryGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataTemperatureBatteryGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataVoltageBatteryGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataVoltageBatteryGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataCapacityNominalAvailableGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataCapacityNominalAvailalbeGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataCapacityFullAvailableGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataCapacityFullAvailableGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataCapacityRemainingGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataCapacityRemainingGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataCapacityFullChargeGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataCapacityFullChargeGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataCurrentAverageGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataCurrentAverageGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataTimeToEmptyGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataTimeToEmptyGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataCurrentStandbyGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataCurrentStandbyGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataTimeToEmptyStandbyGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataTimeToEmptyStandbyGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataCycleCountGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataCycleCountGetFloat(tBQ27510G3 *psInst, float *pfData); +extern void BQ27510G3DataHealthGetRaw(tBQ27510G3 *psInst, int16_t *pui16Data); +extern void BQ27510G3DataHealthGetFloat(tBQ27510G3 *psInst, float *pfData); +extern void BQ27510G3DataChargeStateGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataChargeStateGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataCurrentInstantaneousGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataCurrentInstantaneousGetFloat(tBQ27510G3 *psInst, + float *pfData); +extern void BQ27510G3DataTemperatureInternalGetRaw(tBQ27510G3 *psInst, + int16_t *pui16Data); +extern void BQ27510G3DataTemperatureInternalGetFloat(tBQ27510G3 *psInst, + float *pfData); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_BQ27510G3_H__ + diff --git a/sensorlib/ccs/.ccsproject b/sensorlib/ccs/.ccsproject new file mode 100644 index 0000000..b4eaafa --- /dev/null +++ b/sensorlib/ccs/.ccsproject @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sensorlib/ccs/.cproject b/sensorlib/ccs/.cproject new file mode 100644 index 0000000..10acdbf --- /dev/null +++ b/sensorlib/ccs/.cproject @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sensorlib/ccs/.project b/sensorlib/ccs/.project new file mode 100644 index 0000000..250724d --- /dev/null +++ b/sensorlib/ccs/.project @@ -0,0 +1,140 @@ + + + sensorlib + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + com.ti.ccstudio.core.ccsNature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + ak8963.c + 1 + SW_ROOT/sensorlib/ak8963.c + + + ak8975.c + 1 + SW_ROOT/sensorlib/ak8975.c + + + bmp180.c + 1 + SW_ROOT/sensorlib/bmp180.c + + + bq27510g3.c + 1 + SW_ROOT/sensorlib/bq27510g3.c + + + cm3218.c + 1 + SW_ROOT/sensorlib/cm3218.c + + + comp_dcm.c + 1 + SW_ROOT/sensorlib/comp_dcm.c + + + i2cm_drv.c + 1 + SW_ROOT/sensorlib/i2cm_drv.c + + + isl29023.c + 1 + SW_ROOT/sensorlib/isl29023.c + + + kxti9.c + 1 + SW_ROOT/sensorlib/kxti9.c + + + l3gd20h.c + 1 + SW_ROOT/sensorlib/l3gd20h.c + + + lsm303d.c + 1 + SW_ROOT/sensorlib/lsm303d.c + + + lsm303dlhc_accel.c + 1 + SW_ROOT/sensorlib/lsm303dlhc_accel.c + + + lsm303dlhc_mag.c + 1 + SW_ROOT/sensorlib/lsm303dlhc_mag.c + + + magneto.c + 1 + SW_ROOT/sensorlib/magneto.c + + + mpu6050.c + 1 + SW_ROOT/sensorlib/mpu6050.c + + + mpu9150.c + 1 + SW_ROOT/sensorlib/mpu9150.c + + + quaternion.c + 1 + SW_ROOT/sensorlib/quaternion.c + + + sht21.c + 1 + SW_ROOT/sensorlib/sht21.c + + + tmp006.c + 1 + SW_ROOT/sensorlib/tmp006.c + + + tmp100.c + 1 + SW_ROOT/sensorlib/tmp100.c + + + vector.c + 1 + SW_ROOT/sensorlib/vector.c + + + + + SW_ROOT + $%7BPARENT-2-PROJECT_LOC%7D + + + diff --git a/sensorlib/ccs/.settings/org.eclipse.cdt.codan.core.prefs b/sensorlib/ccs/.settings/org.eclipse.cdt.codan.core.prefs new file mode 100644 index 0000000..98b6350 --- /dev/null +++ b/sensorlib/ccs/.settings/org.eclipse.cdt.codan.core.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +inEditor=false +onBuild=false diff --git a/sensorlib/ccs/Debug/sensorlib.lib b/sensorlib/ccs/Debug/sensorlib.lib new file mode 100644 index 0000000..953d9c6 Binary files /dev/null and b/sensorlib/ccs/Debug/sensorlib.lib differ diff --git a/sensorlib/ccs/macros.ini_initial b/sensorlib/ccs/macros.ini_initial new file mode 100644 index 0000000..08b716d --- /dev/null +++ b/sensorlib/ccs/macros.ini_initial @@ -0,0 +1 @@ +SW_ROOT = ../.. diff --git a/sensorlib/cm3218.c b/sensorlib/cm3218.c new file mode 100644 index 0000000..bb2251f --- /dev/null +++ b/sensorlib/cm3218.c @@ -0,0 +1,468 @@ +//***************************************************************************** +// +// cm3218.c - Driver for the CM3218 light sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include +#include "sensorlib/hw_cm3218.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/cm3218.h" + +//***************************************************************************** +// +//! \addtogroup cm3218_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the CM3218 state machine. +// +//***************************************************************************** +#define CM3218_STATE_IDLE 0 +#define CM3218_STATE_INIT 1 +#define CM3218_STATE_READ 2 +#define CM3218_STATE_WRITE 3 + +//***************************************************************************** +// +// Sensitivity setting to floating point range value lookup table. +// +//***************************************************************************** +const float g_pfSensitivityLookup[4] = +{ + 0.02857, + 0.01328, + 0.00714, + 0.003571 +}; + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the CM3218 +// have completed. +// +//***************************************************************************** +static void +CM3218Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tCM3218 *psInst; + + // + // Convert the instance data into a pointer to a tCM3218 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = CM3218_STATE_IDLE; + } + + // + // Determine the current state of the CM3218 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case CM3218_STATE_INIT: + case CM3218_STATE_READ: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = CM3218_STATE_IDLE; + break; + } + + // + // A write has just completed. + // + case CM3218_STATE_WRITE: + { + // + // Set the integration time to the new integration time. If the + // register was not modified, the values will be the same so this + // has no effect. + // + psInst->ui8IntTime = psInst->ui8NewIntTime; + + // + // The state machine is now idle. + // + psInst->ui8State = CM3218_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == CM3218_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the CM3218 driver. +//! +//! \param psInst is a pointer to the CM3218 instance data. +//! \param psI2CInst is a pointer to the I2C driver instance data. +//! \param ui8I2CAddr is the I2C address of the CM3218 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the CM3218 driver, preparing it for operation. +//! +//! \return Returns 1 if the CM3218 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +CM3218Init(tCM3218 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Initialize the CM3218 instance structure + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = CM3218_STATE_IDLE; + psInst->ui8IntTime = CM3218_CMD_CONFIG_IT_10 >> CM3218_CMD_CONFIG_IT_S; + psInst->ui8NewIntTime = CM3218_CMD_CONFIG_IT_10 >> CM3218_CMD_CONFIG_IT_S; + + // + // The default settings are ok. Call the callback function if provided. + // + if(pfnCallback) + { + pfnCallback(pvCallbackData, 0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from CM3218 registers. +//! +//! \param psInst is a pointer to the CM3218 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui16Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count the number of register values bytes to read. +//! \param pfnCallback is the function to be called when data read is complete +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the CM3218. +//! +//! \note The CM3218 does not auto-increment the register pointer, so reads of +//! more than one value returns the same data. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +CM3218Read(tCM3218 *psInst, uint_fast8_t ui8Reg, uint16_t *pui16Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the CM3218 driver is not idle (in other words, there + // is already an outstanding request to the CM3218). + // + if(psInst->ui8State != CM3218_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = CM3218_STATE_READ; + + // + // Read the requested registers from the CM3218. + // + if(I2CMRead16BE(&(psInst->uCommand.sReadState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, + CM3218Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = CM3218_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to CM3218 registers. +//! +//! \param psInst is a pointer to the CM3218 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui16Data is a pointer to the 16-bit register data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the CM3218. The first value in the \e pui16Data buffer contains the data +//! to be written into the \e ui8Reg register, the second value contains the +//! data to be written into the next register, and so on. +//! +//! \note The CM3218 does not auto-increment the register pointer, so writes of +//! more than one register are rejected by the CM3218. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +CM3218Write(tCM3218 *psInst, uint_fast8_t ui8Reg, const uint16_t *pui16Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the CM3218 driver is not idle (in other words, there + // is already an outstanding request to the CM3218). + // + if(psInst->ui8State != CM3218_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the CMD_CONFIG register is being written. + // + if((ui8Reg <= CM3218_CMD_CONFIG) && + ((ui8Reg + ui16Count) > CM3218_CMD_CONFIG)) + { + // + // Extract the integration time from the CMD_CONFIG register value. + // + psInst->ui8NewIntTime = ((pui16Data[ui8Reg - CM3218_CMD_CONFIG] & + CM3218_CMD_CONFIG_IT_M) >> + CM3218_CMD_CONFIG_IT_S); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = CM3218_STATE_WRITE; + + // + // Write the requested registers to the CM3218. + // + if(I2CMWrite16BE(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, + CM3218Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = CM3218_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the light data from the CM3218. +//! +//! \param psInst is a pointer to the CM3218 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the CM3218 data registers. When the read +//! has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - CM3218DataLightVisibleGetRaw() +//! - CM3218DataLightVisibleGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +CM3218DataRead(tCM3218 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the CM3218 driver is not idle (in other words, there + // is already an outstanding request to the CM3218). + // + if(psInst->ui8State != CM3218_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read + // + psInst->ui8State = CM3218_STATE_READ; + + // + // Read the ambient light data from the CM3218. + // + psInst->uCommand.pui8Buffer[0] = CM3218_CMD_ALS_DATA; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 2, + CM3218Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = CM3218_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the CM3218 instance data. +//! \param pui16Visible is a pointer to the value into which the raw visible +//! light data is stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +CM3218DataLightVisibleGetRaw(tCM3218 *psInst, uint16_t *pui16Visible) +{ + // + // Return the raw Light value. + // + *pui16Visible = (psInst->pui8Data[1] << 8) | psInst->pui8Data[0]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the CM3218 instance data. +//! \param pfVisibleLight is a pointer to the value into which the light +//! data is stored as floating point lux. +//! +//! This function returns the light data from the most recent data read, +//! converted into lux. +//! +//! \return None. +// +//***************************************************************************** +void +CM3218DataLightVisibleGetFloat(tCM3218 *psInst, float *pfVisibleLight) +{ + uint16_t ui16Light; + float fSensitivity; + + // + // Get the raw light data from the instance structure + // + CM3218DataLightVisibleGetRaw(psInst, &ui16Light); + + // + // Get the floating point values for sensitivity + // + fSensitivity = g_pfSensitivityLookup[psInst->ui8IntTime]; + + // + // Calculate light reading in lux. + // + *pfVisibleLight = ((float)ui16Light) * fSensitivity; +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/cm3218.h b/sensorlib/cm3218.h new file mode 100644 index 0000000..fad9f11 --- /dev/null +++ b/sensorlib/cm3218.h @@ -0,0 +1,149 @@ +//***************************************************************************** +// +// CM3218.h - Prototypes for the CM3218 light sensor +// driver. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_CM3218_H__ +#define __SENSORLIB_CM3218_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the CM3218 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the CM3218. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the CM3218. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the CM3218. + // + uint8_t ui8State; + + // + // The data buffer used for sending/receiving data to/from the CM3218. + // + uint8_t pui8Data[4]; + + // + // The integration time, which determines the sensitivity. + // + uint8_t ui8IntTime; + + // + // The new integration time, which is used when a register write succeeds. + // + uint8_t ui8NewIntTime; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read and write operations. + // Since only one operation can be active at a time, it is safe to re-use + // the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[4]; + + // + // The read state used to read register values. + // + tI2CMRead16BE sReadState; + + // + // The write state used to write register values. + // + tI2CMWrite16BE sWriteState; + } + uCommand; +} +tCM3218; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t CM3218Init(tCM3218 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t CM3218Read(tCM3218 *psInst, uint_fast8_t ui8Reg, + uint16_t *pui16Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t CM3218Write(tCM3218 *psInst, uint_fast8_t ui8Reg, + const uint16_t *pui16Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t CM3218DataRead(tCM3218 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void CM3218DataLightVisibleGetRaw(tCM3218 *psInst, + uint16_t *pui16Visible); +extern void CM3218DataLightVisibleGetFloat(tCM3218 *psInst, float *pfVisible); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_CM3218_H__ diff --git a/sensorlib/comp_dcm.c b/sensorlib/comp_dcm.c new file mode 100644 index 0000000..42db71d --- /dev/null +++ b/sensorlib/comp_dcm.c @@ -0,0 +1,634 @@ +//***************************************************************************** +// +// comp_dcm.c - Complementary filter algorithm on a Direction Cosine Matrix for +// fusing sensor data from an accelerometer, gyroscope, and +// magnetometer. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include +#include +#include "driverlib/debug.h" +#include "sensorlib/comp_dcm.h" +#include "sensorlib/vector.h" + +//***************************************************************************** +// +//! \addtogroup comp_dcm_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// If M_PI has not been defined by the system headers, define it here. +// +//***************************************************************************** +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//***************************************************************************** +// +//! Initializes the complementary filter DCM attitude estimation state. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! \param fDeltaT is the amount of time between DCM updates, in seconds. +//! \param fScaleA is the weight of the accelerometer reading in determining +//! the updated attitude estimation. +//! \param fScaleG is the weight of the gyroscope reading in determining the +//! updated attitude estimation. +//! \param fScaleM is the weight of the magnetometer reading in determining the +//! updated attitude estimation. +//! +//! This function initializes the complementary filter DCM attitude estimation +//! state, and must be called prior to performing any attitude estimation. +//! +//! New readings must be supplied to the complementary filter DCM attitude +//! estimation algorithm at the rate specified by the \e fDeltaT parameter. +//! Failure to provide new readings at this rate results in inaccuracies in the +//! attitude estimation. +//! +//! The \e fScaleA, \e fScaleG, and \e fScaleM weights must sum to one. +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMInit(tCompDCM *psDCM, float fDeltaT, float fScaleA, float fScaleG, + float fScaleM) +{ + // + // Initialize the DCM matrix to the identity matrix. + // + psDCM->ppfDCM[0][0] = 1.0; + psDCM->ppfDCM[0][1] = 0.0; + psDCM->ppfDCM[0][2] = 0.0; + psDCM->ppfDCM[1][0] = 0.0; + psDCM->ppfDCM[1][1] = 1.0; + psDCM->ppfDCM[1][2] = 0.0; + psDCM->ppfDCM[2][0] = 0.0; + psDCM->ppfDCM[2][1] = 0.0; + psDCM->ppfDCM[2][2] = 1.0; + + // + // Save the time delta between DCM updates. + // + psDCM->fDeltaT = fDeltaT; + + // + // Save the scaling factors that are applied to the accelerometer, + // gyroscope, and magnetometer readings. + // + psDCM->fScaleA = fScaleA; + psDCM->fScaleG = fScaleG; + psDCM->fScaleM = fScaleM; +} + +//***************************************************************************** +// +//! Updates the accelerometer reading used by the complementary filter DCM +//! algorithm. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! \param fAccelX is the accelerometer reading in the X body axis. +//! \param fAccelY is the accelerometer reading in the Y body axis. +//! \param fAccelZ is the accelerometer reading in the Z body axis. +//! +//! This function updates the accelerometer reading used by the complementary +//! filter DCM algorithm. The accelerometer readings provided to this function +//! are used by subsequent calls to CompDCMStart() and CompDCMUpdate() to +//! compute the attitude estimate. +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMAccelUpdate(tCompDCM *psDCM, float fAccelX, float fAccelY, + float fAccelZ) +{ + // + // The user should never pass in values that are not-a-number + // + ASSERT(!isnan(fAccelX)); + ASSERT(!isnan(fAccelY)); + ASSERT(!isnan(fAccelZ)); + + // + // Save the new accelerometer reading. + // + psDCM->pfAccel[0] = fAccelX; + psDCM->pfAccel[1] = fAccelY; + psDCM->pfAccel[2] = fAccelZ; +} + +//***************************************************************************** +// +//! Updates the gyroscope reading used by the complementary filter DCM +//! algorithm. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! \param fGyroX is the gyroscope reading in the X body axis. +//! \param fGyroY is the gyroscope reading in the Y body axis. +//! \param fGyroZ is the gyroscope reading in the Z body axis. +//! +//! This function updates the gyroscope reading used by the complementary +//! filter DCM algorithm. The gyroscope readings provided to this function are +//! used by subsequent calls to CompDCMUpdate() to compute the attitude +//! estimate. +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMGyroUpdate(tCompDCM *psDCM, float fGyroX, float fGyroY, float fGyroZ) +{ + // + // The user should never pass in values that are not-a-number + // + ASSERT(!isnan(fGyroX)); + ASSERT(!isnan(fGyroY)); + ASSERT(!isnan(fGyroZ)); + + // + // Save the new gyroscope reading. + // + psDCM->pfGyro[0] = fGyroX; + psDCM->pfGyro[1] = fGyroY; + psDCM->pfGyro[2] = fGyroZ; +} + +//***************************************************************************** +// +//! Updates the magnetometer reading used by the complementary filter DCM +//! algorithm. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! \param fMagnetoX is the magnetometer reading in the X body axis. +//! \param fMagnetoY is the magnetometer reading in the Y body axis. +//! \param fMagnetoZ is the magnetometer reading in the Z body axis. +//! +//! This function updates the magnetometer reading used by the complementary +//! filter DCM algorithm. The magnetometer readings provided to this function +//! are used by subsequent calls to CompDCMStart() and CompDCMUpdate() to +//! compute the attitude estimate. +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMMagnetoUpdate(tCompDCM *psDCM, float fMagnetoX, float fMagnetoY, + float fMagnetoZ) +{ + // + // The user should never pass in values that are not-a-number + // + ASSERT(!isnan(fMagnetoX)); + ASSERT(!isnan(fMagnetoY)); + ASSERT(!isnan(fMagnetoZ)); + + // + // Save the new magnetometer reading. + // + psDCM->pfMagneto[0] = fMagnetoX; + psDCM->pfMagneto[1] = fMagnetoY; + psDCM->pfMagneto[2] = fMagnetoZ; +} + +//***************************************************************************** +// +//! Starts the complementary filter DCM attitude estimation from an initial +//! sensor reading. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! +//! This function computes the initial complementary filter DCM attitude +//! estimation state based on the initial accelerometer and magnetometer +//! reading. While not necessary for the attitude estimation to converge, +//! using an initial state based on sensor readings results in quicker +//! convergence. +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMStart(tCompDCM *psDCM) +{ + float pfI[3], pfJ[3], pfK[3]; + + // + // The magnetometer reading forms the initial I vector, pointing north. + // + pfI[0] = psDCM->pfMagneto[0]; + pfI[1] = psDCM->pfMagneto[1]; + pfI[2] = psDCM->pfMagneto[2]; + + // + // The accelerometer reading forms the initial K vector, pointing down. + // + pfK[0] = psDCM->pfAccel[0]; + pfK[1] = psDCM->pfAccel[1]; + pfK[2] = psDCM->pfAccel[2]; + + // + // Compute the initial J vector, which is the cross product of the K and I + // vectors. + // + VectorCrossProduct(pfJ, pfK, pfI); + + // + // Recompute the I vector from the cross product of the J and K vectors. + // This makes it fully orthogonal, which it wasn't before since magnetic + // north points inside the Earth in many places. + // + VectorCrossProduct(pfI, pfJ, pfK); + + // + // Normalize the I, J, and K vectors. + // + VectorScale(pfI, pfI, 1 / sqrtf(VectorDotProduct(pfI, pfI))); + VectorScale(pfJ, pfJ, 1 / sqrtf(VectorDotProduct(pfJ, pfJ))); + VectorScale(pfK, pfK, 1 / sqrtf(VectorDotProduct(pfK, pfK))); + + // + // Initialize the DCM matrix from the I, J, and K vectors. + // + psDCM->ppfDCM[0][0] = pfI[0]; + psDCM->ppfDCM[0][1] = pfI[1]; + psDCM->ppfDCM[0][2] = pfI[2]; + psDCM->ppfDCM[1][0] = pfJ[0]; + psDCM->ppfDCM[1][1] = pfJ[1]; + psDCM->ppfDCM[1][2] = pfJ[2]; + psDCM->ppfDCM[2][0] = pfK[0]; + psDCM->ppfDCM[2][1] = pfK[1]; + psDCM->ppfDCM[2][2] = pfK[2]; +} + +//***************************************************************************** +// +//! Updates the complementary filter DCM attitude estimation based on an +//! updated set of sensor readings. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! +//! This function updates the complementary filter DCM attitude estimation +//! state based on the current sensor readings. This function must be called +//! at the rate specified to CompDCMInit(), with new readings supplied at an +//! appropriate rate (for example, magnetometers typically sample at a much +//! slower rate than accelerometers and gyroscopes). +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMUpdate(tCompDCM *psDCM) +{ + float pfI[3], pfJ[3], pfK[3], pfDelta[3], pfTemp[3], fError; + bool bNAN; + + // + // The magnetometer reading forms the new Im vector, pointing north. + // + pfI[0] = psDCM->pfMagneto[0]; + pfI[1] = psDCM->pfMagneto[1]; + pfI[2] = psDCM->pfMagneto[2]; + + // + // The accelerometer reading forms the new Ka vector, pointing down. + // + pfK[0] = psDCM->pfAccel[0]; + pfK[1] = psDCM->pfAccel[1]; + pfK[2] = psDCM->pfAccel[2]; + + // + // Compute the new J vector, which is the cross product of the Ka and Im + // vectors. + // + VectorCrossProduct(pfJ, pfK, pfI); + + // + // Recompute the Im vector from the cross product of the J and Ka vectors. + // This makes it fully orthogonal, which it wasn't before since magnetic + // north points inside the Earth in many places. + // + VectorCrossProduct(pfI, pfJ, pfK); + + // + // Normalize the Im and Ka vectors. + // + VectorScale(pfI, pfI, 1 / sqrtf(VectorDotProduct(pfI, pfI))); + VectorScale(pfK, pfK, 1 / sqrtf(VectorDotProduct(pfK, pfK))); + + // + // Compute and scale the rotation as inferred from the accelerometer, + // storing it in the rotation accumulator. + // + VectorCrossProduct(pfTemp, psDCM->ppfDCM[2], pfK); + VectorScale(pfDelta, pfTemp, psDCM->fScaleA); + + // + // Compute and scale the rotation as measured by the gyroscope, adding it + // to the rotation accumulator. + // + pfTemp[0] = psDCM->pfGyro[0] * psDCM->fDeltaT * psDCM->fScaleG; + pfTemp[1] = psDCM->pfGyro[1] * psDCM->fDeltaT * psDCM->fScaleG; + pfTemp[2] = psDCM->pfGyro[2] * psDCM->fDeltaT * psDCM->fScaleG; + VectorAdd(pfDelta, pfDelta, pfTemp); + + // + // Compute and scale the rotation as inferred from the magnetometer, adding + // it to the rotation accumulator. + // + VectorCrossProduct(pfTemp, psDCM->ppfDCM[0], pfI); + VectorScale(pfTemp, pfTemp, psDCM->fScaleM); + VectorAdd(pfDelta, pfDelta, pfTemp); + + // + // Rotate the I vector from the DCM matrix by the scaled rotation. + // + VectorCrossProduct(pfI, pfDelta, psDCM->ppfDCM[0]); + VectorAdd(psDCM->ppfDCM[0], psDCM->ppfDCM[0], pfI); + + // + // Rotate the K vector from the DCM matrix by the scaled rotation. + // + VectorCrossProduct(pfK, pfDelta, psDCM->ppfDCM[2]); + VectorAdd(psDCM->ppfDCM[2], psDCM->ppfDCM[2], pfK); + + // + // Compute the orthogonality error between the rotated I and K vectors and + // adjust each by half the error, bringing them closer to orthogonality. + // + fError = VectorDotProduct(psDCM->ppfDCM[0], psDCM->ppfDCM[2]) / -2.0; + VectorScale(pfI, psDCM->ppfDCM[0], fError); + VectorScale(pfK, psDCM->ppfDCM[2], fError); + VectorAdd(psDCM->ppfDCM[0], psDCM->ppfDCM[0], pfK); + VectorAdd(psDCM->ppfDCM[2], psDCM->ppfDCM[2], pfI); + + // + // Normalize the I and K vectors. + // + VectorScale(psDCM->ppfDCM[0], psDCM->ppfDCM[0], + 0.5 * (3.0 - VectorDotProduct(psDCM->ppfDCM[0], + psDCM->ppfDCM[0]))); + VectorScale(psDCM->ppfDCM[2], psDCM->ppfDCM[2], + 0.5 * (3.0 - VectorDotProduct(psDCM->ppfDCM[2], + psDCM->ppfDCM[2]))); + + // + // Compute the rotated J vector from the cross product of the rotated, + // corrected K and I vectors. + // + VectorCrossProduct(psDCM->ppfDCM[1], psDCM->ppfDCM[2], psDCM->ppfDCM[0]); + + // + // Determine if the newly updated DCM contains any invalid (in other words, + // NaN) values. + // + bNAN = (isnan(psDCM->ppfDCM[0][0]) || + isnan(psDCM->ppfDCM[0][1]) || + isnan(psDCM->ppfDCM[0][2]) || + isnan(psDCM->ppfDCM[1][0]) || + isnan(psDCM->ppfDCM[1][1]) || + isnan(psDCM->ppfDCM[1][2]) || + isnan(psDCM->ppfDCM[2][0]) || + isnan(psDCM->ppfDCM[2][1]) || + isnan(psDCM->ppfDCM[2][2])); + + // + // As a debug measure, we check for NaN in the DCM. The user can trap + // this event depending on their implementation of __error__. Should they + // choose to disable interrupts and loop forever then they will have + // preserved the stack and can analyze how they arrived at NaN. + // + ASSERT(!bNAN); + + // + // If any part of the matrix is not-a-number then reset the DCM back to the + // identity matrix. + // + if(bNAN) + { + psDCM->ppfDCM[0][0] = 1.0; + psDCM->ppfDCM[0][1] = 0.0; + psDCM->ppfDCM[0][2] = 0.0; + psDCM->ppfDCM[1][0] = 0.0; + psDCM->ppfDCM[1][1] = 1.0; + psDCM->ppfDCM[1][2] = 0.0; + psDCM->ppfDCM[2][0] = 0.0; + psDCM->ppfDCM[2][1] = 0.0; + psDCM->ppfDCM[2][2] = 1.0; + } +} + +//***************************************************************************** +// +//! Returns the current DCM attitude estimation matrix. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! \param ppfDCM is a pointer to the array into which to store the DCM matrix +//! values. +//! +//! This function returns the current value of the DCM matrix. +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMMatrixGet(tCompDCM *psDCM, float ppfDCM[3][3]) +{ + // + // Return the current DCM matrix. + // + ppfDCM[0][0] = psDCM->ppfDCM[0][0]; + ppfDCM[0][1] = psDCM->ppfDCM[0][1]; + ppfDCM[0][2] = psDCM->ppfDCM[0][2]; + ppfDCM[1][0] = psDCM->ppfDCM[1][0]; + ppfDCM[1][1] = psDCM->ppfDCM[1][1]; + ppfDCM[1][2] = psDCM->ppfDCM[1][2]; + ppfDCM[2][0] = psDCM->ppfDCM[2][0]; + ppfDCM[2][1] = psDCM->ppfDCM[2][1]; + ppfDCM[2][2] = psDCM->ppfDCM[2][2]; +} + +//***************************************************************************** +// +//! Computes the Euler angles from the DCM attitude estimation matrix. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! \param pfRoll is a pointer to the value into which the roll is stored. +//! \param pfPitch is a pointer to the value into which the pitch is stored. +//! \param pfYaw is a pointer to the value into which the yaw is stored. +//! +//! This function computes the Euler angles that are represented by the DCM +//! attitude estimation matrix. If any of the Euler angles is not required, +//! the corresponding parameter can be \b NULL. +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMComputeEulers(tCompDCM *psDCM, float *pfRoll, float *pfPitch, + float *pfYaw) +{ + // + // Compute the roll, pitch, and yaw as required. + // + if(pfRoll) + { + *pfRoll = atan2f(psDCM->ppfDCM[2][1], psDCM->ppfDCM[2][2]); + } + if(pfPitch) + { + *pfPitch = -asinf(psDCM->ppfDCM[2][0]); + } + if(pfYaw) + { + *pfYaw = atan2f(psDCM->ppfDCM[1][0], psDCM->ppfDCM[0][0]); + } +} + +//***************************************************************************** +// +//! Computes the quaternion from the DCM attitude estimation matrix. +//! +//! \param psDCM is a pointer to the DCM state structure. +//! \param pfQuaternion is an array into which the quaternion is stored. +//! +//! This function computes the quaternion that is represented by the DCM +//! attitude estimation matrix. +//! +//! \return None. +// +//***************************************************************************** +void +CompDCMComputeQuaternion(tCompDCM *psDCM, float pfQuaternion[4]) +{ + float fQs, fQx, fQy, fQz; + + // + // Partially compute Qs, Qx, Qy, and Qz based on the DCM diagonals. The + // square root, an expensive operation, is computed for only one of these + // as determined later. + // + fQs = 1 + psDCM->ppfDCM[0][0] + psDCM->ppfDCM[1][1] + psDCM->ppfDCM[2][2]; + fQx = 1 + psDCM->ppfDCM[0][0] - psDCM->ppfDCM[1][1] - psDCM->ppfDCM[2][2]; + fQy = 1 - psDCM->ppfDCM[0][0] + psDCM->ppfDCM[1][1] - psDCM->ppfDCM[2][2]; + fQz = 1 - psDCM->ppfDCM[0][0] - psDCM->ppfDCM[1][1] + psDCM->ppfDCM[2][2]; + + // + // See if Qs is the largest of the diagonal values. + // + if((fQs > fQx) && (fQs > fQy) && (fQs > fQz)) + { + // + // Finish the computation of Qs. + // + fQs = sqrtf(fQs) / 2; + + // + // Compute the values of the quaternion based on Qs. + // + pfQuaternion[0] = fQs; + pfQuaternion[1] = ((psDCM->ppfDCM[2][1] - psDCM->ppfDCM[1][2]) / + (4 * fQs)); + pfQuaternion[2] = ((psDCM->ppfDCM[0][2] - psDCM->ppfDCM[2][0]) / + (4 * fQs)); + pfQuaternion[3] = ((psDCM->ppfDCM[1][0] - psDCM->ppfDCM[0][1]) / + (4 * fQs)); + } + + // + // Qs is not the largest, so see if Qx is the largest remaining diagonal + // value. + // + else if((fQx > fQy) && (fQx > fQz)) + { + // + // Finish the computation of Qx. + // + fQx = sqrtf(fQx) / 2; + + // + // Compute the values of the quaternion based on Qx. + // + pfQuaternion[0] = ((psDCM->ppfDCM[2][1] - psDCM->ppfDCM[1][2]) / + (4 * fQx)); + pfQuaternion[1] = fQx; + pfQuaternion[2] = ((psDCM->ppfDCM[1][0] + psDCM->ppfDCM[0][1]) / + (4 * fQx)); + pfQuaternion[3] = ((psDCM->ppfDCM[0][2] + psDCM->ppfDCM[2][0]) / + (4 * fQx)); + } + + // + // Qs and Qx are not the largest, so see if Qy is the largest remaining + // diagonal value. + // + else if(fQy > fQz) + { + // + // Finish the computation of Qy. + // + fQy = sqrtf(fQy) / 2; + + // + // Compute the values of the quaternion based on Qy. + // + pfQuaternion[0] = ((psDCM->ppfDCM[0][2] - psDCM->ppfDCM[2][0]) / + (4 * fQy)); + pfQuaternion[1] = ((psDCM->ppfDCM[1][0] + psDCM->ppfDCM[0][1]) / + (4 * fQy)); + pfQuaternion[2] = fQy; + pfQuaternion[3] = ((psDCM->ppfDCM[2][1] + psDCM->ppfDCM[1][2]) / + (4 * fQy)); + } + + // + // Qz is the largest diagonal value. + // + else + { + // + // Finish the computation of Qz. + // + fQz = sqrtf(fQz) / 2; + + // + // Compute the values of the quaternion based on Qz. + // + pfQuaternion[0] = ((psDCM->ppfDCM[1][0] - psDCM->ppfDCM[0][1]) / + (4 * fQz)); + pfQuaternion[1] = ((psDCM->ppfDCM[0][2] + psDCM->ppfDCM[2][0]) / + (4 * fQz)); + pfQuaternion[2] = ((psDCM->ppfDCM[2][1] + psDCM->ppfDCM[1][2]) / + (4 * fQz)); + pfQuaternion[3] = fQz; + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/comp_dcm.h b/sensorlib/comp_dcm.h new file mode 100644 index 0000000..860bda9 --- /dev/null +++ b/sensorlib/comp_dcm.h @@ -0,0 +1,120 @@ +//***************************************************************************** +// +// comp_dcm.h - Prototypes for the complementary filter direction cosine matrix +// functions. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_COMP_DCM_H__ +#define __SENSORLIB_COMP_DCM_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the complementary filter +// DCM algorithm. +// +//***************************************************************************** +typedef struct +{ + // + // The state of the direction cosine matrix. + // + float ppfDCM[3][3]; + + // + // The time delta between updates to the DCM. + // + float fDeltaT; + + // + // The scaling factor for the DCM update based on the accelerometer + // reading. + // + float fScaleA; + + // + // The scaling factor for the DCM update based on the gyroscope reading. + // + float fScaleG; + + // + // The scaling factor for the DCM update based on the magnetometer reading. + // + float fScaleM; + + // + // The most recent accelerometer readings. + // + float pfAccel[3]; + + // + // The most recent gyroscope readings. + // + float pfGyro[3]; + + // + // The most recent magnetometer readings. + // + float pfMagneto[3]; +} +tCompDCM; + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern void CompDCMInit(tCompDCM *psDCM, float fDeltaT, float fScaleA, + float fScaleG, float fScaleM); +extern void CompDCMAccelUpdate(tCompDCM *psDCM, float fAccelX, float fAccelY, + float fAccelZ); +extern void CompDCMGyroUpdate(tCompDCM *psDCM, float fGyroX, float fGyroY, + float fGyroZ); +extern void CompDCMMagnetoUpdate(tCompDCM *psDCM, float fMagnetoX, + float fMagnetoY, float fMagnetoZ); +extern void CompDCMStart(tCompDCM *psDCM); +extern void CompDCMUpdate(tCompDCM *psDCM); +extern void CompDCMMatrixGet(tCompDCM *psDCM, float ppfDCM[3][3]); +extern void CompDCMComputeEulers(tCompDCM *psDCM, float *pfRoll, + float *pfPitch, float *pfYaw); +extern void CompDCMComputeQuaternion(tCompDCM *psDCM, float pfQuaternion[4]); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_COMP_DCM_H__ diff --git a/sensorlib/ewarm/Exe/sensorlib.a b/sensorlib/ewarm/Exe/sensorlib.a new file mode 100644 index 0000000..408cb46 Binary files /dev/null and b/sensorlib/ewarm/Exe/sensorlib.a differ diff --git a/sensorlib/gcc/libsensor.a b/sensorlib/gcc/libsensor.a new file mode 100644 index 0000000..ae22311 Binary files /dev/null and b/sensorlib/gcc/libsensor.a differ diff --git a/sensorlib/hw_ak8963.h b/sensorlib/hw_ak8963.h new file mode 100644 index 0000000..53e43f2 --- /dev/null +++ b/sensorlib/hw_ak8963.h @@ -0,0 +1,209 @@ +//***************************************************************************** +// +// hw_ak8963.h - Macros used when accessing the Asahi Kasei AK8963 +// magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_AK8963_H__ +#define __SENSORLIB_HW_AK8963_H__ + +//***************************************************************************** +// +// The following are defines for the AK8963 register addresses. +// +//***************************************************************************** +#define AK8963_O_WIA 0x00 // Device ID register +#define AK8963_O_INFO 0x01 // Information register +#define AK8963_O_ST1 0x02 // Status 1 register +#define AK8963_O_HXL 0x03 // X-axis LSB output register +#define AK8963_O_HXH 0x04 // X-axis MSB output register +#define AK8963_O_HYL 0x05 // Y-axis LSB output register +#define AK8963_O_HYH 0x06 // Y-axis MSB output register +#define AK8963_O_HZL 0x07 // Z-axis LSB output register +#define AK8963_O_HZH 0x08 // Z-axis MSB output register +#define AK8963_O_ST2 0x09 // Status 2 register +#define AK8963_O_CNTL 0x0A // Control register +#define AK8963_O_CNTL2 0x0B // Control 2 register +#define AK8963_O_ASTC 0x0C // Self-test register +#define AK8963_O_I2CDIS 0x0F // Disable I2C bus interface +#define AK8963_O_ASAX 0x10 // X-axis sensitivity register +#define AK8963_O_ASAY 0x11 // Y-axis sensitivity register +#define AK8963_O_ASAZ 0x12 // Z-axis sensitivity register + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_WIA register. +// +//***************************************************************************** +#define AK8963_WIA_M 0xFF // Device ID +#define AK8963_WIA_AK8963 0x48 // AK8963 +#define AK8963_WIA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_INFO register. +// +//***************************************************************************** +#define AK8963_INFO_M 0xFF // Device information value +#define AK8963_INFO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_ST1 register. +// +//***************************************************************************** +#define AK8963_ST1_DOR 0x02 // Data overrun +#define AK8963_ST1_DRDY 0x01 // Data ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_HXL register. +// +//***************************************************************************** +#define AK8963_HXL_M 0xFF // Output data +#define AK8963_HXL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_HXH register. +// +//***************************************************************************** +#define AK8963_HXH_M 0xFF // Output data +#define AK8963_HXH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_HYL register. +// +//***************************************************************************** +#define AK8963_HYL_M 0xFF // Output data +#define AK8963_HYL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_HYH register. +// +//***************************************************************************** +#define AK8963_HYH_M 0xFF // Output data +#define AK8963_HYH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_HZL register. +// +//***************************************************************************** +#define AK8963_HZL_M 0xFF // Output data +#define AK8963_HZL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_HZH register. +// +//***************************************************************************** +#define AK8963_HZH_M 0xFF // Output data +#define AK8963_HZH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_ST2 register. +// +//***************************************************************************** +#define AK8963_ST2_BITM_M 0x10 // Output bit setting +#define AK8963_ST2_BITM_14BIT 0x00 // 14-bit output +#define AK8963_ST2_BITM_16BIT 0x10 // 16-bit output +#define AK8963_ST2_HOFL 0x08 // Magnetic sensor overflow +#define AK8963_ST2_BITM_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_CNTL register. +// +//***************************************************************************** +#define AK8963_CNTL_BITM_M 0x10 // Output bit setting +#define AK8963_CNTL_BITM_14BIT 0x00 // 14-bit output +#define AK8963_CNTL_BITM_16BIT 0x10 // 16-bit output +#define AK8963_CNTL_MODE_M 0x0F // Operation mode +#define AK8963_CNTL_MODE_POWER_DOWN \ + 0x00 // Power-down mode +#define AK8963_CNTL_MODE_SINGLE 0x01 // Single measurement mode +#define AK8963_CNTL_MODE_CONT_1 0x02 // Continuous measurement mode 1 + // (8Hz) +#define AK8963_CNTL_MODE_EXT_TRIG \ + 0x04 // External trigger measurement + // mode +#define AK8963_CNTL_MODE_CONT_2 0x06 // Continuous measurement mode 2 + // (100Hz) +#define AK8963_CNTL_MODE_SELF_TEST \ + 0x08 // Self-test mode +#define AK8963_CNTL_MODE_FUSE_ROM \ + 0x0F // Fuse ROM access mode +#define AK8963_CNTL_BITM_S 4 +#define AK8963_CNTL_MODE_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_CNTL2 register. +// +//***************************************************************************** +#define AK8963_CNTL2_SRST 0x01 // Register reset + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_ASTC register. +// +//***************************************************************************** +#define AK8963_ASTC_SELF 0x40 // Generate magnetic field for + // self-test + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_I2CDIS +// register. +// +//***************************************************************************** +#define AK8963_I2CDIS_I2CDIS 0xFF // Disable I2C bus interface + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_ASAX register. +// +//***************************************************************************** +#define AK8963_ASAX_M 0xFF // X-axis sensitivity adjustment +#define AK8963_ASAX_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_ASAY register. +// +//***************************************************************************** +#define AK8963_ASAY_M 0xFF // Y-axis sensitivity adjustment +#define AK8963_ASAY_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8963_O_ASAZ register. +// +//***************************************************************************** +#define AK8963_ASAZ_M 0xFF // Z-axis sensitivity adjustment +#define AK8963_ASAZ_S 0 + +#endif // __SENSORLIB_HW_AK8963_H__ diff --git a/sensorlib/hw_ak8975.h b/sensorlib/hw_ak8975.h new file mode 100644 index 0000000..e1cb847 --- /dev/null +++ b/sensorlib/hw_ak8975.h @@ -0,0 +1,177 @@ +//***************************************************************************** +// +// hw_ak8975.h - Macros used when accessing the Asahi Kasei AK8975 +// magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_AK8975_H__ +#define __SENSORLIB_HW_AK8975_H__ + +//***************************************************************************** +// +// The following are defines for the AK8975 register addresses. +// +//***************************************************************************** +#define AK8975_O_WIA 0x00 // Device ID register +#define AK8975_O_INFO 0x01 // Information register +#define AK8975_O_ST1 0x02 // Status 1 register +#define AK8975_O_HXL 0x03 // X-axis LSB output register +#define AK8975_O_HXH 0x04 // X-axis MSB output register +#define AK8975_O_HYL 0x05 // Y-axis LSB output register +#define AK8975_O_HYH 0x06 // Y-axis MSB output register +#define AK8975_O_HZL 0x07 // Z-axis LSB output register +#define AK8975_O_HZH 0x08 // Z-axis MSB output register +#define AK8975_O_ST2 0x09 // Status 2 register +#define AK8975_O_CNTL 0x0A // Control register +#define AK8975_O_ASTC 0x0C // Self-test register +#define AK8975_O_ASAX 0x10 // X-axis sensitivity register +#define AK8975_O_ASAY 0x11 // Y-axis sensitivity register +#define AK8975_O_ASAZ 0x12 // Z-axis sensitivity register + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_WIA register. +// +//***************************************************************************** +#define AK8975_WIA_M 0xFF // Device ID +#define AK8975_WIA_AK8975 0x48 // AK8975 +#define AK8975_WIA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_INFO register. +// +//***************************************************************************** +#define AK8975_INFO_M 0xFF // Device information value +#define AK8975_INFO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_ST1 register. +// +//***************************************************************************** +#define AK8975_ST1_DRDY 0x01 // Data ready + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_HXL register. +// +//***************************************************************************** +#define AK8975_HXL_M 0xFF // Output data +#define AK8975_HXL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_HXH register. +// +//***************************************************************************** +#define AK8975_HXH_M 0xFF // Output data +#define AK8975_HXH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_HYL register. +// +//***************************************************************************** +#define AK8975_HYL_M 0xFF // Output data +#define AK8975_HYL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_HYH register. +// +//***************************************************************************** +#define AK8975_HYH_M 0xFF // Output data +#define AK8975_HYH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_HZL register. +// +//***************************************************************************** +#define AK8975_HZL_M 0xFF // Output data +#define AK8975_HZL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_HZH register. +// +//***************************************************************************** +#define AK8975_HZH_M 0xFF // Output data +#define AK8975_HZH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_ST2 register. +// +//***************************************************************************** +#define AK8975_ST2_HOFL 0x08 // Magnetic sensor overflow +#define AK8975_ST2_DERR 0x04 // Data error + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_CNTL register. +// +//***************************************************************************** +#define AK8975_CNTL_MODE_M 0x0F // Operation mode +#define AK8975_CNTL_MODE_POWER_DOWN \ + 0x00 // Power-down mode +#define AK8975_CNTL_MODE_SINGLE 0x01 // Single measurement mode +#define AK8975_CNTL_MODE_SELF_TEST \ + 0x08 // Self-test mode +#define AK8975_CNTL_MODE_FUSE_ROM \ + 0x0F // Fuse ROM access mode +#define AK8975_CNTL_MODE_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_ASTC register. +// +//***************************************************************************** +#define AK8975_ASTC_SELF 0x40 // Generate magnetic field for + // self-test + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_ASAX register. +// +//***************************************************************************** +#define AK8975_ASAX_M 0xFF // X-axis sensitivity adjustment +#define AK8975_ASAX_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_ASAY register. +// +//***************************************************************************** +#define AK8975_ASAY_M 0xFF // Y-axis sensitivity adjustment +#define AK8975_ASAY_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the AK8975_O_ASAZ register. +// +//***************************************************************************** +#define AK8975_ASAZ_M 0xFF // Z-axis sensitivity adjustment +#define AK8975_ASAZ_S 0 + +#endif // __SENSORLIB_HW_AK8975_H__ diff --git a/sensorlib/hw_bmp180.h b/sensorlib/hw_bmp180.h new file mode 100644 index 0000000..7f8e3fe --- /dev/null +++ b/sensorlib/hw_bmp180.h @@ -0,0 +1,349 @@ +//***************************************************************************** +// +// hw_bmp180.h - Macros used when accessing the Bosch BMP180 barometric +// pressure sensor. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_BMP180_H__ +#define __SENSORLIB_HW_BMP180_H__ + +//***************************************************************************** +// +// The following are defines for the BMP180 register addresses. +// +//***************************************************************************** +#define BMP180_O_AC1_MSB 0xAA // AC1 MSB register +#define BMP180_O_AC1_LSB 0xAB // AC1 LSB register +#define BMP180_O_AC2_MSB 0xAC // AC2 MSB register +#define BMP180_O_AC2_LSB 0xAD // AC2 LSB register +#define BMP180_O_AC3_MSB 0xAE // AC3 MSB register +#define BMP180_O_AC3_LSB 0xAF // AC3 LSB register +#define BMP180_O_AC4_MSB 0xB0 // AC4 MSB register +#define BMP180_O_AC4_LSB 0xB1 // AC4 LSB register +#define BMP180_O_AC5_MSB 0xB2 // AC5 MSB register +#define BMP180_O_AC5_LSB 0xB3 // AC5 LSB register +#define BMP180_O_AC6_MSB 0xB4 // AC6 MSB register +#define BMP180_O_AC6_LSB 0xB5 // AC6 LSB register +#define BMP180_O_B1_MSB 0xB6 // B1 MSB register +#define BMP180_O_B1_LSB 0xB7 // B1 LSB register +#define BMP180_O_B2_MSB 0xB8 // B2 MSB register +#define BMP180_O_B2_LSB 0xB9 // B2 LSB register +#define BMP180_O_MB_MSB 0xBA // MB MSB register +#define BMP180_O_MB_LSB 0xBB // MB LSB register +#define BMP180_O_MC_MSB 0xBC // MC MSB register +#define BMP180_O_MC_LSB 0xBD // MC LSB register +#define BMP180_O_MD_MSB 0xBE // MD MSB register +#define BMP180_O_MD_LSB 0xBF // MD LSB register +#define BMP180_O_ID 0xD0 // Device ID register +#define BMP180_O_SOFT_RESET 0xE0 // Soft reset register +#define BMP180_O_CTRL_MEAS 0xF4 // Measurement control register +#define BMP180_O_OUT_MSB 0xF6 // ADC data MSB register +#define BMP180_O_OUT_LSB 0xF7 // ADC data LSB register +#define BMP180_O_OUT_XLSB 0xF8 // ADC data XLSB register + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC1_MSB +// register. +// +//***************************************************************************** +#define BMP180_AC1_MSB_M 0xFF // MSB of AC1 calibration + // coefficient +#define BMP180_AC1_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC1_LSB +// register. +// +//***************************************************************************** +#define BMP180_AC1_LSB_M 0xFF // LSB of AC1 calibration + // coefficient +#define BMP180_AC1_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC2_MSB +// register. +// +//***************************************************************************** +#define BMP180_AC2_MSB_M 0xFF // MSB of AC2 calibration + // coefficient +#define BMP180_AC2_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC2_LSB +// register. +// +//***************************************************************************** +#define BMP180_AC2_LSB_M 0xFF // LSB of AC2 calibration + // coefficient +#define BMP180_AC2_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC3_MSB +// register. +// +//***************************************************************************** +#define BMP180_AC3_MSB_M 0xFF // MSB of AC3 calibration + // coefficient +#define BMP180_AC3_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC3_LSB +// register. +// +//***************************************************************************** +#define BMP180_AC3_LSB_M 0xFF // LSB of AC3 calibration + // coefficient +#define BMP180_AC3_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC4_MSB +// register. +// +//***************************************************************************** +#define BMP180_AC4_MSB_M 0xFF // MSB of AC4 calibration + // coefficient +#define BMP180_AC4_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC4_LSB +// register. +// +//***************************************************************************** +#define BMP180_AC4_LSB_M 0xFF // LSB of AC4 calibration + // coefficient +#define BMP180_AC4_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC5_MSB +// register. +// +//***************************************************************************** +#define BMP180_AC5_MSB_M 0xFF // MSB of AC5 calibration + // coefficient +#define BMP180_AC5_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC5_LSB +// register. +// +//***************************************************************************** +#define BMP180_AC5_LSB_M 0xFF // LSB of AC5 calibration + // coefficient +#define BMP180_AC5_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC6_MSB +// register. +// +//***************************************************************************** +#define BMP180_AC6_MSB_M 0xFF // MSB of AC6 calibration + // coefficient +#define BMP180_AC6_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_AC6_LSB +// register. +// +//***************************************************************************** +#define BMP180_AC6_LSB_M 0xFF // LSB of AC6 calibration + // coefficient +#define BMP180_AC6_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_B1_MSB +// register. +// +//***************************************************************************** +#define BMP180_B1_MSB_M 0xFF // MSB of B1 calibration + // coefficient +#define BMP180_B1_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_B1_LSB +// register. +// +//***************************************************************************** +#define BMP180_B1_LSB_M 0xFF // LSB of B1 calibration + // coefficient +#define BMP180_B1_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_B2_MSB +// register. +// +//***************************************************************************** +#define BMP180_B2_MSB_M 0xFF // MSB of B2 calibration + // coefficient +#define BMP180_B2_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_B2_LSB +// register. +// +//***************************************************************************** +#define BMP180_B2_LSB_M 0xFF // LSB of B2 calibration + // coefficient +#define BMP180_B2_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_MB_MSB +// register. +// +//***************************************************************************** +#define BMP180_MB_MSB_M 0xFF // MSB of MB calibration + // coefficient +#define BMP180_MB_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_MB_LSB +// register. +// +//***************************************************************************** +#define BMP180_MB_LSB_M 0xFF // LSB of MB calibration + // coefficient +#define BMP180_MB_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_MC_MSB +// register. +// +//***************************************************************************** +#define BMP180_MC_MSB_M 0xFF // MSB of MC calibration + // coefficient +#define BMP180_MC_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_MC_LSB +// register. +// +//***************************************************************************** +#define BMP180_MC_LSB_M 0xFF // LSB of MC calibration + // coefficient +#define BMP180_MC_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_MD_MSB +// register. +// +//***************************************************************************** +#define BMP180_MD_MSB_M 0xFF // MSB of MD calibration + // coefficient +#define BMP180_MD_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_MD_LSB +// register. +// +//***************************************************************************** +#define BMP180_MD_LSB_M 0xFF // LSB of MD calibration + // coefficient +#define BMP180_MD_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_ID register. +// +//***************************************************************************** +#define BMP180_ID_M 0xFF // Device ID +#define BMP180_ID_BMP180 0x55 // BMP180 +#define BMP180_ID_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_SOFT_RESET +// register. +// +//***************************************************************************** +#define BMP180_SOFT_RESET_M 0xFF // Soft reset value +#define BMP180_SOFT_RESET_VALUE 0xB6 // Request a soft reset +#define BMP180_SOFT_RESET_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_CTRL_MEAS +// register. +// +//***************************************************************************** +#define BMP180_CTRL_MEAS_OSS_M 0xC0 // Oversampling ratio +#define BMP180_CTRL_MEAS_OSS_1 0x00 // Single sampling +#define BMP180_CTRL_MEAS_OSS_2 0x40 // 2x oversampling +#define BMP180_CTRL_MEAS_OSS_4 0x80 // 4x oversampling +#define BMP180_CTRL_MEAS_OSS_8 0xC0 // 8x oversampling +#define BMP180_CTRL_MEAS_SCO 0x20 // Start of conversion +#define BMP180_CTRL_MEAS_M 0x1F // Measurement control +#define BMP180_CTRL_MEAS_TEMPERATURE \ + 0x0E // Temperature measurement +#define BMP180_CTRL_MEAS_PRESSURE \ + 0x14 // Pressure measurement +#define BMP180_CTRL_MEAS_OSS_S 6 +#define BMP180_CTRL_MEAS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_OUT_MSB +// register. +// +//***************************************************************************** +#define BMP180_OUT_MSB_M 0xFF // Bits [20:13] of the ADC data +#define BMP180_OUT_MSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_OUT_LSB +// register. +// +//***************************************************************************** +#define BMP180_OUT_LSB_M 0xFF // Bits [12:5] of the ADC data +#define BMP180_OUT_LSB_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the BMP180_O_OUT_XLSB +// register. +// +//***************************************************************************** +#define BMP180_OUT_XLSB_M 0xF8 // Bits [4:0] of the ADC data +#define BMP180_OUT_XLSB_S 3 + +#endif // __SENSORLIB_HW_BMP180_H__ diff --git a/sensorlib/hw_bq27510g3.h b/sensorlib/hw_bq27510g3.h new file mode 100644 index 0000000..f0b3309 --- /dev/null +++ b/sensorlib/hw_bq27510g3.h @@ -0,0 +1,148 @@ +//***************************************************************************** +// +// hw_bq27510g3.h - Macros used when accessing the TI BQ27510-G3 Fuel Gauge +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_BQ27510G3_H__ +#define __SENSORLIB_HW_BQ27510G3_H__ + +//***************************************************************************** +// +// The following are defines for the BQ27510G3 register addresses +// +//***************************************************************************** +#define BQ27510G3_O_CNTL_LSB 0x00 // System Control Register LSB +#define BQ27510G3_O_CNTL_MSB 0x01 // System Control Register MSB +#define BQ27510G3_O_AT_RATE_LSB 0x02 // Discharge current value LSB +#define BQ27510G3_O_AT_RATE_MSB 0x03 // Discharge current value MSB +#define BQ27510G3_O_AT_RATE_TTE_LSB \ + 0x04 // Remaining operating time of + // battery with current AT_RATE LSB +#define BQ27510G3_O_AT_RATE_TTE_MSB \ + 0x05 // Remaining operating time of + // battery with current AT_RATE MSB +#define BQ27510G3_O_TEMP_LSB 0x06 // Battery temperature LSB +#define BQ27510G3_O_TEMP_MSB 0x07 // Battery temperature MSB +#define BQ27510G3_O_VOLT_LSB 0x08 // Battery cell-pack voltage LSB +#define BQ27510G3_O_VOLT_MSB 0x09 // Battery cell-pack voltage MSB +#define BQ27510G3_O_FLAGS_LSB 0x0A // Holds various operating status + // value of gas-guage LSB +#define BQ27510G3_O_FLAGS_MSB 0x0B // Holds various operating status + // value of gas-guage MSB +#define BQ27510G3_O_NOM_AV_CAP_LSB \ + 0x0C // Uncompensated battery capacity + // remaining LSB +#define BQ27510G3_O_NOM_AV_CAP_MSB \ + 0x0D // Uncompensated battery capacity + // remaining MSB +#define BQ27510G3_O_FULL_AV_CAP_LSB \ + 0x0E // Uncompensated capacity of fully + // charged battery LSB +#define BQ27510G3_O_FULL_AV_CAP_MSB \ + 0x0F // Uncompensated capacity of fully + // charged battery MSB +#define BQ27510G3_O_REM_CAP_LSB 0x10 // Compensated battery capacity + // remaining LSB +#define BQ27510G3_O_REM_CAP_MSB 0x11 // Compensated battery capacity + // remaining MSB +#define BQ27510G3_O_FULL_CHRG_CAP_LSB \ + 0x12 // Compensated battery capacity + // when fully charged LSB +#define BQ27510G3_O_FULL_CHRG_CAP_MSB \ + 0x13 // Compensated battery capacity + // when fully charged MSB +#define BQ27510G3_O_AVG_I_LSB 0x14 // Average current flow through + // sense resistor LSB +#define BQ27510G3_O_AVG_I_MSB 0x15 // Average current flow through + // sense resistor MSB +#define BQ27510G3_O_TTE_LSB 0x16 // Predicted remaining battery life + // (minutes) LSB +#define BQ27510G3_O_TTE_MSB 0x17 // Predicted remaining battery life + // (minutes) MSB +#define BQ27510G3_O_STBY_I_LSB 0x18 // Standbye current through sense + // resistor LSB +#define BQ27510G3_O_STBY_I_MSB 0x19 // Standbye current through sense + // resistor MSB +#define BQ27510G3_O_STBY_TTE_LSB \ + 0x1A // Predicted remaining standby + // battery life LSB +#define BQ27510G3_O_STBY_TTE_MSB \ + 0x1B // Predicted remaining standby + // battery life MSB +#define BQ27510G3_O_STATE_OF_HEALTH_LSB \ + 0x1C // State of health (percent) LSB +#define BQ27510G3_O_STATE_OF_HEALTH_MSB \ + 0x1D // State of health (percent) MSB +#define BQ27510G3_O_CYC_COUNT_LSB \ + 0x1E // Number of battery cycles + // experienced LSB +#define BQ27510G3_O_CYC_COUNT_MSB \ + 0x1F // Number of battery cycles + // experienced MSB +#define BQ27510G3_O_STATE_OF_CHRG_LSB \ + 0x20 // State of charge (percent) LSB +#define BQ27510G3_O_STATE_OF_CHRG_MSB \ + 0x21 // State of charge (percent) MSB +#define BQ27510G3_O_INST_I_LSB 0x22 // Instananeous current flow + // through sense resistor LSB +#define BQ27510G3_O_INST_I_MSB 0x23 // Instananeous current flow + // through sense resistor MSB +#define BQ27510G3_O_INT_TEMP_LSB \ + 0x28 // Internal tmeperature LSB +#define BQ27510G3_O_INT_TEMP_MSB \ + 0x29 // Internal tmeperature MSB +#define BQ27510G3_O_RES_SCALE_LSB \ + 0x2A // Resistance Scale LSB +#define BQ27510G3_O_RES_SCALE_MSB \ + 0x2B // Resistance Scale MSB +#define BQ27510G3_O_OP_CFG_LSB 0x2C // Operating Configuration LSB +#define BQ27510G3_O_OP_CFG_MSB 0x2D // Operating Configuration MSB +#define BQ27510G3_O_DCAP_LSB 0x2E // Designed capacity of battery LSB +#define BQ27510G3_O_DCAP_MSB 0x2F // Designed capacity of battery MSB + +//***************************************************************************** +// +// The following are defines for the bit fields in the BQ27510G3_O_CNTL_LSB +// register. +// +//***************************************************************************** +#define BQ27510G3_CNTL_LSB_FUNC_M \ + 0xFF // Functions +#define BQ27510G3_CNTL_LSB_FUNC_STATUS \ + 0x00 // reports DF checksum, hibernate, + // IT, etc +#define BQ27510G3_CNTL_LSB_FUNC_DEVTYPE \ + 0x01 // reports device type (for + // example: 0x0520) +#define BQ27510G3_CNTL_LSB_FUNC_FWVER \ + 0x02 // reports firmware version on the + // device type +#define BQ27510G3_CNTL_LSB_FUNC_PREVCMD \ + 0x07 // reports previous Control() + // subcommand code +#define BQ27510G3_CNTL_LSB_FUNC_RESET \ + 0x41 // forces a full reset of the fuel + // gauge +#define BQ27510G3_CNTL_LSB_FUNC_S \ + 0 + +#endif // __SENSORLIB_HW_BQ27510G3_H__ diff --git a/sensorlib/hw_cm3218.h b/sensorlib/hw_cm3218.h new file mode 100644 index 0000000..87f959b --- /dev/null +++ b/sensorlib/hw_cm3218.h @@ -0,0 +1,96 @@ +//***************************************************************************** +// +// hw_cm3218.h - Macros used for accessing the Capella CM3218 ambient light +// sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_CM3218_H__ +#define __SENSORLIB_HW_CM3218_H__ + +//***************************************************************************** +// +// The following are defines for the CM3218 Commands and Registers +// +//***************************************************************************** +#define CM3218_CMD_CONFIG 0x00 // Configure sensitivity, + // integration time, persistence + // protect, interrupts, and power +#define CM3218_CMD_HIGH_THRESHOLD \ + 0x01 // High threshold window setting +#define CM3218_CMD_LOW_THRESHOLD \ + 0x02 // Low threshold window setting +#define CM3218_CMD_ALS_DATA 0x04 // Read ambient light data + +//***************************************************************************** +// +// The following are defines for the bit fields in the CM3218_CMD_CONFIG +// register. +// +//***************************************************************************** +#define CM3218_CMD_CONFIG_SM_M 0x1800 // ALS sensitivity mode selection +#define CM3218_CMD_CONFIG_SM_10 0x0000 // Sensitivty * 1.0 +#define CM3218_CMD_CONFIG_SM_20 0x0800 // Sensitivty * 2.0 +#define CM3218_CMD_CONFIG_SM_05 0x1000 // Sensitivty * 0.5 +#define CM3218_CMD_CONFIG_SM_RSVD \ + 0x1800 // Reserved +#define CM3218_CMD_CONFIG_IT_M 0x00C0 // ALS integration time setting +#define CM3218_CMD_CONFIG_IT_05 0x0000 // integration time 0.5T +#define CM3218_CMD_CONFIG_IT_10 0x0040 // integration time 1.0T (default) +#define CM3218_CMD_CONFIG_IT_20 0x0080 // integration time 2.0T +#define CM3218_CMD_CONFIG_IT_40 0x00C0 // integration time 4.0T +#define CM3218_CMD_CONFIG_PERS_M \ + 0x0030 // ALS persistence protect number + // setting +#define CM3218_CMD_CONFIG_PERS_1 \ + 0x0000 // Persistence setting of 1 +#define CM3218_CMD_CONFIG_PERS_2 \ + 0x0010 // Persistence setting of 2 +#define CM3218_CMD_CONFIG_PERS_4 \ + 0x0020 // Persistence setting of 4 +#define CM3218_CMD_CONFIG_PERS_8 \ + 0x0030 // Persistence setting of 8 +#define CM3218_CMD_CONFIG_RSVD_M \ + 0x00C // Reserved +#define CM3218_CMD_CONFIG_RSVD_DEFAULT \ + 0x0004 // Default setting +#define CM3218_CMD_CONFIG_INT_M 0x2 // Interrupt Control +#define CM3218_CMD_CONFIG_INT_DISABLE \ + 0x0 // Disable interrupts +#define CM3218_CMD_CONFIG_INT_ENABLE \ + 0x2 // Enable interrupts +#define CM3218_CMD_CONFIG_POWER_M \ + 0x1 // Power Control +#define CM3218_CMD_CONFIG_POWER_ON \ + 0x0 // Power On +#define CM3218_CMD_CONFIG_POWER_OFF \ + 0x1 // Power Off +#define CM3218_CMD_CONFIG_SM_S 11 +#define CM3218_CMD_CONFIG_IT_S 6 +#define CM3218_CMD_CONFIG_PERS_S \ + 4 +#define CM3218_CMD_CONFIG_RSVD_S \ + 2 +#define CM3218_CMD_CONFIG_INT_S 1 +#define CM3218_CMD_CONFIG_POWER_S \ + 0 + +#endif // __SENSORLIB_HW_CM3218_H__ diff --git a/sensorlib/hw_isl29023.h b/sensorlib/hw_isl29023.h new file mode 100644 index 0000000..66f65ea --- /dev/null +++ b/sensorlib/hw_isl29023.h @@ -0,0 +1,128 @@ +//***************************************************************************** +// +// hw_isl29023.h - Macros used when accessing the Intersil ISL29023 ambient +// light sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_ISL29023_H__ +#define __SENSORLIB_HW_ISL29023_H__ + +//***************************************************************************** +// +// The following are defines for the ISL29023 Register Addresses +// +//***************************************************************************** +#define ISL29023_O_CMD_I 0x00 // ISL29023 command register one +#define ISL29023_O_CMD_II 0x01 +#define ISL29023_O_DATA_OUT_LSB 0x02 // Least significant byte of data +#define ISL29023_O_DATA_OUT_MSB 0x03 // Most significant byte of data +#define ISL29023_O_INT_LT_LSB 0x04 // Interrupt lower threshold least + // significant byte. +#define ISL29023_O_INT_LT_MSB 0x05 // Interrupt lower threshold most + // significant byte. +#define ISL29023_O_INT_HT_LSB 0x06 // Interrupt high threshold least + // significant byte. +#define ISL29023_O_INT_HT_MSB 0x07 // Interrupt high threshold most + // signficant byte + +//***************************************************************************** +// +// The following are defines for the bit fields in the ISL29023_O_CMD_I +// register. +// +//***************************************************************************** +#define ISL29023_CMD_I_OP_MODE_M \ + 0xE0 // Operation Mode +#define ISL29023_CMD_I_OP_MODE_POWER_DOWN \ + 0x00 // Power Down the device (Default) +#define ISL29023_CMD_I_OP_MODE_RESERVED_3 \ + 0x0E // RESERVED +#define ISL29023_CMD_I_OP_MODE_ALS_LOW \ + 0x20 // Measure ALS once per integration + // cyle +#define ISL29023_CMD_I_OP_MODE_IR_ONCE \ + 0x40 // Measure IR once +#define ISL29023_CMD_I_OP_MODE_RESERVED_1 \ + 0x60 // RESERVED +#define ISL29023_CMD_I_OP_MODE_RESERVED_2 \ + 0x80 // RESERVED +#define ISL29023_CMD_I_OP_MODE_ALS_CONT \ + 0xA0 // Measure ambient light sensor + // continuously. +#define ISL29023_CMD_I_OP_MODE_IR_CONT \ + 0xC // Measure infrared sensor + // continuously +#define ISL29023_CMD_I_INT_FLAG_M \ + 0x04 // Interrupt flag +#define ISL29023_CMD_I_INT_FLAG 0x04 // Interrupt flag +#define ISL29023_CMD_I_INT_PERSIST_M \ + 0x03 // Consecutive measurements outside + // threshold before interrupt +#define ISL29023_CMD_I_INT_PERSIST_1 \ + 0x00 // Interrupt on first cycle outside + // threshold +#define ISL29023_CMD_I_INT_PERSIST_4 \ + 0x01 // Interrupt on fourth cycle + // oustside threshold +#define ISL29023_CMD_I_INT_PERSIST_8 \ + 0x02 // Interrupt on eigth cycle outside + // threshold +#define ISL29023_CMD_I_INT_PERSIST_16 \ + 0x03 // Interrupt on sixteenth cycle + // outside threshold +#define ISL29023_CMD_I_OP_MODE_S \ + 5 +#define ISL29023_CMD_I_INT_FLAG_S \ + 2 +#define ISL_29023_CMD_I_INT_PERSIST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the ISL29023_O_CMD_II +// register. +// +//***************************************************************************** +#define ISL29023_CMD_II_ADC_RES_M \ + 0x0C // ADC resolution setting +#define ISL29023_CMD_II_ADC_RES_16 \ + 0x00 // 16 bit resolution +#define ISL29023_CMD_II_ADC_RES_12 \ + 0x04 // 12 bit resolution +#define ISL29023_CMD_II_ADC_RES_8 \ + 0x08 // 8 bit resolution +#define ISL29023_CMD_II_ADC_RES_4 \ + 0x0C // 4 bit resolution +#define ISL29023_CMD_II_RANGE_M 0x03 // Sensor Range Setting in Lux +#define ISL29023_CMD_II_RANGE_1K \ + 0x00 // 1000 lux range +#define ISL29023_CMD_II_RANGE_4K \ + 0x01 // 4000 lux range +#define ISL29023_CMD_II_RANGE_16K \ + 0x02 // 16000 lux range +#define ISL29023_CMD_II_RANGE_64K \ + 0x03 // 64000 lux range +#define ISL29023_CMD_II_ADC_RES_S \ + 2 +#define ISL29023_CMD_II_RANGE_S 0 + +#endif // __SENSORLIB_HW_ISL29023_H__ diff --git a/sensorlib/hw_kxti9.h b/sensorlib/hw_kxti9.h new file mode 100644 index 0000000..4ffc53a --- /dev/null +++ b/sensorlib/hw_kxti9.h @@ -0,0 +1,619 @@ +//***************************************************************************** +// +// hw_kxti9.h - Macros used when accessing the Kionix KXTI9 accelerometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_KXTI9_H__ +#define __SENSORLIB_HW_KXTI9_H__ + +//***************************************************************************** +// +// The following are defines for the KXTI9 register addresses. +// +//***************************************************************************** +#define KXTI9_O_XOUT_HFP_L 0x00 // X-axis high-pass data LSB + // register +#define KXTI9_O_XOUT_HFP_H 0x01 // X-axis high-pass data MSB + // register +#define KXTI9_O_YOUT_HFP_L 0x02 // Y-axis high-pass data LSB + // register +#define KXTI9_O_YOUT_HFP_H 0x03 // Y-axis high-pass data MSB + // register +#define KXTI9_O_ZOUT_HFP_L 0x04 // Z-axis high-pass data LSB + // register +#define KXTI9_O_ZOUT_HFP_H 0x05 // Z-axis high-pass data MSB + // register +#define KXTI9_O_XOUT_L 0x06 // X-axis data LSB register +#define KXTI9_O_XOUT_H 0x07 // X-axis data MSB register +#define KXTI9_O_YOUT_L 0x08 // Y-axis data LSB register +#define KXTI9_O_YOUT_H 0x09 // Y-axis data MSB register +#define KXTI9_O_ZOUT_L 0x0A // Z-axis data LSB register +#define KXTI9_O_ZOUT_H 0x0B // Z-axis data MSB register +#define KXTI9_O_DCST_RESP 0x0C // Digital Control Status register +#define KXTI9_O_WHO_AM_I 0x0F // Who Am I register +#define KXTI9_O_TILT_POS_CUR 0x10 // Current tilt position register +#define KXTI9_O_TILT_POS_PRE 0x11 // Previous tilt position register +#define KXTI9_O_INT_SRC1 0x15 // Interrupt source register 1 +#define KXTI9_O_INT_SRC2 0x16 // Interrupt source register2 +#define KXTI9_O_STATUS 0x18 // Status register +#define KXTI9_O_INT_REL 0x1A // Interrupt clear/release register +#define KXTI9_O_CTRL1 0x1B // Control register 1 +#define KXTI9_O_CTRL2 0x1C // Control register 2 +#define KXTI9_O_CTRL3 0x1D // Control register 3 +#define KXTI9_O_INT_CTRL1 0x1E // Interrupt control register 1 +#define KXTI9_O_INT_CTRL2 0x1F // Interrupt control register 2 +#define KXTI9_O_INT_CTRL3 0x20 // Interrupt control register 3 +#define KXTI9_O_DATA_CTRL 0x21 // Data control register +#define KXTI9_O_TILT_TIMER 0x28 // Tilt timer register +#define KXTI9_O_WUF_TIMER 0x29 // Wake-up timer register +#define KXTI9_O_TDT_TIMER 0x2B // TDT timer register +#define KXTI9_O_TDT_H_THRESH 0x2C // Jerk threshold high register +#define KXTI9_O_TDT_L_THRESH 0x2D // Jerk threshold low register +#define KXTI9_O_TDT_TAP_TIMER 0x2E // TDT tap timer register +#define KXTI9_O_TDT_TOTAL_TIMER 0x2F // TDT double tap timer register +#define KXTI9_O_TDT_LATENCY_TIMER \ + 0x30 // TDT tap latency timer register +#define KXTI9_O_TDT_WINDOW_TIMER \ + 0x31 // TDT tap window timer register +#define KXTI9_O_BUF_CTRL1 0x32 // Buffer control 1 register +#define KXTI9_O_BUF_CTRL2 0x33 // Buffer control 2 register +#define KXTI9_O_STATUS1 0x34 // Buffer status 1 register +#define KXTI9_O_STATUS2 0x35 // Buffer status 2 register +#define KXTI9_O_BUF_CLEAR 0x36 // Buffer status clear register +#define KXTI9_O_SELF_TEST 0x3A // Self-test register +#define KXTI9_O_WUF_THRESH 0x5A // Wake-up threshold register +#define KXTI9_O_TILT_ANGLE 0x5C // Tilt angle register +#define KXTI9_O_HYST_SET 0x5F // Hysteresis set register +#define KXTI9_O_BUF_READ 0x7F // Buffer read register + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_XOUT_HPF_L +// register. +// +//***************************************************************************** +#define KXTI9_XOUT_HPF_L_M 0xF0 // Bits [3:0] of high-pass filtered + // X-axis data +#define KXTI9_XOUT_HPF_L_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_XOUT_HPF_H +// register. +// +//***************************************************************************** +#define KXTI9_XOUT_HPF_H_M 0xFF // Bits [11:4] of high-pass + // filtered X-axis data +#define KXTI9_XOUT_HPF_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_YOUT_HPF_L +// register. +// +//***************************************************************************** +#define KXTI9_YOUT_HPF_L_M 0xF0 // Bits [3:0] of high-pass filtered + // Y-axis data +#define KXTI9_YOUT_HPF_L_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_YOUT_HPF_H +// register. +// +//***************************************************************************** +#define KXTI9_YOUT_HPF_H_M 0xFF // Bits [11:4] of high-pass + // filtered Y-axis data +#define KXTI9_YOUT_HPF_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_ZOUT_HPF_L +// register. +// +//***************************************************************************** +#define KXTI9_ZOUT_HPF_L_M 0xF0 // Bits [3:0] of high-pass filtered + // Z-axis data +#define KXTI9_ZOUT_HPF_L_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_ZOUT_HPF_H +// register. +// +//***************************************************************************** +#define KXTI9_ZOUT_HPF_H_M 0xFF // Bits [11:4] of high-pass + // filtered Z-axis data +#define KXTI9_ZOUT_HPF_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_XOUT_L register. +// +//***************************************************************************** +#define KXTI9_XOUT_L_M 0xF0 // Bits [3:0] of X-axis data +#define KXTI9_XOUT_L_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_XOUT_H register. +// +//***************************************************************************** +#define KXTI9_XOUT_H_M 0xFF // Bits [11:4] of X-axis data +#define KXTI9_XOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_YOUT_L register. +// +//***************************************************************************** +#define KXTI9_YOUT_L_M 0xF0 // Bits [3:0] of Y-axis data +#define KXTI9_YOUT_L_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_YOUT_H register. +// +//***************************************************************************** +#define KXTI9_YOUT_H_M 0xFF // Bits [11:4] of Y-axis data +#define KXTI9_YOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_ZOUT_L register. +// +//***************************************************************************** +#define KXTI9_ZOUT_L_M 0xF0 // Bits [3:0] of Z-axis data +#define KXTI9_ZOUT_L_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_ZOUT_H register. +// +//***************************************************************************** +#define KXTI9_ZOUT_H_M 0xFF // Bits [11:4] of Z-axis data +#define KXTI9_ZOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_DCST_RESP +// register. +// +//***************************************************************************** +#define KXTI9_DCST_RESP_M 0xFF // Check field +#define KXTI9_DCST_RESP_DEF 0x55 // Default response +#define KXTI9_DCST_RESP_INIT 0xAA // Post-initialization response +#define KXTI9_DCST_RESP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_WHO_AM_I +// register. +// +//***************************************************************************** +#define KXTI9_DCST_RESP_M 0xFF // Identification field +#define KXTI9_WHO_AM_I_KXTI9 0x04 // KXTI9 +#define KXTI9_WHO_AM_I_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TILT_POS_CUR +// register. +// +//***************************************************************************** +#define KXTI9_TILT_POS_CUR_LE 0x20 // Left state (X-) +#define KXTI9_TILT_POS_CUR_RI 0x10 // Right state (X+) +#define KXTI9_TILT_POS_CUR_DO 0x08 // Down state (Y-) +#define KXTI9_TILT_POS_CUR_UP 0x04 // Up state (Y+) +#define KXTI9_TILT_POS_CUR_FD 0x02 // Face-down state (Z-) +#define KXTI9_TILT_POS_CUR_FU 0x01 // Face-up state (Z+) + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TILT_POS_PRE +// register. +// +//***************************************************************************** +#define KXTI9_TILT_POS_PRE_LE 0x20 // Left state (X-) +#define KXTI9_TILT_POS_PRE_RI 0x10 // Right state (X+) +#define KXTI9_TILT_POS_PRE_DO 0x08 // Down state (Y-) +#define KXTI9_TILT_POS_PRE_UP 0x04 // Up state (Y+) +#define KXTI9_TILT_POS_PRE_FD 0x02 // Face-down state (Z-) +#define KXTI9_TILT_POS_PRE_FU 0x01 // Face-up state (Z+) + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_INT_SRC1 +// register. +// +//***************************************************************************** +#define KXTI9_INT_SRC1_TLE 0x20 // X negative (X-) reported +#define KXTI9_INT_SRC1_TRI 0x10 // X positive (X+) reported +#define KXTI9_INT_SRC1_TDO 0x08 // Y negative (Y-) reported +#define KXTI9_INT_SRC1_TUP 0x04 // Y positive (Y+) reported +#define KXTI9_INT_SRC1_TFD 0x02 // Z negative (Z-) reported +#define KXTI9_INT_SRC1_TFU 0x01 // Z positive (Z+) reported + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_INT_SRC2 +// register. +// +//***************************************************************************** +#define KXTI9_INT_SRC2_WMI 0x20 // Buffer sample threshold reached +#define KXTI9_INT_SRC2_DRDY 0x10 // New accel data ready +#define KXTI9_INT_SRC2_TDTS_M 0x0C // Tap event detected +#define KXTI9_INT_SRC2_TDTS_NONE \ + 0x00 // No tap event +#define KXTI9_INT_SRC2_TDTS_SINGLE \ + 0x01 // Single tap event +#define KXTI9_INT_SRC2_TDTS_DOUBLE \ + 0x02 // Double tap event +#define KXTI9_INT_SRC2_TDTS_DIRECTIONAL \ + 0x03 // Double tap event +#define KXTI9_INT_SRC2_WUFS 0x02 // Wake-up +#define KXTI9_INT_SRC2_TPS 0x01 // Tilt position change +#define KXTI9_INT_SRC2_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_STATUS register. +// +//***************************************************************************** +#define KXTI9_STATUS_INT 0x10 // Interrupt event + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_INT_REL +// register. +// +//***************************************************************************** +#define KXTI9_INT_REL_M 0xFF // Data is unpredictable +#define KXTI9_INT_REL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_CTRL1 register. +// +//***************************************************************************** +#define KXTI9_CTRL1_PC1 0x80 // Operating mode +#define KXTI9_CTRL1_RES 0x40 // Performance (resolution) mode +#define KXTI9_CTRL1_DRDYE 0x20 // New data interrupt enable +#define KXTI9_CTRL1_GSEL_M 0x18 // Acceleration range +#define KXTI9_CTRL1_GSEL_2G 0x00 // +/-2g +#define KXTI9_CTRL1_GSEL_4G 0x01 // +/-4g +#define KXTI9_CTRL1_GSEL_8G 0x02 // +/-8g +#define KXTI9_CTRL1_TDTE 0x04 // Directional tap enable +#define KXTI9_CTRL1_WUFE 0x02 // Wake-up enable +#define KXTI9_CTRL1_TPE 0x01 // Tilt position enable +#define KXTI9_CTRL1_GSEL_S 3 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_CTRL2 register. +// +//***************************************************************************** +#define KXTI9_CTRL2_OTDTH 0x80 // Output data rate selection for + // directional tap +#define KXTI9_CTRL2_LEM 0x20 // Left state tilt enable +#define KXTI9_CTRL2_RIM 0x10 // Right state tilt enable +#define KXTI9_CTRL2_DOM 0x08 // Down state tilt enable +#define KXTI9_CTRL2_UPM 0x04 // Up state tilt enable +#define KXTI9_CTRL2_FDM 0x02 // Face-down state tilt enable +#define KXTI9_CTRL2_FUM 0x01 // Face-up state tilt enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_CTRL3 register. +// +//***************************************************************************** +#define KXTI9_CTRL3_SRST 0x80 // Initiate software reset +#define KXTI9_CTRL3_OTP_M 0x60 // Output data rate for tilt + // position +#define KXTI9_CTRL3_OTP_1_6HZ 0x00 // Data rate is 1.6Hz +#define KXTI9_CTRL3_OTP_6_3HZ 0x01 // Data rate is 6.3Hz +#define KXTI9_CTRL3_OTP_12_5HZ 0x02 // Data rate is 12.5Hz +#define KXTI9_CTRL3_OTP_50HZ 0x03 // Data rate is 50Hz +#define KXTI9_CTRL3_OWUF_M 0x60 // Output data rate for motion + // detection and high-pass outputs +#define KXTI9_CTRL3_OWUF_25HZ 0x00 // Data rate is 25Hz +#define KXTI9_CTRL3_OWUF_50HZ 0x01 // Data rate is 50Hz +#define KXTI9_CTRL3_OWUF_100HZ 0x02 // Data rate is 100Hz +#define KXTI9_CTRL3_OWUF_200HZ 0x03 // Data rate is 200Hz +#define KXTI9_CTRL3_DCST 0x10 // Digital communication self-test +#define KXTI9_CTRL3_OTDT_M 0x0C // Encoding values change based on + // value of OTDTH bit +#define KXTI9_CTRL3_OTDT_0 0x00 // Encoding 0 is 50Hz or 12.5Hz +#define KXTI9_CTRL3_OTDT_1 0x01 // Encoding 1 is 100Hz or 25Hz +#define KXTI9_CTRL3_OTDT_2 0x02 // Encoding 2 is 200Hz or 800Hz +#define KXTI9_CTRL3_OTDT_3 0x03 // Encoding 3 is 400Hz or 1600Hz +#define KXTI9_CTRL3_OTP_S 5 +#define KXTI9_CTRL3_OTDT_S 2 +#define KXTI9_CTRL3_OWUF_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_INT_CTRL1 +// register. +// +//***************************************************************************** +#define KXTI9_INT_CTRL1_IEN 0x20 // Interrupt pin enable +#define KXTI9_INT_CTRL1_IEA 0x10 // Interrupt pin polarity +#define KXTI9_INT_CTRL1_IEL 0x08 // Interrupt pin response +#define KXTI9_INT_CTRL1_IEU 0x04 // Interrupt pin alternative + // response + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_INT_CTRL2 +// register. +// +//***************************************************************************** +#define KXTI9_INT_CTRL2_XBW 0x80 // X-axis motion interrupt enable +#define KXTI9_INT_CTRL2_YBW 0x40 // Y-axis motion interrupt enable +#define KXTI9_INT_CTRL2_ZBW 0x20 // Z-axis motion interrupt enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_INT_CTRL3 +// register. +// +//***************************************************************************** +#define KXTI9_INT_CTRL3_TMEN 0x40 // Tap masking scheme enable +#define KXTI9_INT_CTRL3_TLEM 0x20 // X negative interrupt enable +#define KXTI9_INT_CTRL3_TRIM 0x10 // X positive interrupt enable +#define KXTI9_INT_CTRL3_TDOM 0x08 // Y negative interrupt enable +#define KXTI9_INT_CTRL3_TUPM 0x04 // Y positive interrupt enable +#define KXTI9_INT_CTRL3_TFDM 0x02 // Z negative interrupt enable +#define KXTI9_INT_CTRL3_TFUM 0x01 // Z positive interrupt enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_DATA_CTRL +// register. +// +//***************************************************************************** +#define KXTI9_DATA_CTRL_HPFRO_M 0x30 // High-pass filter roll-off + // frequency +#define KXTI9_DATA_CTRL_HPFRO_50HZ \ + 0x00 // Roll-off at 50Hz +#define KXTI9_DATA_CTRL_HPFRO_100HZ \ + 0x01 // Roll-off at 100Hz +#define KXTI9_DATA_CTRL_HPFRO_200HZ \ + 0x02 // Roll-off at 200Hz +#define KXTI9_DATA_CTRL_HPFRO_400HZ \ + 0x03 // Roll-off at 400Hz +#define KXTI9_DATA_CTRL_OSA_M 0x07 // Output data rate and roll-off + // for low-pass filter outputs +#define KXTI9_DATA_CTRL_OSA_12_5HZ \ + 0x00 // 12.5Hz data rate, 6.25Hz LPF + // roll-off +#define KXTI9_DATA_CTRL_OSA_25HZ \ + 0x01 // 25Hz data rate, 12.5Hz LPF + // roll-off +#define KXTI9_DATA_CTRL_OSA_50HZ \ + 0x02 // 50Hz data rate, 25Hz LPF + // roll-off +#define KXTI9_DATA_CTRL_OSA_100HZ \ + 0x03 // 100Hz data rate, 50Hz LPF + // roll-off +#define KXTI9_DATA_CTRL_OSA_200HZ \ + 0x04 // 200Hz data rate, 100Hz LPF + // roll-off +#define KXTI9_DATA_CTRL_OSA_400HZ \ + 0x05 // 400Hz data rate, 200Hz LPF + // roll-off +#define KXTI9_DATA_CTRL_OSA_800HZ \ + 0x06 // 800Hz data rate, 400Hz LPF + // roll-off +#define KXTI9_DATA_CTRL_HPFRO_S 4 +#define KXTI9_DATA_CTRL_OSA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TILT_TIMER +// register. +// +//***************************************************************************** +#define KXTI9_TILT_TIMER_M 0xFF // Initial timer count +#define KXTI9_TILT_TIMER_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_WUF_TIMER +// register. +// +//***************************************************************************** +#define KXTI9_WUF_TIMER_M 0xFF // Initial timer count +#define KXTI9_WUF_TIMER_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TDT_TIMER +// register. +// +//***************************************************************************** +#define KXTI9_TDT_TIMER_M 0xFF // Initial timer count +#define KXTI9_TDT_TIMER_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TDT_H_THRESH +// register. +// +//***************************************************************************** +#define KXTI9_TDT_H_THRESH_M 0xFF // Threshold high value +#define KXTI9_TDT_H_THRESH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TDT_L_THRESH +// register. +// +//***************************************************************************** +#define KXTI9_TDT_L_THRESH_M 0xFF // Threshold low value +#define KXTI9_TDT_L_THRESH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TDT_TAP_TIMER +// register. +// +//***************************************************************************** +#define KXTI9_TDT_TAP_TIMER_M 0xFF // Tap event counter +#define KXTI9_TDT_TAP_TIMER_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TDT_TOTAL_TIMER +// register. +// +//***************************************************************************** +#define KXTI9_TDT_TOTAL_TIMER_M 0xFF // Double tap event counter +#define KXTI9_TDT_TOTAL_TIMER_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// KXTI9_O_TDT_LATENCY_TIMER register. +// +//***************************************************************************** +#define KXTI9_TDT_LATENCY_TIMER_M \ + 0xFF // Tap event latency counter +#define KXTI9_TDT_LATENCY_TIMER_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TDT_WINDOW_TIMER +// register. +// +//***************************************************************************** +#define KXTI9_TDT_WINDOW_TIMER_M \ + 0xFF // Tap event window counter +#define KXTI9_TDT_WINDOW_TIMER_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_BUF_CTRL1 +// register. +// +//***************************************************************************** +#define KXTI9_BUF_CTRL1_M 0x7F // Buffer sample threshold +#define KXTI9_BUF_CTRL1_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_BUF_CTRL2 +// register. +// +//***************************************************************************** +#define KXTI9_BUF_CTRL2_BUFE 0x80 // Buffer enable +#define KXTI9_BUF_CTRL2_BUF_RES 0x40 // Buffer resolution +#define KXTI9_BUF_CTRL2_BUF_M_M 0x03 // Buffer mode +#define KXTI9_BUF_CTRL2_BUF_M_FIFO \ + 0x00 // FIFO mode +#define KXTI9_BUF_CTRL2_BUF_M_STREAM \ + 0x01 // Stream mode +#define KXTI9_BUF_CTRL2_BUF_M_TRIG \ + 0x02 // Trigger mode +#define KXTI9_BUF_CTRL2_BUF_M_FILO \ + 0x03 // FILO mode +#define KXTI9_BUF_CTRL2_BUF_M_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_STATUS1 +// register. +// +//***************************************************************************** +#define KXTI9_STATUS1_SMP_LEV_M 0xFF // Number of bytes in sample buffer +#define KXTI9_STATUS1_SMP_LEV_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_STATUS2 +// register. +// +//***************************************************************************** +#define KXTI9_STATUS2_BUF_TRIG 0x80 // Trigger mode status + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_BUF_CLEAR +// register. +// +//***************************************************************************** +#define KXTI9_BUF_CLEAR_M 0xFF // Data is unpredictable +#define KXTI9_BUF_CLEAR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_SELF_TEST +// register. +// +//***************************************************************************** +#define KXTI9_SELF_TEST_M 0xFF // Writing 0xCA enables MEMS + // self-test +#define KXTI9_SELF_TEST_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_WUF_THRESH +// register. +// +//***************************************************************************** +#define KXTI9_WUF_THRESH_M 0xFF // Acceleration wake-up threshold +#define KXTI9_WUF_THRESH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_TILT_ANGLE +// register. +// +//***************************************************************************** +#define KXTI9_TILT_ANGLE_M 0xFF // Tilt angle threshold +#define KXTI9_TILT_ANGLE_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_HYST_SET +// register. +// +//***************************************************************************** +#define KXTI9_HYST_SET_RES_M 0xE0 // Factory set value - do not + // change +#define KXTI9_HYST_SET_HYST_M 0x1F // Hysteresis angle +#define KXTI9_HYST_SET_RES_S 5 +#define KXTI9_HYST_SET_HYST_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the KXTI9_O_BUF_READ +// register. +// +//***************************************************************************** +#define KXTI9_BUF_READ_M 0xFF // Read data from buffer +#define KXTI9_BUF_READ_S 0 + +#endif // __SENSORLIB_HW_KXTI9_H__ diff --git a/sensorlib/hw_l3gd20h.h b/sensorlib/hw_l3gd20h.h new file mode 100644 index 0000000..4a9a459 --- /dev/null +++ b/sensorlib/hw_l3gd20h.h @@ -0,0 +1,468 @@ +//***************************************************************************** +// +// hw_l3gd20h.h - Macros used when accessing the ST L3GD20H gyroscope +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_L3GD20H_H__ +#define __SENSORLIB_HW_L3GD20H_H__ + +//***************************************************************************** +// +// The following are defines for the L3GD20H register addresses +// +//***************************************************************************** +#define L3GD20H_O_WHOAMI 0x0F // Device idenfitication register +#define L3GD20H_O_CTRL1 0x20 // Control 1 - power settings +#define L3GD20H_O_CTRL2 0x21 // control 2 +#define L3GD20H_O_CTRL3 0x22 // Control 3 +#define L3GD20H_O_CTRL4 0x23 // Control 4 +#define L3GD20H_O_CTRL5 0x24 // Control 5 +#define L3GD20H_O_REFERENCE 0x25 // Reference register +#define L3GD20H_O_OUT_TEMP 0x26 // Temperature data; -1LSB/deg, + // two's complement +#define L3GD20H_O_STATUS 0x27 // Status register +#define L3GD20H_O_OUT_X_LSB 0x28 // X-axis LSB +#define L3GD20H_O_OUT_X_MSB 0x29 // X-axis MSB +#define L3GD20H_O_OUT_Y_LSB 0x2A // Y-axis LSB +#define L3GD20H_O_OUT_Y_MSB 0x2B // Y-axis MSB +#define L3GD20H_O_OUT_Z_LSB 0x2C // Z-axis LSB +#define L3GD20H_O_OUT_Z_MSB 0x2D // Z-axis MSB +#define L3GD20H_O_FIFO_CTRL 0x2E // FIFO control +#define L3GD20H_O_FIFO_SRC 0x2F // FIFO_SRC register +#define L3GD20H_O_IG_CFG 0x30 // Interrupt generation control +#define L3GD20H_O_IG_SRC 0x31 // interrupt source register (read + // only) +#define L3GD20H_O_IG_THS_XH 0x32 // Hi-X threshold +#define L3GD20H_O_IG_THS_XL 0x33 // Lo-X threshold +#define L3GD20H_O_IG_THS_TH 0x34 // Hi-Y threshold +#define L3GD20H_O_IG_THS_TL 0x35 // Lo-Y threshold +#define L3GD20H_O_IG_THS_ZH 0x36 // Hi-Z threshold +#define L3GD20H_O_IG_THS_ZL 0x37 // Lo-X threshold +#define L3GD20H_O_IG_DURATION 0x38 // Interrupt generation duration + // register +#define L3GD20H_O_LOW_ODR 0x39 // Low-speed output data rate (ODR) + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_CTRL1 +// register. +// +//***************************************************************************** +#define L3GD20H_CTRL1_DR_M 0xC0 // ODR select, x8 if Low_ODR = 0 +#define L3GD20H_CTRL1_DR_12_5_HZ \ + 0x00 // 12.5Hz or 100Hz +#define L3GD20H_CTRL1_DR_25_HZ 0x40 // 25Hz or 200Hz +#define L3GD20H_CTRL1_DR_50_HZ 0x80 // 50Hz or 400Hz +#define L3GD20H_CTRL1_DR_800_HZ 0xC0 // 800Hz of Low_ODR=0, or 50Hz + // otherwise +#define L3GD20H_CTRL1_BW_M 0x30 // Bandwidth select +#define L3GD20H_CTRL1_POWER_M 0x08 // Power control +#define L3GD20H_CTRL1_POWER_LOWPOW \ + 0x00 +#define L3GD20H_CTRL1_POWER_NORMAL \ + 0x08 +#define L3GD20H_CTRL1_AXIS_M 0x7 // Axis power control +#define L3GD20H_CTRL1_AXIS_Y_EN 0x01 // Y-axis enable +#define L3GD20H_CTRL1_AXIS_X_EN 0x02 // X-axis enable +#define L3GD20H_CTRL1_AXIS_Z_EN 0x04 // Z-axis enable +#define L3GD20H_CTRL1_DR_S 6 +#define L3GD20H_CTRL1_BW_S 4 +#define L3GD20H_CTRL1_AXIS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_CTRL2 +// register. +// +//***************************************************************************** +#define L3GD20H_CTRL2_EXTREN_M 0x80 // edge sensitive +#define L3GD20H_CTRL2_EXTREN_DIS \ + 0x00 +#define L3GD20H_CTRL2_EXTREN_EN 0x80 +#define L3GD20H_CTRL2_LVLEN_M 0x40 // level sensitive +#define L3GD20H_CTRL2_LVLEN_DIS 0x00 +#define L3GD20H_CTRL2_LVLEN_EN 0x40 +#define L3GD20H_CTRL2_HPM_M 0x30 // high pass filter mode selection +#define L3GD20H_CTRL2_HPCF_M 0x0F // high pass cutoff frequency + // selection +#define L3GD20H_CTRL2_HPM_S 4 +#define L3GD20H_CTRL2_HPCF_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_CTRL3 +// register. +// +//***************************************************************************** +#define L3GD20H_CTRL3_INT1_IG_M 0x80 // Interrupt enable on INT1 pin +#define L3GD20H_CTRL3_INT1_IG_DIS \ + 0x00 +#define L3GD20H_CTRL3_INT1_IG_EN \ + 0x80 +#define L3GD20H_CTRL3_INT1_BOOT_M \ + 0x40 // Boot status available on INT1 + // pin. +#define L3GD20H_CTRL3_INT1_BOOT_DIS \ + 0x00 +#define L3GD20H_CTRL3_INT1_BOOT_EN \ + 0x40 +#define L3GD20H_CTRL3_H_LACTIVE_M \ + 0x20 // Interrupt active configuration + // on INT; default value: 0 (0: + // high; 1:low) +#define L3GD20H_CTRL3_H_LACTIVE_HI \ + 0x00 +#define L3GD20H_CTRL3_H_LACTIVE_LOW \ + 0x20 +#define L3GD20H_CTRL3_DRIVE_TYPE_M \ + 0x10 // Push- Pull / Open drain; default + // value: 0 (0: push-pull; 1: open + // drain) +#define L3GD20H_CTRL3_DRIVE_TYPE_PP \ + 0x00 +#define L3GD20H_CTRL3_DRIVE_TYPE_OD \ + 0x10 +#define L3GD20H_CTRL3_INT2_DRDY_M \ + 0x08 // Date Ready on DRDY/INT2 pin; + // default value: 0 +#define L3GD20H_CTRL3_INT2_DRDY_DIS \ + 0x00 +#define L3GD20H_CTRL3_INT2_DRDY_EN \ + 0x08 +#define L3GD20H_CTRL3_INT2_FTH_M \ + 0x04 // FIFO Threshold interrupt on + // DRDY/INT2 pin; default value: 0 +#define L3GD20H_CTRL3_INT2_FTH_DIS \ + 0x00 +#define L3GD20H_CTRL3_INT2_FTH_EN \ + 0x04 +#define L3GD20H_CTRL3_INT2_ORUN_M \ + 0x02 // FIFO Overrun interrupt on + // DRDY/INT2 pin; default value: 0 +#define L3GD20H_CTRL3_INT2_ORUN_DIS \ + 0x00 +#define L3GD20H_CTRL3_INT2_ORUN_EN \ + 0x02 +#define L3GD20H_CTRL3_INT2_EMPTY_M \ + 0x01 // FIFO Empty interrupt on + // DRDY/INT2 pin; default value: 0 +#define L3GD20H_CTRL3_INT2_EMPTY_DIS \ + 0x00 +#define L3GD20H_CTRL3_INT2_EMPTY_EN \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_CTRL4 +// register. +// +//***************************************************************************** +#define L3GD20H_CTRL4_BDU_M 0x80 // Block data update; default + // value: 0 (0: continuous update; + // 1: output registers not updated + // until MSB and LSB reading) +#define L3GD20H_CTRL4_BDU_CONTINUOUS \ + 0x00 +#define L3GD20H_CTRL4_BDU_MSBLSB \ + 0x80 +#define L3GD20H_CTRL4_ENDIAN_M 0x40 // Endian selection +#define L3GD20H_CTRL4_ENDIAN_LITTLE \ + 0x00 +#define L3GD20H_CTRL4_ENDIAN_BIG \ + 0x40 +#define L3GD20H_CTRL4_FS_M 0x30 // full scale selection; default + // value: 0 +#define L3GD20H_CTRL4_FS_245DPS 0x00 // 245 degrees per second +#define L3GD20H_CTRL4_FS_500DPS 0x10 // 500 degrees per second +#define L3GD20H_CTRL4_FS_2000DPS \ + 0x30 // 2000 degrees per second +#define L3GD20H_CTRL4_IMPEN_M 0x08 // level sensitive latched enable; + // default value: 0 +#define L3GD20H_CTRL4_IMPEN_LVL_DIS \ + 0x00 +#define L3GD20H_CTRL4_IMPEN_LVL_EN \ + 0x08 +#define L3GD20H_CTRL4_SELFTEST_M \ + 0x06 // self-test mode +#define L3GD20H_CTRL4_SELFTEST_NORMAL \ + 0x00 // Normal mode (not self test, + // default) +#define L3GD20H_CTRL4_SELFTEST_MODE0 \ + 0x02 // Self-test mode 0 (+) +#define L3GD20H_CTRL4_SELFTEST_MODE1 \ + 0x06 // Self-test mode 1 (-) +#define L3GD20H_CTRL4_SIM_M 0x01 // SPI Serial Interface Mode + // selection (default = 0, 4-wire) +#define L3GD20H_CTRL4_SIM_4WIRE 0x00 +#define L3GD20H_CTRL4_SIM_3WIRE 0x01 +#define L3GD20H_CTRL4_FS_S 4 +#define L3GD20H_CTRL4_SELFTEST_S \ + 1 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_CTRL5 +// register. +// +//***************************************************************************** +#define L3GD20H_CTRL5_REBOOTCTL_M \ + 0x80 // Reboot memory conent +#define L3GD20H_CTRL5_REBOOTCTL_NORMAL \ + 0x00 +#define L3GD20H_CTRL5_REBOOTCTL_REBOOT \ + 0x80 +#define L3GD20H_CTRL5_FIFOCTL_M 0x40 // FIFO control +#define L3GD20H_CTRL5_FIFOCTL_DIS \ + 0x00 +#define L3GD20H_CTRL5_FIFOCTL_EN \ + 0x40 +#define L3GD20H_CTRL5_STOPONFTH_M \ + 0x20 // Sensing chain FIFO stop values + // memorization at FIFO Threshold; + // default value: 0 +#define L3GD20H_CTRL5_STOPONFTH_UNLIMITED \ + 0x00 +#define L3GD20H_CTRL5_STOPONFTH_THRESH_LIMITED \ + 0x20 +#define L3GD20H_CTRL5_HPEN_M 0x10 // high pass filtern enable + // (default 0) +#define L3GD20H_CTRL5_HPEN_DIS 0x00 +#define L3GD20H_CTRL5_HPEN_EN 0x10 +#define L3GD20H_CTRL5_IG_SEL_M 0x0C // interrupt generator section + // configuration +#define L3GD20H_CTRL5_OUT_SEL_M 0x03 // out selection configuration +#define L3GD20H_CTRL5_IG_SEL_S 2 +#define L3GD20H_CTRL5_OUT_SEL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_STATUS +// register. +// +//***************************************************************************** +#define L3GD20H_STATUS_OR_M 0xF0 // Axis data overrun +#define L3GD20H_STATUS_OR_X 0x10 // X-axis data overrun +#define L3GD20H_STATUS_OR_Y 0x20 // Y-axis data overrun +#define L3GD20H_STATUS_OR_Z 0x40 // Z-axis data overrun +#define L3GD20H_STATUS_OR_ZYX 0x80 // X, Y, and X data overrun +#define L3GD20H_STATUS_DA_M 0xF // Axis data available +#define L3GD20H_STATUS_DA_X 0x01 // X-axis data available +#define L3GD20H_STATUS_DA_Y 0x02 // Y-axis data available +#define L3GD20H_STATUS_DA_Z 0x04 // Z-axis data available +#define L3GD20H_STATUS_DA_ZYX 0x08 // X, Y, and X data available +#define L3GD20H_STATUS_OR_S 4 +#define L3GD20H_STATUS_DA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_FIFO_CTRL +// register. +// +//***************************************************************************** +#define L3GD20H_FIFO_CTRL_THRESH_M \ + 0x1F // FIFO Threshold setting +#define L3GD20H_FIFO_CTRL_MODE_M \ + 0xE // FIFO mode setting +#define L3GD20H_FIFO_CTRL_MODE_S \ + 5 +#define L3GD20H_FIFO_CTRL_THRESH_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_FIFO_SRC +// register. +// +//***************************************************************************** +#define L3GD20H_FIFO_SRC_FTH_M 0x80 // FIFO threshold is greater than + // or equal to level or less than + // level +#define L3GD20H_FIFO_SRC_FTH_LT 0x00 +#define L3GD20H_FIFO_SRC_FTH_GEQ \ + 0x80 +#define L3GD20H_FIFO_SRC_OVRN_M 0x40 // overrun status bit +#define L3GD20H_FIFO_SRC_OVRN_FILLED \ + 0x40 +#define L3GD20H_FIFO_SRC_EMPTY_M \ + 0x20 // FIFO empty +#define L3GD20H_FIFO_SRC_EMPTY_EMPTY \ + 0x20 +#define L3GD20H_FIFO_SRC_STORE_SAMPLES_M \ + 0x1F // FIFO stored data level of the + // unread samples +#define L3GD20H_FIFO_SRC_STORE_SAMPLES_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_IG_CFG +// register. +// +//***************************************************************************** +#define L3GD20H_IG_CFG_ANDOR_M 0x80 // AND/OR combination of Interrupt + // events; default value: 0 +#define L3GD20H_IG_CFG_ANDOR_OR 0x00 +#define L3GD20H_IG_CFG_ANDOR_AND \ + 0x80 +#define L3GD20H_IG_CFG_LIR_M 0x40 // Latch Interrupt Request; default + // value: 0 +#define L3GD20H_IG_CFG_LIR_LATCHED \ + 0x40 +#define L3GD20H_IG_CFG_ZHI_M 0x20 // enable interrupt generation on + // Z-hi event +#define L3GD20H_IG_CFG_ZHI_EN 0x20 +#define L3GD20H_IG_CFG_ZLI_M 0x10 // enable interrupt generation on + // Z-low event +#define L3GD20H_IG_CFG_ZLI_EN 0x10 +#define L3GD20H_IG_CFG_YHI_M 0x08 // enable interrupt generation on + // Y-hi event +#define L3GD20H_IG_CFG_YHI_EN 0x08 +#define L3GD20H_IG_CFG_YLI_M 0x04 // enable interrupt generation on + // Y-low event +#define L3GD20H_IG_CFG_YLI_EN 0x04 +#define L3GD20H_IG_CFG_XHI_M 0x02 // enable interrupt generation on + // X-hi event +#define L3GD20H_IG_CFG_XHI_EN 0x02 +#define L3GD20H_IG_CFG_XLI_M 0x01 // enable interrupt generation on + // X-low event +#define L3GD20H_IG_CFG_XLI_EN 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_IG_SRC +// register. +// +//***************************************************************************** +#define L3GD20H_IG_SRC_IA_M 0x40 // interrupt active +#define L3GD20H_IG_SRC_IA_ACTIVE \ + 0x40 +#define L3GD20H_IG_SRC_ZH_M 0x20 // Z-Hi event occurred +#define L3GD20H_IG_SRC_ZH_OCCURRED \ + 0x20 +#define L3GD20H_IG_SRC_ZL_M 0x10 // Z-Low event occurred +#define L3GD20H_IG_SRC_ZL_OCCURRED \ + 0x10 +#define L3GD20H_IG_SRC_YH_M 0x08 // Y-Hi event occurred +#define L3GD20H_IG_SRC_YH_OCCURRED \ + 0x08 +#define L3GD20H_IG_SRC_YL_M 0x04 // Y-Low event occurred +#define L3GD20H_IG_SRC_YL_OCCURRED \ + 0x04 +#define L3GD20H_IG_SRC_XH_M 0x02 // X-Hi event occurred +#define L3GD20H_IG_SRC_XH_OCCURRED \ + 0x02 +#define L3GD20H_IG_SRC_XL_M 0x01 // X-Low event occurred +#define L3GD20H_IG_SRC_XL_OCCURRED \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_IG_THS_XH +// register. +// +//***************************************************************************** +#define L3GD20H_IG_THS_XH_DCRM_M \ + 0x80 // interrupt generation counter + // mode +#define L3GD20H_IG_THS_XH_DCRM_RESET \ + 0x00 +#define L3GD20H_IG_THS_XH_DCRM_DECREMENT \ + 0x80 +#define L3GD20H_IG_THS_XH_THSX_M \ + 0x7F // THSX[14-8], default 0x0 +#define L3GD20H_IG_THS_XH_THSX_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_IG_THS_TH +// register. +// +//***************************************************************************** +#define L3GD20H_IG_THS_TH_THSY_M \ + 0x7F // THSY[14-8], default 0x0 +#define L3GD20H_IG_THS_TH_THSY_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_IG_THS_ZH +// register. +// +//***************************************************************************** +#define L3GD20H_IG_THS_ZH_THSX_M \ + 0x7F // THSZ[14-8], default 0x0 +#define L3GD20H_IG_THS_ZH_THSX_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_IG_DURATION +// register. +// +//***************************************************************************** +#define L3GD20H_IG_DURATION_WAIT_M \ + 0x80 // If WAIT is enabled then DURATION + // samples must occur before + // asserting the interrupt. +#define L3GD20H_IG_DURATION_WAIT_DIS \ + 0x00 +#define L3GD20H_IG_DURATION_WAIT_EN \ + 0x80 +#define L3GD20H_IG_DURATION_DURATION_M \ + 0x7F // Duration D[6-0] +#define L3GD20H_IG_DURATION_DURATION_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the L3GD20H_O_LOW_ODR +// register. +// +//***************************************************************************** +#define L3GD20H_LOW_ODR_DRDY_HL_M \ + 0x20 // DRDY/INT2 active level +#define L3GD20H_LOW_ODR_DRDY_HL_ACTIVE_LOW \ + 0x00 +#define L3GD20H_LOW_ODR_DRDY_HL_ACTIVE_HIGH \ + 0x20 +#define L3GD20H_LOW_ODR_I2C_DISABLE_M \ + 0x08 // disable I2C interface +#define L3GD20H_LOW_ODR_I2C_DISABLE_BOTH \ + 0x00 +#define L3GD20H_LOW_ODR_I2C_DISABLE_SPI_ONLY \ + 0x08 +#define L3GD20H_LOW_ODR_SWRESET_M \ + 0x04 // software reset +#define L3GD20H_LOW_ODR_SWRESET_NORMAL \ + 0x00 +#define L3GD20H_LOW_ODR_SWRESET_RESET \ + 0x04 +#define L3GD20H_LOW_ODR_DATARATE_M \ + 0x01 // Low-speed data rate enable; + // default value: 0 +#define L3GD20H_LOW_ODR_DATARATE_HIGH \ + 0x00 +#define L3GD20H_LOW_ODR_DATARATE_LOW \ + 0x01 + +#endif // __SENSORLIB_HW_L3GD20H_H__ diff --git a/sensorlib/hw_lsm303d.h b/sensorlib/hw_lsm303d.h new file mode 100644 index 0000000..19ea89e --- /dev/null +++ b/sensorlib/hw_lsm303d.h @@ -0,0 +1,1017 @@ +//***************************************************************************** +// +// hw_lsm303d.h - Macros used when accessing the ST LSM303D +// accelerometer/magnetometer +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_LSM303D_H__ +#define __SENSORLIB_HW_LSM303D_H__ + +//***************************************************************************** +// +// The following are defines for the LSM303D register addresses +// +//***************************************************************************** +#define LSM303D_O_TEMP_OUT_LSB 0x5 // Temperature bits 7-0 +#define LSM303D_O_TEMP_OUT_MSB 0x6 // Temperature bits 11-8 +#define LSM303D_O_MAG_STATUS 0x7 // Magnetic status register +#define LSM303D_O_MAG_OUT_X_MSB 0x08 // X-axis MSB +#define LSM303D_O_MAG_OUT_X_LSB 0x09 // X-axis LSB +#define LSM303D_O_MAG_OUT_Y_MSB 0x0A // Y-axis MSB +#define LSM303D_O_MAG_OUT_Y_LSB 0x0B // Y-axis LSB +#define LSM303D_O_MAG_OUT_Z_MSB 0x0C // Z-axis MSB +#define LSM303D_O_MAG_OUT_Z_LSB 0x0D // Z-axis LSB +#define LSM303D_O_WHO_AM_I 0x0F // ID register, constant 0x49 +#define LSM303D_O_MAG_INT_CTRL 0x12 // magnetic control register +#define LSM303D_O_MAG_INT_SRC 0x13 // Interrupt source (status) for + // magnetometer interrupt +#define LSM303D_O_MAG_THS_MSB 0x14 // Threshold MSB +#define LSM303D_O_MAG_THS_LSB 0x15 // Threshold LSB. Even though the + // threshold is expressed in + // absolute value, the device + // detects both positive and + // negative thresholds. +#define LSM303D_O_MAG_OFFSET_X_MSB \ + 0x16 // MSB of Magnetic offset for + // X-axis. The value is expressed + // in 16-bit as 2s complement. +#define LSM303D_O_MAG_OFFSET_X_LSB \ + 0x17 // LSB of Magnetic offset for + // X-axis. The value is expressed + // in 16-bit as 2s complement. +#define LSM303D_O_MAG_OFFSET_Y_MSB \ + 0x18 // MSB of Magnetic offset for + // Y-axis. The value is expressed + // in 16-bit as 2s complement. +#define LSM303D_O_MAG_OFFSET_Y_LSB \ + 0x19 // LSB of Magnetic offset for + // Y-axis. The value is expressed + // in 16-bit as 2s complement. +#define LSM303D_O_MAG_OFFSET_Z_MSB \ + 0x1A // MSB of Magnetic offset for + // Z-axis. The value is expressed + // in 16-bit as 2s complement. +#define LSM303D_O_MAG_OFFSET_Z_LSB \ + 0x1B // LSB of Magnetic offset for + // Z-axis. The value is expressed + // in 16-bit as 2s complement. +#define LSM303D_O_ACCEL_REFERENCE_X \ + 0x1C // Reference value for high-pass + // filter for X-axis acceleration + // data. +#define LSM303D_O_ACCEL_REFERENCE_Y \ + 0x1D // Reference value for high-pass + // filter for Y-axis acceleration + // data. +#define LSM303D_O_ACCEL_REFERENCE_Z \ + 0x1E // Reference value for high-pass + // filter for Z-axis acceleration + // data. +#define LSM303D_O_CTRL0 0x1F // Accel control 0 +#define LSM303D_O_CTRL1 0x20 // Control 1 - power settings +#define LSM303D_O_CTRL2 0x21 // Control 2 +#define LSM303D_O_CTRL3 0x22 // Control 3 +#define LSM303D_O_CTRL4 0x23 // Control 4 +#define LSM303D_O_CTRL5 0x24 // Control 5 +#define LSM303D_O_CTRL6 0x25 // Control 6 +#define LSM303D_O_CTRL7 0x26 // Control 7 +#define LSM303D_O_STATUS 0x27 // Status register +#define LSM303D_O_OUT_X_LSB 0x28 // X-axis LSB +#define LSM303D_O_OUT_X_MSB 0x29 // X-axis MSB +#define LSM303D_O_OUT_Y_LSB 0x2A // Y-axis LSB +#define LSM303D_O_OUT_Y_MSB 0x2B // Y-axis MSB +#define LSM303D_O_OUT_Z_LSB 0x2C // Z-axis LSB +#define LSM303D_O_OUT_Z_MSB 0x2D // Z-axis MSB +#define LSM303D_O_FIFO_CTRL 0x2E // FIFO control +#define LSM303D_O_FIFO_SRC 0x2F // FIFO_SRC register +#define LSM303D_O_INT1_CFG 0x30 // INT1 interrupt generation; this + // register only writable after + // boot +#define LSM303D_O_INT1_SRC 0x31 // interrupt source register (read + // only) +#define LSM303D_O_INT1_THS 0x32 // Interrupt 1 threshold +#define LSM303D_O_INT1_DURATION 0x33 // INT1 duration register +#define LSM303D_O_INT2_CFG 0x34 // INT2 interrupt generation; this + // register only writable after + // boot +#define LSM303D_O_INT2_SRC 0x35 // INT2 source register (read only) +#define LSM303D_O_INT2_THS 0x36 // INT2 threshold +#define LSM303D_O_INT2_DURATION 0x37 // INT2 duration register +#define LSM303D_O_CLICK_CFG 0x38 // Click config A register +#define LSM303D_O_CLICK_SRC 0x39 // Click source A +#define LSM303D_O_CLICK_THS 0x3A // click-click threshold +#define LSM303D_O_TIME_LIMIT 0x3B // Time Limit A register +#define LSM303D_O_TIME_LATENCY 0x3C // Time Latency A register; 1 LSB = + // 1/ODR; TLA7 through TLA0 define + // the time interval that starts + // after the first click detection + // where the click detection + // procedure is disabled, in cases + // where the device is configured + // for double click detection +#define LSM303D_O_TIME_WINDOW 0x3D // Time Window A register; 1 LSB = + // 1/ODR; TW7 through TW0 define + // the maximum interval of time + // that can elapse after the end of + // the latency interval in which + // the click detection procedure + // can start, in cases where the + // device is configured for double + // click detection +#define LSM303D_O_ACT_THS 0x3E // Sleep to Wake, Return to Sleep + // activation threshold 1LSb = 16mg +#define LSM303D_O_ACT_DUR 0x3F // Sleep to Wake, Return to Sleep + // duration DUR = (Act_DUR + + // 1)*8/ODR + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_TEMP_OUT_LSB +// register. +// +//***************************************************************************** +#define LSM303D_TEMP_OUT_LSB_LSB_M \ + 0xFF +#define LSM303D_TEMP_OUT_LSB_LSB_S \ + 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_TEMP_OUT_MSB +// register. +// +//***************************************************************************** +#define LSM303D_TEMP_OUT_MSB_MSB_M \ + 0x0F +#define LSM303D_TEMP_OUT_MSB_MSB_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_MAG_STATUS +// register. +// +//***************************************************************************** +#define LSM303D_MAG_STATUS_ZYXTMOR_M \ + 0x80 // X,Y,Z axis and temp data overrun +#define LSM303D_MAG_STATUS_ZYXTMOR_TRUE \ + 0x80 +#define LSM303D_MAG_STATUS_ZMOR_M \ + 0x40 // Z-axis mag data overrun +#define LSM303D_MAG_STATUS_ZMOR_TRUE \ + 0x40 +#define LSM303D_MAG_STATUS_YMOR_M \ + 0x20 // Y-axis mag data overrun +#define LSM303D_MAG_STATUS_YMOR_TRUE \ + 0x20 +#define LSM303D_MAG_STATUS_XMOR_M \ + 0x10 // X-axis mag data overrun +#define LSM303D_MAG_STATUS_XMOR_TRUE \ + 0x10 +#define LSM303D_MAG_STATUS_ZYXTMD_M \ + 0x08 // X,Y,Z axis and temp data + // available +#define LSM303D_MAG_STATUS_ZYXTMD_AVAIL \ + 0x08 +#define LSM303D_MAG_STATUS_ZMD_M \ + 0x04 // New mag data available for Z + // axis +#define LSM303D_MAG_STATUS_ZMD_AVAIL \ + 0x04 +#define LSM303D_MAG_STATUS_YMD_M \ + 0x02 // New mag data available for Y + // axis +#define LSM303D_MAG_STATUS_YMD_AVAIL \ + 0x02 +#define LSM303D_MAG_STATUS_XMD_M \ + 0x01 // New mag data available for X + // axis +#define LSM303D_MAG_STATUS_XMD_AVAIL \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_MAG_INT_CTRL +// register. +// +//***************************************************************************** +#define LSM303D_MAG_INT_CTRL_XINT_M \ + 0x80 // Enable interrupt recognition on + // X-axis for magnetic data. +#define LSM303D_MAG_INT_CTRL_XINT_ENABLE \ + 0x80 +#define LSM303D_MAG_INT_CTRL_YINT_M \ + 0x40 // Enable interrupt recognition on + // Y-axis for magnetic data. +#define LSM303D_MAG_INT_CTRL_YINT_ENABLE \ + 0x40 +#define LSM303D_MAG_INT_CTRL_ZINT_M \ + 0x20 // Enable interrupt recognition on + // Z-axis for magnetic data. +#define LSM303D_MAG_INT_CTRL_ZINT_ENABLE \ + 0x20 +#define LSM303D_MAG_INT_CTRL_PINCFG_M \ + 0x10 // interrupt pin drive + // configuration +#define LSM303D_MAG_INT_CTRL_PINCFG_PUSHPULL \ + 0x00 +#define LSM303D_MAG_INT_CTRL_PINCFG_OPENDRAIN \ + 0x10 +#define LSM303D_MAG_INT_CTRL_POLARITY_M \ + 0x08 // interrupt polarity +#define LSM303D_MAG_INT_CTRL_POLARITY_LOW \ + 0x00 +#define LSM303D_MAG_INT_CTRL_POLARITY_HIGH \ + 0x08 +#define LSM303D_MAG_INT_CTRL_LATCH_M \ + 0x04 // latch interrupt request +#define LSM303D_MAG_INT_CTRL_LATCH_ENABLE \ + 0x04 +#define LSM303D_MAG_INT_CTRL_4D_M \ + 0x02 // 4D detection on acceleration + // data is enabled when 6D bit in + // IG_CFG1 +#define LSM303D_MAG_INT_CTRL_4D_ENABLE \ + 0x02 +#define LSM303D_MAG_INT_CTRL_MI_M \ + 0x01 // Interrupt generation for + // magnetic data +#define LSM303D_MAG_INT_CTRL_MI_ENABLE \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_MAG_INT_SRC +// register. +// +//***************************************************************************** +#define LSM303D_MAG_INT_SRC_M_PTH_X_M \ + 0x80 // Magnetic value on X-axis exceeds + // the threshold on the positive + // side. +#define LSM303D_MAG_INT_SRC_M_PTH_X_ACTIVE \ + 0x80 +#define LSM303D_MAG_INT_SRC_M_PTH_Y_M \ + 0x40 // Magnetic value on Y-axis exceeds + // the threshold on the positive + // side. +#define LSM303D_MAG_INT_SRC_M_PTH_Y_ACTIVE \ + 0x40 +#define LSM303D_MAG_INT_SRC_M_PTH_Z_M \ + 0x20 // Magnetic value on Z-axis exceeds + // the threshold on the positive + // side. +#define LSM303D_MAG_INT_SRC_M_PTH_Z_ACTIVE \ + 0x20 +#define LSM303D_MAG_INT_SRC_M_NTH_X_M \ + 0x10 // Magnetic value on X-axis exceeds + // the threshold on the negative + // side. +#define LSM303D_MAG_INT_SRC_M_NTH_X_ACTIVE \ + 0x10 +#define LSM303D_MAG_INT_SRC_M_NTH_Y_M \ + 0x08 // Magnetic value on Y-axis exceeds + // the threshold on the negative + // side. +#define LSM303D_MAG_INT_SRC_M_NTH_Y_ACTIVE \ + 0x08 +#define LSM303D_MAG_INT_SRC_M_NTH_Z_M \ + 0x04 // Magnetic value on Z-axis exceeds + // the threshold on the negative + // side. +#define LSM303D_MAG_INT_SRC_M_NTH_Z_ACTIVE \ + 0x04 +#define LSM303D_MAG_INT_SRC_MROI_M \ + 0x02 // Internal measurement range + // overflow on magnetic value. +#define LSM303D_MAG_INT_SRC_MROI_ACTIVE \ + 0x02 +#define LSM303D_MAG_INT_SRC_MINT_M \ + 0x01 // Magnetic interrupt event. The + // magnetic field value exceeds the + // threshold. +#define LSM303D_MAG_INT_SRC_MINT_ACTIVE \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CTRL0 +// register. +// +//***************************************************************************** +#define LSM303D_CTRL0_BOOT_M 0x80 // Reboot memory content. +#define LSM303D_CTRL0_BOOT_REBOOT \ + 0x80 +#define LSM303D_CTRL0_FIFO_M 0x40 // FIFO enable. +#define LSM303D_CTRL0_FIFO_ENABLE \ + 0x40 +#define LSM303D_CTRL0_FTH_M 0x20 // FIFO programmable threshold + // enable. +#define LSM303D_CTRL0_FTH_ENABLE \ + 0x20 +#define LSM303D_CTRL0_HPCLICK_M 0x04 // High-pass filter enabled for + // click function. +#define LSM303D_CTRL0_HPCLICK_ENABLE \ + 0x04 +#define LSM303D_CTRL0_HPIS1_M 0x02 // High-pass filter enabled for + // interrupt generator 1 +#define LSM303D_CTRL0_HPIS1_ENABLE \ + 0x02 +#define LSM303D_CTRL0_HPIS2_M 0x01 // High-pass filter enabled for + // interrupt generator 2 +#define LSM303D_CTRL0_HPIS2_ENABLE \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CTRL1 +// register. +// +//***************************************************************************** +#define LSM303D_CTRL1_AODR_M 0xF0 // accel output data rate selection +#define LSM303D_CTRL1_AODR_PD 0x00 // Power-down mode +#define LSM303D_CTRL1_AODR_3_125HZ \ + 0x10 +#define LSM303D_CTRL1_AODR_6_2HZ \ + 0x20 +#define LSM303D_CTRL1_AODR_12_5HZ \ + 0x30 +#define LSM303D_CTRL1_AODR_25HZ 0x40 +#define LSM303D_CTRL1_AODR_50HZ 0x50 +#define LSM303D_CTRL1_AODR_100HZ \ + 0x60 +#define LSM303D_CTRL1_AODR_200HZ \ + 0x70 +#define LSM303D_CTRL1_AODR_400HZ \ + 0x80 +#define LSM303D_CTRL1_AODR_800HZ \ + 0x90 +#define LSM303D_CTRL1_AODR_1600HZ \ + 0xA0 +#define LSM303D_CTRL1_BDU_M 0x08 // Block data update for + // acceleration and magnetic data. + // (0: continuous update; 1: output + // registers not updated until MSB + // and LSB have been read), default + // continuous +#define LSM303D_CTRL1_BDU_CONTINUOUS \ + 0x00 +#define LSM303D_CTRL1_BDU_BLOCK 0x08 +#define LSM303D_CTRL1_AXIS_M 0x7 // Axis power control +#define LSM303D_CTRL1_AXIS_Y_EN 0x01 // Y-axis enable +#define LSM303D_CTRL1_AXIS_X_EN 0x02 // X-axis enable +#define LSM303D_CTRL1_AXIS_Z_EN 0x04 // Z-axis enable +#define LSM303D_CTRL1_AODR_S 4 +#define LSM303D_CTRL1_AXIS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CTRL2 +// register. +// +//***************************************************************************** +#define LSM303D_CTRL2_AFS_M 0x38 // Acceleration full-scale + // selection. +#define LSM303D_CTRL2_AFS_2G 0x00 // +/- 2G sensitivity +#define LSM303D_CTRL2_AFS_4G 0x08 // +/- 4G sensitivity +#define LSM303D_CTRL2_AFS_6G 0x10 // +/- 6G sensitivity +#define LSM303D_CTRL2_AFS_8G 0x18 // +/- 8G sensitivity +#define LSM303D_CTRL2_AFS_16G 0x40 // +/- 16G sensitivity +#define LSM303D_CTRL2_ABW_M 0xC // anti-alias filter bandwidth +#define LSM303D_CTRL2_ABW_773HZ 0x00 +#define LSM303D_CTRL2_ABW_194HZ 0x40 +#define LSM303D_CTRL2_ABW_362HZ 0x80 +#define LSM303D_CTRL2_ABW_50HZ 0xC0 +#define LSM303D_CTRL2_AST_M 0x02 // Acceleration self-test enable. +#define LSM303D_CTRL2_AST_ENABLE \ + 0x02 +#define LSM303D_CTRL2_SIM_M 0x01 // SPI Serial Interface mode + // selection. (default: 4 wire) +#define LSM303D_CTRL2_SIM_4WIRE 0x00 +#define LSM303D_CTRL2_SIM_3WIRE 0x01 +#define LSM303D_CTRL2_ABW_S 6 +#define LSM303D_CTRL2_AFS_S 3 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CTRL3 +// register. +// +//***************************************************************************** +#define LSM303D_CTRL3_INT1_BOOT_M \ + 0x80 // Boot on INT1 enable +#define LSM303D_CTRL3_INT1_BOOT_EN \ + 0x80 +#define LSM303D_CTRL3_INT1_CLICK_M \ + 0x40 // Click generator interrupt on + // INT1. +#define LSM303D_CTRL3_INT1_CLICK_EN \ + 0x40 +#define LSM303D_CTRL3_INT1_IG1_M \ + 0x20 // Inertial interrupt generator 1 + // on INT1 +#define LSM303D_CTRL3_INT1_IG1_EN \ + 0x20 +#define LSM303D_CTRL3_INT1_IG2_M \ + 0x10 // Inertial interrupt generator 2 + // on INT1 +#define LSM303D_CTRL3_INT1_IG2_EN \ + 0x10 +#define LSM303D_CTRL3_INT1_IGM_M \ + 0x08 // Magnetic interrupt generator on + // INT1 +#define LSM303D_CTRL3_INT1_IGM_EN \ + 0x08 +#define LSM303D_CTRL3_INT1_ACCEL_DRDY_M \ + 0x04 // Accelerometer data-ready signal + // on INT1 +#define LSM303D_CTRL3_INT1_ACCEL_DRDY_EN \ + 0x04 +#define LSM303D_CTRL3_INT1_MAG_DRDY_M \ + 0x02 // Magnetometer data-ready signal + // on INT1. +#define LSM303D_CTRL3_INT1_MAG_DRDY_EN \ + 0x02 +#define LSM303D_CTRL3_INT1_EMPTY_M \ + 0x01 // FIFO empty indication on INT1 +#define LSM303D_CTRL3_INT1_EMPTY_EN \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CTRL4 +// register. +// +//***************************************************************************** +#define LSM303D_CTRL4_INT2_CLICK_M \ + 0x80 // Click generator interrupt on + // INT2 +#define LSM303D_CTRL4_INT2_CLICK_EN \ + 0x80 +#define LSM303D_CTRL4_INT2_IG1_M \ + 0x40 // Inertial interrupt generator 1 + // on INT2 +#define LSM303D_CTRL4_INT2_IG1_EN \ + 0x40 +#define LSM303D_CTRL4_INT2_IG2_M \ + 0x20 // Inertial interrupt generator 2 + // on INT2 +#define LSM303D_CTRL4_INT2_IG2_EN \ + 0x20 +#define LSM303D_CTRL4_INT2_IGM_M \ + 0x10 // Magnetic interrupt generator on + // INT2 +#define LSM303D_CTRL4_INT2_IGM_EN \ + 0x10 +#define LSM303D_CTRL4_INT2_ACCEL_DRDY_M \ + 0x08 // Accelerometer data-ready signal + // on INT2 +#define LSM303D_CTRL4_INT2_ACCEL_DRDY_EN \ + 0x08 +#define LSM303D_CTRL4_INT2_MAG_DRDY_M \ + 0x04 // Magnetometer data-ready signal + // on INT2 +#define LSM303D_CTRL4_INT2_MAG_DRDY_EN \ + 0x04 +#define LSM303D_CTRL4_INT2_OVR_M \ + 0x02 // FIFO overrun interrupt on INT2 +#define LSM303D_CTRL4_INT2_OVR_EN \ + 0x02 +#define LSM303D_CTRL4_INT2_FTH_M \ + 0x01 // FIFO threshold interrupt on INT2 +#define LSM303D_CTRL4_INT2_FTH_EN \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CTRL5 +// register. +// +//***************************************************************************** +#define LSM303D_CTRL5_TEMP_M 0x80 // Temperature sensor enable. +#define LSM303D_CTRL5_TEMP_EN 0x80 +#define LSM303D_CTRL5_MRES_M 0x60 // Magnetic resolution selection +#define LSM303D_CTRL5_MRES_LOW 0x00 // low resolution +#define LSM303D_CTRL5_MRES_HIGH 0x60 // high resolution +#define LSM303D_CTRL5_MODR_M 0x1C // mag output data rate selection +#define LSM303D_CTRL5_MODR_3_125HZ \ + 0x00 +#define LSM303D_CTRL5_MODR_6_2HZ \ + 0x04 +#define LSM303D_CTRL5_MODR_12_5HZ \ + 0x08 +#define LSM303D_CTRL5_MODR_25HZ 0x0C +#define LSM303D_CTRL5_MODR_50HZ 0x10 +#define LSM303D_CTRL5_MODR_100HZ \ + 0x14 +#define LSM303D_CTRL5_LIR2_M 0x02 // latch interrupt request on int2 +#define LSM303D_CTRL5_LIR2_EN 0x02 +#define LSM303D_CTRL5_LIR1_M 0x01 // latch interrupt request on int1 +#define LSM303D_CTRL5_LIR1_EN 0x01 +#define LSM303D_CTRL5_MRES_S 5 +#define LSM303D_CTRL5_MODR_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CTRL6 +// register. +// +//***************************************************************************** +#define LSM303D_CTRL6_MFS_M 0x60 // magnetic full scale select +#define LSM303D_CTRL6_MFS_2G 0x00 // +/- 2 gauss +#define LSM303D_CTRL6_MFS_4G 0x20 // +/- 4 gauss +#define LSM303D_CTRL6_MFS_8G 0x40 // +/- 8 gauss +#define LSM303D_CTRL6_MFS_12G 0x60 // +/- 16 gauss +#define LSM303D_CTRL6_MFS_S 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CTRL7 +// register. +// +//***************************************************************************** +#define LSM303D_CTRL7_AHPM_M 0xC0 // High-pass filter mode selection + // for acceleration data +#define LSM303D_CTRL7_AHPM_NORMAL \ + 0x00 +#define LSM303D_CTRL7_AHPM_REFERENCE \ + 0x40 +#define LSM303D_CTRL7_AHPM_AUTORESET \ + 0xC0 +#define LSM303D_CTRL7_AFDS_M 0x20 // default: internal filter + // bypassed +#define LSM303D_CTRL7_AFDS_BYPASSED \ + 0x00 +#define LSM303D_CTRL7_AFDS_FILTERED \ + 0x20 +#define LSM303D_CTRL7_TEMP_ONLY_M \ + 0x10 // Temperature sensor only mode, + // mag off +#define LSM303D_CTRL7_TEMP_ONLY_EN \ + 0x10 +#define LSM303D_CTRL7_MLP_M 0x04 // Magnetic data low-power mode. If + // this bit is 1, the M_ODR [2:0] + // is set to 3.125 Hz independently + // from the MODR settings. +#define LSM303D_CTRL7_MLP_NORMAL \ + 0x00 +#define LSM303D_CTRL7_MLP_LOWPOWER \ + 0x04 +#define LSM303D_CTRL7_MD_M 0x3 // Magnetic sensor mode selection +#define LSM303D_CTRL7_MD_CONTINUOUS \ + 0x00 +#define LSM303D_CTRL7_MD_SINGLE 0x01 +#define LSM303D_CTRL7_MD_POWERDOWN \ + 0x02 +#define LSM303D_CTRL7_AHPM_S 6 +#define LSM303D_CTRL7_MD_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_STATUS +// register. +// +//***************************************************************************** +#define LSM303D_STATUS_OR_M 0xF0 // Accel Axis data overrun +#define LSM303D_STATUS_OR_X 0x10 // Accel X-axis data overrun +#define LSM303D_STATUS_OR_Y 0x20 // Accel Y-axis data overrun +#define LSM303D_STATUS_OR_Z 0x40 // Accel Z-axis data overrun +#define LSM303D_STATUS_OR_ZYX 0x80 // Accel X, Y, and X data overrun +#define LSM303D_STATUS_DA_M 0xF // Accel data available +#define LSM303D_STATUS_DA_X 0x01 // Accel X-axis data available +#define LSM303D_STATUS_DA_Y 0x02 // Accel Y-axis data available +#define LSM303D_STATUS_DA_Z 0x04 // Accel Z-axis data available +#define LSM303D_STATUS_DA_ZYX 0x08 // Accel X, Y, and X data available +#define LSM303D_STATUS_OR_S 4 +#define LSM303D_STATUS_DA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_FIFO_CTRL +// register. +// +//***************************************************************************** +#define LSM303D_FIFO_CTRL_MODE_M \ + 0xE0 // FIFO mode setting +#define LSM303D_FIFO_CTRL_MODE_BYPASS \ + 0x00 // Bypass mode +#define LSM303D_FIFO_CTRL_MODE_FIFO \ + 0x20 // FIFO mode +#define LSM303D_FIFO_CTRL_MODE_STREAM \ + 0x40 // Stream mode +#define LSM303D_FIFO_CTRL_MODE_S2F \ + 0x60 // Stream-to-FIFO mode +#define LSM303D_FIFO_CTRL_MODE_B2S \ + 0x80 // Bypass-to-stream mode +#define LSM303D_FIFO_CTRL_THRESH_M \ + 0x1F // FIFO Threshold setting +#define LSM303D_FIFO_CTRL_MODE_S \ + 5 +#define LSM303D_FIFO_CTRL_THRESH_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_FIFO_SRC +// register. +// +//***************************************************************************** +#define LSM303D_FIFO_SRC_FTH_M 0x80 // FIFO threshold is greater than + // or equal to level or less than + // level +#define LSM303D_FIFO_SRC_FTH_LT 0x00 +#define LSM303D_FIFO_SRC_FTH_GEQ \ + 0x80 +#define LSM303D_FIFO_SRC_OVRN_M 0x40 // overrun status bit +#define LSM303D_FIFO_SRC_OVRN_FILLED \ + 0x40 +#define LSM303D_FIFO_SRC_EMPTY_M \ + 0x20 // FIFO empty +#define LSM303D_FIFO_SRC_EMPTY_EMPTY \ + 0x20 +#define LSM303D_FIFO_SRC_STORE_SAMPLES_M \ + 0x1F // FIFO stored data level of the + // unread samples +#define LSM303D_FIFO_SRC_STORE_SAMPLES_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_INT1_CFG +// register. +// +//***************************************************************************** +#define LSM303D_INT1_CFG_ANDOR_M \ + 0x80 // AND/OR combination of Interrupt + // events; default value: 0 +#define LSM303D_INT1_CFG_ANDOR_OR \ + 0x00 +#define LSM303D_INT1_CFG_ANDOR_AND \ + 0x80 +#define LSM303D_INT1_CFG_6D_M 0x40 // 6-direction function enabled +#define LSM303D_INT1_CFG_6D_EN 0x40 +#define LSM303D_INT1_CFG_ZHI_M 0x20 // enable interrupt generation on + // Z-hi event +#define LSM303D_INT1_CFG_ZHI_EN 0x20 +#define LSM303D_INT1_CFG_ZUPE_M 0x20 // enable interrupt generation on + // Z-hi event +#define LSM303D_INT1_CFG_ZUPE_EN \ + 0x20 +#define LSM303D_INT1_CFG_ZDOWNE_M \ + 0x10 // enable interrupt generation on + // Z-low event +#define LSM303D_INT1_CFG_ZDOWNE_EN \ + 0x10 +#define LSM303D_INT1_CFG_ZLI_M 0x10 // enable interrupt generation on + // Z-low event +#define LSM303D_INT1_CFG_ZLI_EN 0x10 +#define LSM303D_INT1_CFG_YUPE_M 0x08 // enable interrupt generation on + // Y-hi event +#define LSM303D_INT1_CFG_YUPE_EN \ + 0x08 +#define LSM303D_INT1_CFG_YHI_M 0x08 // enable interrupt generation on + // Y-hi event +#define LSM303D_INT1_CFG_YHI_EN 0x08 +#define LSM303D_INT1_CFG_YDOWNE_M \ + 0x04 // enable interrupt generation on + // Y-low event +#define LSM303D_INT1_CFG_YDOWNE_EN \ + 0x04 +#define LSM303D_INT1_CFG_YLI_M 0x04 // enable interrupt generation on + // Y-low event +#define LSM303D_INT1_CFG_YLI_EN 0x04 +#define LSM303D_INT1_CFG_XUPE_M 0x02 // enable interrupt generation on + // X-hi event +#define LSM303D_INT1_CFG_XUPE_EN \ + 0x02 +#define LSM303D_INT1_CFG_XHI_M 0x02 // enable interrupt generation on + // X-hi event +#define LSM303D_INT1_CFG_XHI_EN 0x02 +#define LSM303D_INT1_CFG_XDOWNE_M \ + 0x01 // enable interrupt generation on + // X-low event +#define LSM303D_INT1_CFG_XDOWNE_EN \ + 0x01 +#define LSM303D_INT1_CFG_XLI_M 0x01 // enable interrupt generation on + // X-low event +#define LSM303D_INT1_CFG_XLI_EN 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_INT1_SRC +// register. +// +//***************************************************************************** +#define LSM303D_INT1_SRC_ZERO_M 0x80 // This bit must be zero +#define LSM303D_INT1_SRC_ZERO_ZERO \ + 0x00 +#define LSM303D_INT1_SRC_ZERO_INVALID \ + 0x80 +#define LSM303D_INT1_SRC_IA_M 0x40 // interrupt active +#define LSM303D_INT1_SRC_IA_ACTIVE \ + 0x40 +#define LSM303D_INT1_SRC_ZH_M 0x20 // Z-Hi event occurred +#define LSM303D_INT1_SRC_ZH_OCCURRED \ + 0x20 +#define LSM303D_INT1_SRC_ZL_M 0x10 // Z-Low event occurred +#define LSM303D_INT1_SRC_ZL_OCCURRED \ + 0x10 +#define LSM303D_INT1_SRC_YH_M 0x08 // Y-Hi event occurred +#define LSM303D_INT1_SRC_YH_OCCURRED \ + 0x08 +#define LSM303D_INT1_SRC_YL_M 0x04 // Y-Low event occurred +#define LSM303D_INT1_SRC_YL_OCCURRED \ + 0x04 +#define LSM303D_INT1_SRC_XH_M 0x02 // X-Hi event occurred +#define LSM303D_INT1_SRC_XH_OCCURRED \ + 0x02 +#define LSM303D_INT1_SRC_XL_M 0x01 // X-Low event occurred +#define LSM303D_INT1_SRC_XL_OCCURRED \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_INT1_THS +// register. +// +//***************************************************************************** +#define LSM303D_INT1_THS_ZERO_M 0x80 // This bit must be zero +#define LSM303D_INT1_THS_ZERO_ZERO \ + 0x00 +#define LSM303D_INT1_THS_ZERO_INVALID \ + 0x80 +#define LSM303D_INT1_THS_THS_M 0x7F // THS[6-0] Interrupt threshold, + // default 0x0 +#define LSM303D_INT1_THS_THS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_INT1_DURATION +// register. +// +//***************************************************************************** +#define LSM303D_INT1_DURATION_ZERO_M \ + 0x80 // This bit must be zero +#define LSM303D_INT1_DURATION_ZERO_ZERO \ + 0x00 +#define LSM303D_INT1_DURATION_ZERO_INVALID \ + 0x80 +#define LSM303D_INT1_DURATION_DURATION_M \ + 0x7F // Duration D[6-0] +#define LSM303D_INT1_DURATION_DURATION_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_INT2_CFG +// register. +// +//***************************************************************************** +#define LSM303D_INT2_CFG_ANDOR_M \ + 0x80 // AND/OR combination of Interrupt + // events; default value: 0 +#define LSM303D_INT2_CFG_ANDOR_OR \ + 0x00 +#define LSM303D_INT2_CFG_ANDOR_AND \ + 0x80 +#define LSM303D_INT2_CFG_6D_M 0x40 // 6-direction function enabled +#define LSM303D_INT2_CFG_6D_EN 0x40 +#define LSM303D_INT2_CFG_ZHI_M 0x20 // enable interrupt generation on + // Z-hi event +#define LSM303D_INT2_CFG_ZHI_EN 0x20 +#define LSM303D_INT2_CFG_ZLI_M 0x10 // enable interrupt generation on + // Z-low event +#define LSM303D_INT2_CFG_ZLI_EN 0x10 +#define LSM303D_INT2_CFG_YHI_M 0x08 // enable interrupt generation on + // Y-hi event +#define LSM303D_INT2_CFG_YHI_EN 0x08 +#define LSM303D_INT2_CFG_YLI_M 0x04 // enable interrupt generation on + // Y-low event +#define LSM303D_INT2_CFG_YLI_EN 0x04 +#define LSM303D_INT2_CFG_XHI_M 0x02 // enable interrupt generation on + // X-hi event +#define LSM303D_INT2_CFG_XHI_EN 0x02 +#define LSM303D_INT2_CFG_XLI_M 0x01 // enable interrupt generation on + // X-low event +#define LSM303D_INT2_CFG_XLI_EN 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_INT2_SRC +// register. +// +//***************************************************************************** +#define LSM303D_INT2_SRC_ZERO_M 0x80 // This bit must be zero +#define LSM303D_INT2_SRC_ZERO_ZERO \ + 0x00 +#define LSM303D_INT2_SRC_ZERO_INVALID \ + 0x80 +#define LSM303D_INT2_SRC_IA_M 0x40 // interrupt active +#define LSM303D_INT2_SRC_IA_ACTIVE \ + 0x40 +#define LSM303D_INT2_SRC_ZH_M 0x20 // Z-Hi event occurred +#define LSM303D_INT2_SRC_ZH_OCCURRED \ + 0x20 +#define LSM303D_INT2_SRC_ZL_M 0x10 // Z-Low event occurred +#define LSM303D_INT2_SRC_ZL_OCCURRED \ + 0x10 +#define LSM303D_INT2_SRC_YH_M 0x08 // Y-Hi event occurred +#define LSM303D_INT2_SRC_YH_OCCURRED \ + 0x08 +#define LSM303D_INT2_SRC_YL_M 0x04 // Y-Low event occurred +#define LSM303D_INT2_SRC_YL_OCCURRED \ + 0x04 +#define LSM303D_INT2_SRC_XH_M 0x02 // X-Hi event occurred +#define LSM303D_INT2_SRC_XH_OCCURRED \ + 0x02 +#define LSM303D_INT2_SRC_XL_M 0x01 // X-Low event occurred +#define LSM303D_INT2_SRC_XL_OCCURRED \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_INT2_THS +// register. +// +//***************************************************************************** +#define LSM303D_INT2_THS_ZERO_M 0x80 // This bit must be zero +#define LSM303D_INT2_THS_ZERO_ZERO \ + 0x00 +#define LSM303D_INT2_THS_ZERO_INVALID \ + 0x80 +#define LSM303D_INT2_THS_THS_M 0x7F // THS[6-0] Interrupt threshold, + // default 0x0 +#define LSM303D_INT2_THS_THS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_INT2_DURATION +// register. +// +//***************************************************************************** +#define LSM303D_INT2_DURATION_ZERO_M \ + 0x80 // This bit must be zero +#define LSM303D_INT2_DURATION_ZERO_ZERO \ + 0x00 +#define LSM303D_INT2_DURATION_ZERO_INVALID \ + 0x80 +#define LSM303D_INT2_DURATION_DURATION_M \ + 0x7F // Duration D[6-0] +#define LSM303D_INT2_DURATION_DURATION_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CLICK_CFG +// register. +// +//***************************************************************************** +#define LSM303D_CLICK_CFG_ZD_M 0x20 // Enable interrupt double click on + // Z axis +#define LSM303D_CLICK_CFG_ZD_DIS \ + 0x00 +#define LSM303D_CLICK_CFG_ZD_EN 0x20 +#define LSM303D_CLICK_CFG_ZS_M 0x10 // Enable interrupt single click on + // Z axis +#define LSM303D_CLICK_CFG_ZS_DIS \ + 0x00 +#define LSM303D_CLICK_CFG_ZS_EN 0x10 +#define LSM303D_CLICK_CFG_YD_M 0x08 // Enable interrupt double click on + // Y axis +#define LSM303D_CLICK_CFG_YD_DIS \ + 0x00 +#define LSM303D_CLICK_CFG_YD_EN 0x08 +#define LSM303D_CLICK_CFG_YS_M 0x04 // Enable interrupt single click on + // Y axis +#define LSM303D_CLICK_CFG_YS_DIS \ + 0x00 +#define LSM303D_CLICK_CFG_YS_EN 0x04 +#define LSM303D_CLICK_CFG_XD_M 0x02 // Enable interrupt double click on + // X axis +#define LSM303D_CLICK_CFG_XD_DIS \ + 0x00 +#define LSM303D_CLICK_CFG_XD_EN 0x02 +#define LSM303D_CLICK_CFG_XS_M 0x01 // Enable interrupt single click on + // X axis +#define LSM303D_CLICK_CFG_XS_DIS \ + 0x00 +#define LSM303D_CLICK_CFG_XS_EN 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CLICK_SRC +// register. +// +//***************************************************************************** +#define LSM303D_CLICK_SRC_IA_M 0x40 // Interrupt pending +#define LSM303D_CLICK_SRC_IA_NONE \ + 0x00 +#define LSM303D_CLICK_SRC_IA_PENDING \ + 0x40 +#define LSM303D_CLICK_SRC_DCLICK_M \ + 0x20 // double click-click enable +#define LSM303D_CLICK_SRC_DCLICK_DIS \ + 0x00 +#define LSM303D_CLICK_SRC_DCLICK_EN \ + 0x20 +#define LSM303D_CLICK_SRC_SCLICK_M \ + 0x10 // single click-click enable +#define LSM303D_CLICK_SRC_SCLICK_DIS \ + 0x00 +#define LSM303D_CLICK_SRC_SCLICK_EN \ + 0x10 +#define LSM303D_CLICK_SRC_SIGN_M \ + 0x08 // click-click sign +#define LSM303D_CLICK_SRC_SIGN_POSITIVE \ + 0x00 +#define LSM303D_CLICK_SRC_SIGN_NEGATIVE \ + 0x08 +#define LSM303D_CLICK_SRC_AXIS_M \ + 0x7 // Axis click detection +#define LSM303D_CLICK_SRC_AXIS_X \ + 0x01 // X click-click detection +#define LSM303D_CLICK_SRC_AXIS_Y \ + 0x02 // Y click-click detection +#define LSM303D_CLICK_SRC_AXIS_Z \ + 0x04 // Z click-click detection +#define LSM303D_CLICK_SRC_AXIS_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_CLICK_THS +// register. +// +//***************************************************************************** +#define LSM303D_CLICK_THS_THS_M 0x7F // Threshold; 1 LSB = full-scale / + // 128; THS6 through THS0 define + // the threshold which is used by + // the system to start the click + // detection procedure; the + // threshold value is expressed + // over 7 bits as an unsigned + // number +#define LSM303D_CLICK_THS_THS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_TIME_LIMIT +// register. +// +//***************************************************************************** +#define LSM303D_TIME_LIMIT_TLI_M \ + 0x7F // Time Limit; 1 LSB = 1/ODR; TLI7 + // through TLI0 define the maximum + // time interval that can elapse + // between the start of the click + // detection procedure (the + // acceleration on the selected + // channel exceeds the programmed + // threshold) and when the + // acceleration goes back below the + // threshold +#define LSM303D_TIME_LIMIT_TLI_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_ACT_THS +// register. +// +//***************************************************************************** +#define LSM303D_ACT_THS_THRESHOLD_M \ + 0x7F +#define LSM303D_ACT_THS_THRESHOLD_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303D_O_ACT_DUR +// register. +// +//***************************************************************************** +#define LSM303D_ACT_DUR_THRESHOLD_M \ + 0x7F +#define LSM303D_ACT_DUR_THRESHOLD_S \ + 0 + +#endif // __SENSORLIB_HW_LSM303D_H__ diff --git a/sensorlib/hw_lsm303dlhc.h b/sensorlib/hw_lsm303dlhc.h new file mode 100644 index 0000000..06cf9ba --- /dev/null +++ b/sensorlib/hw_lsm303dlhc.h @@ -0,0 +1,1034 @@ +//***************************************************************************** +// +// hw_lsm303dlhc.h - Macros used when accessing the ST LSM303DLHC accel/mag +// combo +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_LSM303DLHC_H__ +#define __SENSORLIB_HW_LSM303DLHC_H__ + +//***************************************************************************** +// +// The following are defines for the LSM303DLHC register addresses +// +//***************************************************************************** +#define LSM303DLHC_O_MAG_CRA 0x0 // Magnetometer control +#define LSM303DLHC_O_MAG_CRB 0x01 // Gain configuration +#define LSM303DLHC_O_MAG_MR 0x02 // Mode configuration +#define LSM303DLHC_O_MAG_OUT_X_MSB \ + 0x03 // X-axis MSB +#define LSM303DLHC_O_MAG_OUT_X_LSB \ + 0x04 // X-axis LSB +#define LSM303DLHC_O_MAG_OUT_Y_MSB \ + 0x05 // Y-axis MSB +#define LSM303DLHC_O_MAG_OUT_Y_LSB \ + 0x06 // Y-axis LSB +#define LSM303DLHC_O_MAG_OUT_Z_MSB \ + 0x07 // Z-axis MSB +#define LSM303DLHC_O_MAG_OUT_Z_LSB \ + 0x08 // Z-axis LSB +#define LSM303DLHC_O_MAG_SR 0x09 // Status register +#define LSM303DLHC_O_MAG_IRA 0x0A +#define LSM303DLHC_O_MAG_IRB 0x0B +#define LSM303DLHC_O_MAG_IRC 0x0C +#define LSM303DLHC_O_CTRL1 0x20 // Control 1 - power settings +#define LSM303DLHC_O_CTRL2 0x21 // Control 2 +#define LSM303DLHC_O_CTRL3 0x22 // Control 3 +#define LSM303DLHC_O_CTRL4 0x23 // Control 4 +#define LSM303DLHC_O_CTRL5 0x24 // Control 5 +#define LSM303DLHC_O_CTRL6 0x25 // Control 6 +#define LSM303DLHC_O_REFERENCE 0x26 // Reference/Datacapture_A +#define LSM303DLHC_O_STATUS 0x27 // Status register +#define LSM303DLHC_O_OUT_X_LSB 0x28 // X-axis LSB +#define LSM303DLHC_O_OUT_X_MSB 0x29 // X-axis MSB +#define LSM303DLHC_O_OUT_Y_LSB 0x2A // Y-axis LSB +#define LSM303DLHC_O_OUT_Y_MSB 0x2B // Y-axis MSB +#define LSM303DLHC_O_OUT_Z_LSB 0x2C // Z-axis LSB +#define LSM303DLHC_O_OUT_Z_MSB 0x2D // Z-axis MSB +#define LSM303DLHC_O_FIFO_CTRL 0x2E // FIFO control +#define LSM303DLHC_O_FIFO_SRC 0x2F // FIFO_SRC register +#define LSM303DLHC_O_INT1_CFG_A 0x30 // INT1 interrupt generation; this + // register only writable after + // boot +#define LSM303DLHC_O_INT1_SRC_A 0x31 // interrupt source register (read + // only) +#define LSM303DLHC_O_MAG_TEMP_OUT_MSB \ + 0x31 // Temperature bits 11-4 +#define LSM303DLHC_O_MAG_TEMP_OUT_LSB \ + 0x32 // Temperature bits 3-0 +#define LSM303DLHC_O_INT1_THS_A 0x32 // Interrupt 1 threshold +#define LSM303DLHC_O_INT1_DURATION_A \ + 0x33 // INT1 duration register +#define LSM303DLHC_O_INT2_CFG_A 0x34 // INT2 interrupt generation; this + // register only writable after + // boot +#define LSM303DLHC_O_INT2_SRC_A 0x35 // INT2 source register (read only) +#define LSM303DLHC_O_INT2_THS_A 0x36 // INT2 threshold +#define LSM303DLHC_O_INT2_DURATION_A \ + 0x37 // INT2 duration register +#define LSM303DLHC_O_CLICK_CFG_A \ + 0x38 // Click config A register +#define LSM303DLHC_O_CLICK_SRC_A \ + 0x39 // Click source A +#define LSM303DLHC_O_CLICK_THS_A \ + 0x3A // click-click threshold +#define LSM303DLHC_O_TIME_LIMIT_A \ + 0x3B // Time Limit A register +#define LSM303DLHC_O_TIME_LATENCY_A \ + 0x3C // Time Latency A register; 1 LSB = + // 1/ODR; TLA7 through TLA0 define + // the time interval that starts + // after the first click detection + // where the click detection + // procedure is disabled, in cases + // where the device is configured + // for double click detection +#define LSM303DLHC_O_TIME_WINDOW_A \ + 0x3D // Time Window A register; 1 LSB = + // 1/ODR; TW7 through TW0 define + // the maximum interval of time + // that can elapse after the end of + // the latency interval in which + // the click detection procedure + // can start, in cases where the + // device is configured for double + // click detection + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_MAG_CRA +// register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_CRA_TEMP_M \ + 0x80 // Temperature sensor enable +#define LSM303DLHC_MAG_CRA_TEMP_DIS \ + 0x00 +#define LSM303DLHC_MAG_CRA_TEMP_EN \ + 0x80 +#define LSM303DLHC_MAG_CRA_DO_M 0x1C // Data output rate +#define LSM303DLHC_MAG_CRA_DO_0_75HZ \ + 0x00 // 0.75 Hz +#define LSM303DLHC_MAG_CRA_DO_1_5HZ \ + 0x04 // 1.5 Hz +#define LSM303DLHC_MAG_CRA_DO_3_0HZ \ + 0x08 // 3.0 Hz +#define LSM303DLHC_MAG_CRA_DO_7_5HZ \ + 0x0C // 7.5 Hz +#define LSM303DLHC_MAG_CRA_DO_15HZ \ + 0x10 // 15 Hz +#define LSM303DLHC_MAG_CRA_DO_30HZ \ + 0x14 // 30 Hz +#define LSM303DLHC_MAG_CRA_DO_75HZ \ + 0x18 // 75 Hz +#define LSM303DLHC_MAG_CRA_DO_220HZ \ + 0x1C // 220 Hz +#define LSM303DLHC_MAG_CRA_DO_S 2 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_MAG_CRB +// register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_CRB_GAIN_M \ + 0xE0 // Gain selection +#define LSM303DLHC_MAG_CRB_GAIN_1_3GAUSS \ + 0x20 // +/- 1.3 gauss, 1100 LSB/gauss +#define LSM303DLHC_MAG_CRB_GAIN_1_9GAUSS \ + 0x40 // +/- 1.9 gauss, 855 LSB/gauss +#define LSM303DLHC_MAG_CRB_GAIN_2_5GAUSS \ + 0x60 // +/- 2.5 gauss, 670 LSB/gauss +#define LSM303DLHC_MAG_CRB_GAIN_4_0GAUSS \ + 0x80 // +/- 4.0 gauss, 450 LSB/guass +#define LSM303DLHC_MAG_CRB_GAIN_4_7GAUSS \ + 0xA0 // +/- 4.7 gauss, 400 LSB/gauss +#define LSM303DLHC_MAG_CRB_GAIN_5_6GAUSS \ + 0xC0 // +/- 5.6 gauss, 330 LSB/gauss +#define LSM303DLHC_MAG_CRB_GAIN_8_1GAUSS \ + 0xE0 // +/- 8.1 gauss, 230 LSB/gauss +#define LSM303DLHC_MAG_CRB_GAIN_S \ + 5 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_MAG_MR +// register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_MR_MODE_M \ + 0x3 // Mode select bits +#define LSM303DLHC_MAG_MR_MODE_CONTINUOUS \ + 0x00 // Continuous conversion mode +#define LSM303DLHC_MAG_MR_MODE_SINGLE \ + 0x01 // Single conversion mode +#define LSM303DLHC_MAG_MR_MODE_SLEEP \ + 0x02 // Sleep mode +#define LSM303DLHC_MAG_MR_MODE_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_MAG_SR +// register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_SR_LOCK_M \ + 0x02 // Data output register lock; once + // a new set of measurements is + // available, this bit is set when + // the first magnetic field data + // register has been read +#define LSM303DLHC_MAG_SR_LOCK_LOCKED \ + 0x02 +#define LSM303DLHC_MAG_SR_DATA_M \ + 0x01 // Data ready bit; this bit is set + // when a new set of measures are + // available +#define LSM303DLHC_MAG_SR_DATA_READ \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_MAG_IRA +// register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_IRA_CONSTANT_M \ + 0xFF +#define LSM303DLHC_MAG_IRA_CONSTANT_VAL \ + 0x48 +#define LSM303DLHC_MAG_IRA_CONSTANT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_MAG_IRB +// register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_IRB_CONSTANT_M \ + 0xFF +#define LSM303DLHC_MAG_IRB_CONSTANT_VAL \ + 0x34 +#define LSM303DLHC_MAG_IRB_CONSTANT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_MAG_IRC +// register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_IRC_CONSTANT_M \ + 0xFF +#define LSM303DLHC_MAG_IRC_CONSTANT_VAL \ + 0x33 +#define LSM303DLHC_MAG_IRC_CONSTANT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CTRL1 +// register. +// +//***************************************************************************** +#define LSM303DLHC_CTRL1_ODR_M 0xF0 // data rate selection +#define LSM303DLHC_CTRL1_ODR_PD 0x00 // Power-down mode +#define LSM303DLHC_CTRL1_ODR_1HZ \ + 0x10 +#define LSM303DLHC_CTRL1_ODR_10HZ \ + 0x20 +#define LSM303DLHC_CTRL1_ODR_25HZ \ + 0x30 +#define LSM303DLHC_CTRL1_ODR_50HZ \ + 0x40 +#define LSM303DLHC_CTRL1_ODR_100HZ \ + 0x50 +#define LSM303DLHC_CTRL1_ODR_200HZ \ + 0x60 +#define LSM303DLHC_CTRL1_ODR_400HZ \ + 0x70 +#define LSM303DLHC_CTRL1_ODR_1620HZ \ + 0x80 // Low power mode +#define LSM303DLHC_CTRL1_ODR_5376HZ \ + 0x90 // 1.344KHz normal, 5.376KHz low + // power +#define LSM303DLHC_CTRL1_POWER_M \ + 0x08 // Power control +#define LSM303DLHC_CTRL1_POWER_LOWPOW \ + 0x00 +#define LSM303DLHC_CTRL1_POWER_NORMAL \ + 0x08 +#define LSM303DLHC_CTRL1_AXIS_M 0x7 // Axis power control +#define LSM303DLHC_CTRL1_AXIS_Y_EN \ + 0x01 // Y-axis enable +#define LSM303DLHC_CTRL1_AXIS_X_EN \ + 0x02 // X-axis enable +#define LSM303DLHC_CTRL1_AXIS_Z_EN \ + 0x04 // Z-axis enable +#define LSM303DLHC_CTRL1_ODR_S 4 +#define LSM303DLHC_CTRL1_AXIS_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CTRL2 +// register. +// +//***************************************************************************** +#define LSM303DLHC_CTRL2_HPMODE_M \ + 0xC0 // high pass filter mode selection +#define LSM303DLHC_CTRL2_HPMODE_NORMAL_RESET \ + 0x00 // normal mode (reset reading + // HP_RESET_FILTER) +#define LSM303DLHC_CTRL2_HPMODE_REFERENCE \ + 0x40 // reference signal for filtering +#define LSM303DLHC_CTRL2_HPMODE_NORMAL \ + 0x80 // Normal mode +#define LSM303DLHC_CTRL2_HPMODE_AUTORESET \ + 0xC0 // autoreset on interrupt event +#define LSM303DLHC_CTRL2_HPCUTOFF_M \ + 0x30 // high pass filter cut-off + // frequency selection +#define LSM303DLHC_CTRL2_FDS_M 0x08 // Filtered data selection +#define LSM303DLHC_CTRL2_FDS_BYPASSED \ + 0x00 +#define LSM303DLHC_CTRL2_FDS_FILTERED \ + 0x08 +#define LSM303DLHC_CTRL2_HPCLICK_M \ + 0x04 // High pass filter enabled for + // CLICK function +#define LSM303DLHC_CTRL2_HPCLICK_BYPASSED \ + 0x00 +#define LSM303DLHC_CTRL2_HPCLICK_FILTERED \ + 0x04 +#define LSM303DLHC_CTRL2_HPIS2_M \ + 0x02 // High pass filter enabled for AOI + // function on Interrupt 2 +#define LSM303DLHC_CTRL2_HPIS2_BYPASSED \ + 0x00 +#define LSM303DLHC_CTRL2_HPIS2_FILTERED \ + 0x02 +#define LSM303DLHC_CTRL2_HPIS1_M \ + 0x01 // High pass filter enabled for AOI + // function on Interrupt 1 +#define LSM303DLHC_CTRL2_HPIS1_BYPASSED \ + 0x00 +#define LSM303DLHC_CTRL2_HPIS1_FILTERED \ + 0x01 +#define LSM303DLHC_CTRL2_HPMODE_S \ + 6 +#define LSM303DLHC_CTRL2_HPCUTOFF_S \ + 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CTRL3 +// register. +// +//***************************************************************************** +#define LSM303DLHC_CTRL3_I1CLICK_M \ + 0x80 // CLICK on INT1 +#define LSM303DLHC_CTRL3_I1CLICK_DIS \ + 0x00 +#define LSM303DLHC_CTRL3_I1CLICK_EN \ + 0x80 +#define LSM303DLHC_CTRL3_I1AOI1_M \ + 0x40 // AOI1 on INT1 +#define LSM303DLHC_CTRL3_I1AOI1_DIS \ + 0x00 +#define LSM303DLHC_CTRL3_I1AOI1_EN \ + 0x40 +#define LSM303DLHC_CTRL3_I1AOI2_M \ + 0x20 // AOI2 on INT1 +#define LSM303DLHC_CTRL3_I1AOI2_DIS \ + 0x00 +#define LSM303DLHC_CTRL3_I1AOI2_EN \ + 0x20 +#define LSM303DLHC_CTRL3_I1DRDY1_M \ + 0x10 // DRDY1 on INT1 +#define LSM303DLHC_CTRL3_I1DRDY1_DIS \ + 0x00 +#define LSM303DLHC_CTRL3_I1DRDY1_EN \ + 0x10 +#define LSM303DLHC_CTRL3_I1DRDY2_M \ + 0x08 // DRDY2 on INT1 +#define LSM303DLHC_CTRL3_I1DRDY2_DIS \ + 0x00 +#define LSM303DLHC_CTRL3_I1DRDY2_EN \ + 0x08 +#define LSM303DLHC_CTRL3_I1WTM_M \ + 0x04 // FIFO watermark interrupt on INT1 +#define LSM303DLHC_CTRL3_I1WTM_DIS \ + 0x00 +#define LSM303DLHC_CTRL3_I1WTM_EN \ + 0x04 +#define LSM303DLHC_CTRL3_I1OVERRUN_M \ + 0x02 // FIFO overrun interrupt on INT1 +#define LSM303DLHC_CTRL3_I1OVERRUN_DIS \ + 0x00 +#define LSM303DLHC_CTRL3_I1OVERRUN_EN \ + 0x02 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CTRL4 +// register. +// +//***************************************************************************** +#define LSM303DLHC_CTRL4_BDU_M 0x80 // Block data update; default + // value: 0 (0: continuous update; + // 1: output registers not updated + // until MSB and LSB reading) +#define LSM303DLHC_CTRL4_BDU_CONTINUOUS \ + 0x00 +#define LSM303DLHC_CTRL4_BDU_MSBLSB \ + 0x80 +#define LSM303DLHC_CTRL4_ENDIAN_M \ + 0x40 // Endian selection +#define LSM303DLHC_CTRL4_ENDIAN_LITTLE \ + 0x00 +#define LSM303DLHC_CTRL4_ENDIAN_BIG \ + 0x40 +#define LSM303DLHC_CTRL4_FS_M 0x30 // full scale selection; default + // value: 0 +#define LSM303DLHC_CTRL4_FS_2G 0x00 +#define LSM303DLHC_CTRL4_FS_4G 0x10 +#define LSM303DLHC_CTRL4_FS_8G 0x20 +#define LSM303DLHC_CTRL4_FS_16G 0x30 +#define LSM303DLHC_CTRL4_RESOLUTION_M \ + 0x08 // resolution output mode +#define LSM303DLHC_CTRL4_RESOLUTION_LOW \ + 0x00 +#define LSM303DLHC_CTRL4_RESOLUTION_HIGH \ + 0x08 +#define LSM303DLHC_CTRL4_SIM_M 0x01 // SPI Serial Interface Mode + // selection (default = 0, 4-wire) +#define LSM303DLHC_CTRL4_SIM_4WIRE \ + 0x00 +#define LSM303DLHC_CTRL4_SIM_3WIRE \ + 0x01 +#define LSM303DLHC_CTRL4_FS_S 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CTRL5 +// register. +// +//***************************************************************************** +#define LSM303DLHC_CTRL5_REBOOTCTL_M \ + 0x80 // Reboot memory conent +#define LSM303DLHC_CTRL5_REBOOTCTL_NORMAL \ + 0x00 +#define LSM303DLHC_CTRL5_REBOOTCTL_REBOOT \ + 0x80 +#define LSM303DLHC_CTRL5_FIFO_M 0x40 // FIFO enable +#define LSM303DLHC_CTRL5_FIFO_DIS \ + 0x00 +#define LSM303DLHC_CTRL5_FIFO_EN \ + 0x40 +#define LSM303DLHC_CTRL5_LIR_INT1_M \ + 0x08 // Latch interrupt on INT1 +#define LSM303DLHC_CTRL5_LIR_INT1_DIS \ + 0x00 +#define LSM303DLHC_CTRL5_LIR_INT1_EN \ + 0x08 +#define LSM303DLHC_CTRL5_D4D_INT1_M \ + 0x04 // 4D Int enable on INT1 +#define LSM303DLHC_CTRL5_D4D_INT1_DIS \ + 0x00 +#define LSM303DLHC_CTRL5_D4D_INT1_EN \ + 0x04 +#define LSM303DLHC_CTRL5_LIR_INT2_M \ + 0x02 // Latch interrupt request on + // INT2_SRC register, with INT2_SRC + // register cleared by reading + // INT2_SRC itself; default value: + // 0 +#define LSM303DLHC_CTRL5_LIR_INT2_DIS \ + 0x00 +#define LSM303DLHC_CTRL5_LIR_INT2_EN \ + 0x02 +#define LSM303DLHC_CTRL5_D4D_INT2_M \ + 0x01 // 4D enable: 4D detection is + // enabled on INT2 when 6D bit on + // INT2_CFG is set to 1 +#define LSM303DLHC_CTRL5_D4D_INT2_DIS \ + 0x00 +#define LSM303DLHC_CTRL5_D4D_INT2_EN \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CTRL6 +// register. +// +//***************************************************************************** +#define LSM303DLHC_CTRL6_I2_CLICK_M \ + 0x80 // CLICK interrupt on PAD2 +#define LSM303DLHC_CTRL6_I2_CLICK_DIS \ + 0x00 +#define LSM303DLHC_CTRL6_I2_CLICK_EN \ + 0x80 +#define LSM303DLHC_CTRL6_I2_INT1_M \ + 0x40 // Interrupt 1 on PAD2; default + // value 0 +#define LSM303DLHC_CTRL6_I2_INT1_DIS \ + 0x00 +#define LSM303DLHC_CTRL6_I2_INT1_EN \ + 0x40 +#define LSM303DLHC_CTRL6_I2_INT2_M \ + 0x20 // Interrupt 2 on PAD2; default + // value 0 +#define LSM303DLHC_CTRL6_I2_INT2_DIS \ + 0x00 +#define LSM303DLHC_CTRL6_I2_INT2_EN \ + 0x20 +#define LSM303DLHC_CTRL6_BOOT_I2_M \ + 0x10 // Reboot memory content on PAD2; + // default value: 0 +#define LSM303DLHC_CTRL6_BOOT_I2_DIS \ + 0x00 +#define LSM303DLHC_CTRL6_BOOT_I2_EN \ + 0x10 +#define LSM303DLHC_CTRL6_P2_ACT_M \ + 0x08 // active function status on PAD2 +#define LSM303DLHC_CTRL6_P2_ACT_DIS \ + 0x00 +#define LSM303DLHC_CTRL6_P2_ACT_EN \ + 0x08 +#define LSM303DLHC_CTRL6_H_LACTIVE_M \ + 0x02 // interrupt active configuration + // on INT; default value 0 (0: + // high; 1:low) +#define LSM303DLHC_CTRL6_H_LACTIVE_HI \ + 0x00 +#define LSM303DLHC_CTRL6_H_LACTIVE_LOW \ + 0x02 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_STATUS +// register. +// +//***************************************************************************** +#define LSM303DLHC_STATUS_OR_M 0xF0 // Axis data overrun +#define LSM303DLHC_STATUS_OR_X 0x10 // X-axis data overrun +#define LSM303DLHC_STATUS_OR_Y 0x20 // Y-axis data overrun +#define LSM303DLHC_STATUS_OR_Z 0x40 // Z-axis data overrun +#define LSM303DLHC_STATUS_OR_ZYX \ + 0x80 // X, Y, and X data overrun +#define LSM303DLHC_STATUS_DA_M 0xF // Axis data available +#define LSM303DLHC_STATUS_DA_X 0x01 // X-axis data available +#define LSM303DLHC_STATUS_DA_Y 0x02 // Y-axis data available +#define LSM303DLHC_STATUS_DA_Z 0x04 // Z-axis data available +#define LSM303DLHC_STATUS_DA_ZYX \ + 0x08 // X, Y, and X data available +#define LSM303DLHC_STATUS_OR_S 4 +#define LSM303DLHC_STATUS_DA_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_FIFO_CTRL +// register. +// +//***************************************************************************** +#define LSM303DLHC_FIFO_CTRL_TR_M \ + 0x20 +#define LSM303DLHC_FIFO_CTRL_TR_INT1 \ + 0x00 +#define LSM303DLHC_FIFO_CTRL_TR_INT2 \ + 0x20 +#define LSM303DLHC_FIFO_CTRL_THRESH_M \ + 0x1F // FIFO Threshold setting +#define LSM303DLHC_FIFO_CTRL_MODE_M \ + 0xC // FIFO mode setting +#define LSM303DLHC_FIFO_CTRL_MODE_BYPASS \ + 0x00 // Bypass mode +#define LSM303DLHC_FIFO_CTRL_MODE_FIFO \ + 0x40 // FIFO mode +#define LSM303DLHC_FIFO_CTRL_MODE_STREAM \ + 0x80 // Stream mode +#define LSM303DLHC_FIFO_CTRL_MODE_TRIGGER \ + 0xC0 // Trigger mode +#define LSM303DLHC_FIFO_CTRL_MODE_S \ + 6 +#define LSM303DLHC_FIFO_CTRL_THRESH_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_FIFO_SRC +// register. +// +//***************************************************************************** +#define LSM303DLHC_FIFO_SRC_FTH_M \ + 0x80 // FIFO threshold is greater than + // or equal to level or less than + // level +#define LSM303DLHC_FIFO_SRC_FTH_LT \ + 0x00 +#define LSM303DLHC_FIFO_SRC_FTH_GEQ \ + 0x80 +#define LSM303DLHC_FIFO_SRC_OVRN_M \ + 0x40 // overrun status bit +#define LSM303DLHC_FIFO_SRC_OVRN_FILLED \ + 0x40 +#define LSM303DLHC_FIFO_SRC_EMPTY_M \ + 0x20 // FIFO empty +#define LSM303DLHC_FIFO_SRC_EMPTY_EMPTY \ + 0x20 +#define LSM303DLHC_FIFO_SRC_STORE_SAMPLES_M \ + 0x1F // FIFO stored data level of the + // unread samples +#define LSM303DLHC_FIFO_SRC_STORE_SAMPLES_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_INT1_CFG_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_INT1_CFG_A_ANDOR_M \ + 0x80 // AND/OR combination of Interrupt + // events; default value: 0 +#define LSM303DLHC_INT1_CFG_A_ANDOR_OR \ + 0x00 +#define LSM303DLHC_INT1_CFG_A_ANDOR_AND \ + 0x80 +#define LSM303DLHC_INT1_CFG_A_6D_M \ + 0x40 // 6-direction function enabled +#define LSM303DLHC_INT1_CFG_A_6D_EN \ + 0x40 +#define LSM303DLHC_INT1_CFG_A_ZHI_M \ + 0x20 // enable interrupt generation on + // Z-hi event +#define LSM303DLHC_INT1_CFG_A_ZHI_EN \ + 0x20 +#define LSM303DLHC_INT1_CFG_A_ZUPE_M \ + 0x20 // enable interrupt generation on + // Z-hi event +#define LSM303DLHC_INT1_CFG_A_ZUPE_EN \ + 0x20 +#define LSM303DLHC_INT1_CFG_A_ZDOWNE_M \ + 0x10 // enable interrupt generation on + // Z-low event +#define LSM303DLHC_INT1_CFG_A_ZDOWNE_EN \ + 0x10 +#define LSM303DLHC_INT1_CFG_A_ZLI_M \ + 0x10 // enable interrupt generation on + // Z-low event +#define LSM303DLHC_INT1_CFG_A_ZLI_EN \ + 0x10 +#define LSM303DLHC_INT1_CFG_A_YUPE_M \ + 0x08 // enable interrupt generation on + // Y-hi event +#define LSM303DLHC_INT1_CFG_A_YUPE_EN \ + 0x08 +#define LSM303DLHC_INT1_CFG_A_YHI_M \ + 0x08 // enable interrupt generation on + // Y-hi event +#define LSM303DLHC_INT1_CFG_A_YHI_EN \ + 0x08 +#define LSM303DLHC_INT1_CFG_A_YDOWNE_M \ + 0x04 // enable interrupt generation on + // Y-low event +#define LSM303DLHC_INT1_CFG_A_YDOWNE_EN \ + 0x04 +#define LSM303DLHC_INT1_CFG_A_YLI_M \ + 0x04 // enable interrupt generation on + // Y-low event +#define LSM303DLHC_INT1_CFG_A_YLI_EN \ + 0x04 +#define LSM303DLHC_INT1_CFG_A_XHI_M \ + 0x02 // enable interrupt generation on + // X-hi event +#define LSM303DLHC_INT1_CFG_A_XHI_EN \ + 0x02 +#define LSM303DLHC_INT1_CFG_A_XUPE_M \ + 0x02 // enable interrupt generation on + // X-hi event +#define LSM303DLHC_INT1_CFG_A_XUPE_EN \ + 0x02 +#define LSM303DLHC_INT1_CFG_A_XLI_M \ + 0x01 // enable interrupt generation on + // X-low event +#define LSM303DLHC_INT1_CFG_A_XLI_EN \ + 0x01 +#define LSM303DLHC_INT1_CFG_A_XDOWNE_M \ + 0x01 // enable interrupt generation on + // X-low event +#define LSM303DLHC_INT1_CFG_A_XDOWNE_EN \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_INT1_SRC_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_INT1_SRC_A_ZERO_M \ + 0x80 // This bit must be zero +#define LSM303DLHC_INT1_SRC_A_ZERO_ZERO \ + 0x00 +#define LSM303DLHC_INT1_SRC_A_ZERO_INVALID \ + 0x80 +#define LSM303DLHC_INT1_SRC_A_IA_M \ + 0x40 // interrupt active +#define LSM303DLHC_INT1_SRC_A_IA_ACTIVE \ + 0x40 +#define LSM303DLHC_INT1_SRC_A_ZH_M \ + 0x20 // Z-Hi event occurred +#define LSM303DLHC_INT1_SRC_A_ZH_OCCURRED \ + 0x20 +#define LSM303DLHC_INT1_SRC_A_ZL_M \ + 0x10 // Z-Low event occurred +#define LSM303DLHC_INT1_SRC_A_ZL_OCCURRED \ + 0x10 +#define LSM303DLHC_INT1_SRC_A_YH_M \ + 0x08 // Y-Hi event occurred +#define LSM303DLHC_INT1_SRC_A_YH_OCCURRED \ + 0x08 +#define LSM303DLHC_INT1_SRC_A_YL_M \ + 0x04 // Y-Low event occurred +#define LSM303DLHC_INT1_SRC_A_YL_OCCURRED \ + 0x04 +#define LSM303DLHC_INT1_SRC_A_XH_M \ + 0x02 // X-Hi event occurred +#define LSM303DLHC_INT1_SRC_A_XH_OCCURRED \ + 0x02 +#define LSM303DLHC_INT1_SRC_A_XL_M \ + 0x01 // X-Low event occurred +#define LSM303DLHC_INT1_SRC_A_XL_OCCURRED \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// LSM303DLHC_O_MAG_TEMP_OUT_MSB register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_TEMP_OUT_MSB_MSB_M \ + 0xFF +#define LSM303DLHC_MAG_TEMP_OUT_MSB_MSB_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// LSM303DLHC_O_MAG_TEMP_OUT_LSB register. +// +//***************************************************************************** +#define LSM303DLHC_MAG_TEMP_OUT_LSB_LSB_M \ + 0xF0 +#define LSM303DLHC_MAG_TEMP_OUT_LSB_LSB_S \ + 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_INT1_THS_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_INT1_THS_A_ZERO_M \ + 0x80 // This bit must be zero +#define LSM303DLHC_INT1_THS_A_ZERO_ZERO \ + 0x00 +#define LSM303DLHC_INT1_THS_A_ZERO_INVALID \ + 0x80 +#define LSM303DLHC_INT1_THS_A_THS_M \ + 0x7F // THS[6-0] Interrupt threshold, + // default 0x0 +#define LSM303DLHC_INT1_THS_A_THS_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// LSM303DLHC_O_INT1_DURATION_A register. +// +//***************************************************************************** +#define LSM303DLHC_INT1_DURATION_A_ZERO_M \ + 0x80 // This bit must be zero +#define LSM303DLHC_INT1_DURATION_A_ZERO_ZERO \ + 0x00 +#define LSM303DLHC_INT1_DURATION_A_ZERO_INVALID \ + 0x80 +#define LSM303DLHC_INT1_DURATION_A_DURATION_M \ + 0x7F // Duration D[6-0] +#define LSM303DLHC_INT1_DURATION_A_DURATION_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_INT2_CFG_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_INT2_CFG_A_ANDOR_M \ + 0x80 // AND/OR combination of Interrupt + // events; default value: 0 +#define LSM303DLHC_INT2_CFG_A_ANDOR_OR \ + 0x00 +#define LSM303DLHC_INT2_CFG_A_ANDOR_AND \ + 0x80 +#define LSM303DLHC_INT2_CFG_A_6D_M \ + 0x40 // 6-direction function enabled +#define LSM303DLHC_INT2_CFG_A_6D_EN \ + 0x40 +#define LSM303DLHC_INT2_CFG_A_ZHI_M \ + 0x20 // enable interrupt generation on + // Z-hi event +#define LSM303DLHC_INT2_CFG_A_ZHI_EN \ + 0x20 +#define LSM303DLHC_INT2_CFG_A_ZLI_M \ + 0x10 // enable interrupt generation on + // Z-low event +#define LSM303DLHC_INT2_CFG_A_ZLI_EN \ + 0x10 +#define LSM303DLHC_INT2_CFG_A_YHI_M \ + 0x08 // enable interrupt generation on + // Y-hi event +#define LSM303DLHC_INT2_CFG_A_YHI_EN \ + 0x08 +#define LSM303DLHC_INT2_CFG_A_YLI_M \ + 0x04 // enable interrupt generation on + // Y-low event +#define LSM303DLHC_INT2_CFG_A_YLI_EN \ + 0x04 +#define LSM303DLHC_INT2_CFG_A_XHI_M \ + 0x02 // enable interrupt generation on + // X-hi event +#define LSM303DLHC_INT2_CFG_A_XHI_EN \ + 0x02 +#define LSM303DLHC_INT2_CFG_A_XLI_M \ + 0x01 // enable interrupt generation on + // X-low event +#define LSM303DLHC_INT2_CFG_A_XLI_EN \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_INT2_SRC_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_INT2_SRC_A_ZERO_M \ + 0x80 // This bit must be zero +#define LSM303DLHC_INT2_SRC_A_ZERO_ZERO \ + 0x00 +#define LSM303DLHC_INT2_SRC_A_ZERO_INVALID \ + 0x80 +#define LSM303DLHC_INT2_SRC_A_IA_M \ + 0x40 // interrupt active +#define LSM303DLHC_INT2_SRC_A_IA_ACTIVE \ + 0x40 +#define LSM303DLHC_INT2_SRC_A_ZH_M \ + 0x20 // Z-Hi event occurred +#define LSM303DLHC_INT2_SRC_A_ZH_OCCURRED \ + 0x20 +#define LSM303DLHC_INT2_SRC_A_ZL_M \ + 0x10 // Z-Low event occurred +#define LSM303DLHC_INT2_SRC_A_ZL_OCCURRED \ + 0x10 +#define LSM303DLHC_INT2_SRC_A_YH_M \ + 0x08 // Y-Hi event occurred +#define LSM303DLHC_INT2_SRC_A_YH_OCCURRED \ + 0x08 +#define LSM303DLHC_INT2_SRC_A_YL_M \ + 0x04 // Y-Low event occurred +#define LSM303DLHC_INT2_SRC_A_YL_OCCURRED \ + 0x04 +#define LSM303DLHC_INT2_SRC_A_XH_M \ + 0x02 // X-Hi event occurred +#define LSM303DLHC_INT2_SRC_A_XH_OCCURRED \ + 0x02 +#define LSM303DLHC_INT2_SRC_A_XL_M \ + 0x01 // X-Low event occurred +#define LSM303DLHC_INT2_SRC_A_XL_OCCURRED \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_INT2_THS_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_INT2_THS_A_ZERO_M \ + 0x80 // This bit must be zero +#define LSM303DLHC_INT2_THS_A_ZERO_ZERO \ + 0x00 +#define LSM303DLHC_INT2_THS_A_ZERO_INVALID \ + 0x80 +#define LSM303DLHC_INT2_THS_A_THS_M \ + 0x7F // THS[6-0] Interrupt threshold, + // default 0x0 +#define LSM303DLHC_INT2_THS_A_THS_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// LSM303DLHC_O_INT2_DURATION_A register. +// +//***************************************************************************** +#define LSM303DLHC_INT2_DURATION_A_ZERO_M \ + 0x80 // This bit must be zero +#define LSM303DLHC_INT2_DURATION_A_ZERO_ZERO \ + 0x00 +#define LSM303DLHC_INT2_DURATION_A_ZERO_INVALID \ + 0x80 +#define LSM303DLHC_INT2_DURATION_A_DURATION_M \ + 0x7F // Duration D[6-0] +#define LSM303DLHC_INT2_DURATION_A_DURATION_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CLICK_CFG_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_CLICK_CFG_A_ZD_M \ + 0x20 // Enable interrupt double click on + // Z axis +#define LSM303DLHC_CLICK_CFG_A_ZD_DIS \ + 0x00 +#define LSM303DLHC_CLICK_CFG_A_ZD_EN \ + 0x20 +#define LSM303DLHC_CLICK_CFG_A_ZS_M \ + 0x10 // Enable interrupt single click on + // Z axis +#define LSM303DLHC_CLICK_CFG_A_ZS_DIS \ + 0x00 +#define LSM303DLHC_CLICK_CFG_A_ZS_EN \ + 0x10 +#define LSM303DLHC_CLICK_CFG_A_YD_M \ + 0x08 // Enable interrupt double click on + // Y axis +#define LSM303DLHC_CLICK_CFG_A_YD_DIS \ + 0x00 +#define LSM303DLHC_CLICK_CFG_A_YD_EN \ + 0x08 +#define LSM303DLHC_CLICK_CFG_A_YS_M \ + 0x04 // Enable interrupt single click on + // Y axis +#define LSM303DLHC_CLICK_CFG_A_YS_DIS \ + 0x00 +#define LSM303DLHC_CLICK_CFG_A_YS_EN \ + 0x04 +#define LSM303DLHC_CLICK_CFG_A_XD_M \ + 0x02 // Enable interrupt double click on + // X axis +#define LSM303DLHC_CLICK_CFG_A_XD_DIS \ + 0x00 +#define LSM303DLHC_CLICK_CFG_A_XD_EN \ + 0x02 +#define LSM303DLHC_CLICK_CFG_A_XS_M \ + 0x01 // Enable interrupt single click on + // X axis +#define LSM303DLHC_CLICK_CFG_A_XS_DIS \ + 0x00 +#define LSM303DLHC_CLICK_CFG_A_XS_EN \ + 0x01 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CLICK_SRC_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_CLICK_SRC_A_IA_M \ + 0x40 // Interrupt pending +#define LSM303DLHC_CLICK_SRC_A_IA_NONE \ + 0x00 +#define LSM303DLHC_CLICK_SRC_A_IA_PENDING \ + 0x40 +#define LSM303DLHC_CLICK_SRC_A_DCLICK_M \ + 0x20 // double click-click enable +#define LSM303DLHC_CLICK_SRC_A_DCLICK_DIS \ + 0x00 +#define LSM303DLHC_CLICK_SRC_A_DCLICK_EN \ + 0x20 +#define LSM303DLHC_CLICK_SRC_A_SCLICK_M \ + 0x10 // single click-click enable +#define LSM303DLHC_CLICK_SRC_A_SCLICK_DIS \ + 0x00 +#define LSM303DLHC_CLICK_SRC_A_SCLICK_EN \ + 0x10 +#define LSM303DLHC_CLICK_SRC_A_SIGN_M \ + 0x08 // click-click sign +#define LSM303DLHC_CLICK_SRC_A_SIGN_POSITIVE \ + 0x00 +#define LSM303DLHC_CLICK_SRC_A_SIGN_NEGATIVE \ + 0x08 +#define LSM303DLHC_CLICK_SRC_A_AXIS_M \ + 0x7 // Axis click detection +#define LSM303DLHC_CLICK_SRC_A_AXIS_X \ + 0x01 // X click-click detection +#define LSM303DLHC_CLICK_SRC_A_AXIS_Y \ + 0x02 // Y click-click detection +#define LSM303DLHC_CLICK_SRC_A_AXIS_Z \ + 0x04 // Z click-click detection +#define LSM303DLHC_CLICK_SRC_A_AXIS_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the LSM303DLHC_O_CLICK_THS_A +// register. +// +//***************************************************************************** +#define LSM303DLHC_CLICK_THS_A_THS_M \ + 0x7F // Threshold; 1 LSB = full-scale / + // 128; THS6 through THS0 define + // the threshold which is used by + // the system to start the click + // detection procedure; the + // threshold value is expressed + // over 7 bits as an unsigned + // number +#define LSM303DLHC_CLICK_THS_A_THS_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// LSM303DLHC_O_TIME_LIMIT_A register. +// +//***************************************************************************** +#define LSM303DLHC_TIME_LIMIT_A_TLI_M \ + 0x7F // Time Limit; 1 LSB = 1/ODR; TLI7 + // through TLI0 define the maximum + // time interval that can elapse + // between the start of the click + // detection procedure (the + // acceleration on the selected + // channel exceeds the programmed + // threshold) and when the + // acceleration goes back below the + // threshold +#define LSM303DLHC_TIME_LIMIT_A_TLI_S \ + 0 + +#endif // __SENSORLIB_HW_LSM303DLHC_H__ diff --git a/sensorlib/hw_mpu6050.h b/sensorlib/hw_mpu6050.h new file mode 100644 index 0000000..32706e9 --- /dev/null +++ b/sensorlib/hw_mpu6050.h @@ -0,0 +1,1313 @@ +//***************************************************************************** +// +// hw_mpu6050.h - Macros used when accessing the Invensense MPU6050 +// accelerometer/gyroscope/magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_MPU6050_H__ +#define __SENSORLIB_HW_MPU6050_H__ + +//***************************************************************************** +// +// The following are defines for the MPU6050 register addresses. +// +//***************************************************************************** +#define MPU6050_O_SELF_TEST_X 0x0D // Self test X register +#define MPU6050_O_SELF_TEST_Y 0x0E // Self test Y register +#define MPU6050_O_SELF_TEST_Z 0x0F // Self test Z register +#define MPU6050_O_SELF_TEST_A 0x10 // Self test A register +#define MPU6050_O_SMPLRT_DIV 0x19 // Sample rate divider register +#define MPU6050_O_CONFIG 0x1A // Configuration register +#define MPU6050_O_GYRO_CONFIG 0x1B // Gyro configuration register +#define MPU6050_O_ACCEL_CONFIG 0x1C // Accelerometer configuration + // register +#define MPU6050_O_MOT_THR 0x1F // Motion detection threshold + // register +#define MPU6050_O_FIFO_EN 0x23 // FIFO enable register +#define MPU6050_O_I2C_MST_CTRL 0x24 // I2C master control register +#define MPU6050_O_I2C_SLV0_ADDR 0x25 // I2C slave 0 address register +#define MPU6050_O_I2C_SLV0_REG 0x26 // I2C slave 0 register number + // register +#define MPU6050_O_I2C_SLV0_CTRL 0x27 // I2C slave 0 control register +#define MPU6050_O_I2C_SLV1_ADDR 0x28 // I2C slave 1 address register +#define MPU6050_O_I2C_SLV1_REG 0x29 // I2C slave 1 register number + // register +#define MPU6050_O_I2C_SLV1_CTRL 0x2A // I2C slave 1 control register +#define MPU6050_O_I2C_SLV2_ADDR 0x2B // I2C slave 2 address register +#define MPU6050_O_I2C_SLV2_REG 0x2C // I2C slave 2 register number + // register +#define MPU6050_O_I2C_SLV2_CTRL 0x2D // I2C slave 2 control register +#define MPU6050_O_I2C_SLV3_ADDR 0x2E // I2C slave 3 address register +#define MPU6050_O_I2C_SLV3_REG 0x2F // I2C slave 3 register number + // register +#define MPU6050_O_I2C_SLV3_CTRL 0x30 // I2C slave 3 control register +#define MPU6050_O_I2C_SLV4_ADDR 0x31 // I2C slave 4 address register +#define MPU6050_O_I2C_SLV4_REG 0x32 // I2C slave 4 register number + // register +#define MPU6050_O_I2C_SLV4_DO 0x33 // I2C slave 4 output data register +#define MPU6050_O_I2C_SLV4_CTRL 0x34 // I2C slave 4 control register +#define MPU6050_O_I2C_SLV4_DI 0x35 // I2C slave 4 input data register +#define MPU6050_O_I2C_MST_STATUS \ + 0x36 // I2C master status register +#define MPU6050_O_INT_PIN_CFG 0x37 // INT pin configuration register +#define MPU6050_O_INT_ENABLE 0x38 // Interrupt enable register +#define MPU6050_O_INT_STATUS 0x3A // Interrupt status register +#define MPU6050_O_ACCEL_XOUT_H 0x3B // X-axis acceleration data MSB + // register +#define MPU6050_O_ACCEL_XOUT_L 0x3C // X-axis acceleration data LSB + // register +#define MPU6050_O_ACCEL_YOUT_H 0x3D // Y-axis acceleration data MSB + // register +#define MPU6050_O_ACCEL_YOUT_L 0x3E // Y-axis accelearation data LSB + // register +#define MPU6050_O_ACCEL_ZOUT_H 0x3F // Z-axis acceleration data MSB + // register +#define MPU6050_O_ACCEL_ZOUT_L 0x40 // Z-axis acceleration data LSB + // register +#define MPU6050_O_TEMP_OUT_H 0x41 // Temperature data MSB register +#define MPU6050_O_TEMP_OUT_L 0x42 // Temperature data LSB register +#define MPU6050_O_GYRO_XOUT_H 0x43 // X-axis gyro data MSB register +#define MPU6050_O_GYRO_XOUT_L 0x44 // X-axis gyro data LSB register +#define MPU6050_O_GYRO_YOUT_H 0x45 // Y-axis gyro data MSB register +#define MPU6050_O_GYRO_YOUT_L 0x46 // Y-axis gyro data LSB register +#define MPU6050_O_GYRO_ZOUT_H 0x47 // Z-axis gyro data MSB register +#define MPU6050_O_GYRO_ZOUT_L 0x48 // Z-axis gyro data LSB register +#define MPU6050_O_EXT_SENS_DATA_00 \ + 0x49 // External sensor data 0 register +#define MPU6050_O_EXT_SENS_DATA_01 \ + 0x4A // External sensor data 1 register +#define MPU6050_O_EXT_SENS_DATA_02 \ + 0x4B // External sensor data 2 register +#define MPU6050_O_EXT_SENS_DATA_03 \ + 0x4C // External sensor data 3 register +#define MPU6050_O_EXT_SENS_DATA_04 \ + 0x4D // External sensor data 4 register +#define MPU6050_O_EXT_SENS_DATA_05 \ + 0x4E // External sensor data 5 register +#define MPU6050_O_EXT_SENS_DATA_06 \ + 0x4F // External sensor data 6 register +#define MPU6050_O_EXT_SENS_DATA_07 \ + 0x50 // External sensor data 7 register +#define MPU6050_O_EXT_SENS_DATA_08 \ + 0x51 // External sensor data 8 register +#define MPU6050_O_EXT_SENS_DATA_09 \ + 0x52 // External sensor data 9 register +#define MPU6050_O_EXT_SENS_DATA_10 \ + 0x53 // External sensor data 10 register +#define MPU6050_O_EXT_SENS_DATA_11 \ + 0x54 // External sensor data 11 register +#define MPU6050_O_EXT_SENS_DATA_12 \ + 0x55 // External sensor data 12 register +#define MPU6050_O_EXT_SENS_DATA_13 \ + 0x56 // External sensor data 13 register +#define MPU6050_O_EXT_SENS_DATA_14 \ + 0x57 // External sensor data 14 register +#define MPU6050_O_EXT_SENS_DATA_15 \ + 0x58 // External sensor data 15 register +#define MPU6050_O_EXT_SENS_DATA_16 \ + 0x59 // External sensor data 16 register +#define MPU6050_O_EXT_SENS_DATA_17 \ + 0x5A // External sensor data 17 register +#define MPU6050_O_EXT_SENS_DATA_18 \ + 0x5B // External sensor data 18 register +#define MPU6050_O_EXT_SENS_DATA_19 \ + 0x5C // External sensor data 19 register +#define MPU6050_O_EXT_SENS_DATA_20 \ + 0x5D // External sensor data 20 register +#define MPU6050_O_EXT_SENS_DATA_21 \ + 0x5E // External sensor data 21 register +#define MPU6050_O_EXT_SENS_DATA_22 \ + 0x5F // External sensor data 22 register +#define MPU6050_O_EXT_SENS_DATA_23 \ + 0x60 // External sensor data 23 register +#define MPU6050_O_I2C_SLV0_DO 0x63 // I2C slave 0 output data register +#define MPU6050_O_I2C_SLV1_DO 0x64 // I2C slave 1 output data register +#define MPU6050_O_I2C_SLV2_DO 0x65 // I2C slave 2 output data register +#define MPU6050_O_I2C_SLV3_DO 0x66 // I2C slave 3 output data register +#define MPU6050_O_I2C_MST_DELAY_CTRL \ + 0x67 // I2C master delay control + // register +#define MPU6050_O_SIGNAL_PATH_RESET \ + 0x68 // Signal path reset register +#define MPU6050_O_MOT_DETECT_CTRL \ + 0x69 // Motion detection control + // register +#define MPU6050_O_USER_CTRL 0x6A // User control register +#define MPU6050_O_PWR_MGMT_1 0x6B // Power management 1 register +#define MPU6050_O_PWR_MGMT_2 0x6C // Power management 2 register +#define MPU6050_O_FIFO_COUNTH 0x72 // FIFO count MSB register +#define MPU6050_O_FIFO_COUNTL 0x73 // FIFO count LSB register +#define MPU6050_O_FIFO_R_W 0x74 // FIFO read write register +#define MPU6050_O_WHO_AM_I 0x75 // Who am I register + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_SELF_TEST_X +// register. +// +//***************************************************************************** +#define MPU6050_SELF_TEST_X_XA_TEST_M \ + 0xE0 // Accelerometer XA_TEST[4:2] +#define MPU6050_SELF_TEST_X_XG_TEST_M \ + 0x1F // Gyro XG_TEST[4:0] +#define MPU6050_SELF_TEST_X_XA_TEST_S \ + 5 +#define MPU6050_SELF_TEST_X_XG_TEST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_SELF_TEST_Y +// register. +// +//***************************************************************************** +#define MPU6050_SELF_TEST_Y_YA_TEST_M \ + 0xE0 // Accelerometer YA_TEST[4:2] +#define MPU6050_SELF_TEST_Y_YG_TEST_M \ + 0x1F // Gyro YG_TEST[4:0] +#define MPU6050_SELF_TEST_Y_YA_TEST_S \ + 5 +#define MPU6050_SELF_TEST_Y_YG_TEST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_SELF_TEST_Z +// register. +// +//***************************************************************************** +#define MPU6050_SELF_TEST_Z_ZA_TEST_M \ + 0xE0 // Accelerometer ZA_TEST[4:2] +#define MPU6050_SELF_TEST_Z_ZG_TEST_M \ + 0x1F // Gyro ZG_TEST[4:0] +#define MPU6050_SELF_TEST_Z_ZA_TEST_S \ + 5 +#define MPU6050_SELF_TEST_Z_ZG_TEST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_SELF_TEST_A +// register. +// +//***************************************************************************** +#define MPU6050_SELF_TEST_A_XA_TEST_M \ + 0x30 // Accelerometer XA_TEST[1:0] +#define MPU6050_SELF_TEST_A_YA_TEST_M \ + 0x0C // Accelerometer YA_TEST[1:0] +#define MPU6050_SELF_TEST_A_ZA_TEST_M \ + 0x03 // Accelerometer ZA_TEST[1:0] +#define MPU6050_SELF_TEST_A_XA_TEST_S \ + 4 +#define MPU6050_SELF_TEST_A_YA_TEST_S \ + 2 +#define MPU6050_SELF_TEST_A_ZA_TEST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_SMPLRT_DIV +// register. +// +//***************************************************************************** +#define MPU6050_SMPLRT_DIV_M 0xFF // Gyro output rate divider +#define MPU6050_SMPLRT_DIV_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_CONFIG +// register. +// +//***************************************************************************** +#define MPU6050_CONFIG_EXT_SYNC_SET_M \ + 0x38 // FSYNC pin sample location +#define MPU6050_CONFIG_EXT_SYNC_SET_DIS \ + 0x00 // FSYNC input disabled +#define MPU6050_CONFIG_EXT_SYNC_SET_TEMP_OUT_L \ + 0x08 // FSYNC on TEMP_OUT_L[0] +#define MPU6050_CONFIG_EXT_SYNC_SET_GYRO_XOUT_L \ + 0x10 // FSYNC on GYRO_XOUT_L[0] +#define MPU6050_CONFIG_EXT_SYNC_SET_GYRO_YOUT_L \ + 0x18 // FSYNC on GYRO_YOUT_L[0] +#define MPU6050_CONFIG_EXT_SYNC_SET_GYRO_ZOUT_L \ + 0x20 // FSYNC on GYRO_ZOUT_L[0] +#define MPU6050_CONFIG_EXT_SYNC_SET_ACCEL_XOUT_L \ + 0x28 // FSYNC on ACCEL_XOUT_L[0] +#define MPU6050_CONFIG_EXT_SYNC_SET_ACCEL_YOUT_L \ + 0x30 // FSYNC on ACCEL_YOUT_L[0] +#define MPU6050_CONFIG_EXT_SYNC_SET_ACCEL_ZOUT_L \ + 0x38 // FSYNC on ACCEL_ZOUT_L[0] +#define MPU6050_CONFIG_DLPF_CFG_M \ + 0x07 // Digital low-pass filter + // configuration +#define MPU6050_CONFIG_DLPF_CFG_260_256 \ + 0x00 // 260 Hz accelerometer bandwidth, + // 256 Hz gyro bandwidth +#define MPU6050_CONFIG_DLPF_CFG_184_188 \ + 0x01 // 184 Hz accelerometer bandwidth, + // 188 Hz gyro bandwidth +#define MPU6050_CONFIG_DLPF_CFG_94_98 \ + 0x02 // 94 Hz accelerometer bandwidth, + // 98 Hz gyro bandwidth +#define MPU6050_CONFIG_DLPF_CFG_44_42 \ + 0x03 // 44 Hz accelerometer bandwidth, + // 42 Hz gyro bandwidth +#define MPU6050_CONFIG_DLPF_CFG_21_20 \ + 0x04 // 21 Hz accelerometer bandwidth, + // 20 Hz gyro bandwidth +#define MPU6050_CONFIG_DLPF_CFG_10_10 \ + 0x05 // 10 Hz accelerometer bandwidth, + // 10 Hz gyro bandwidth +#define MPU6050_CONFIG_DLPF_CFG_5_5 \ + 0x06 // 5 Hz accelerometer bandwidth, 5 + // Hz gyro bandwidth +#define MPU6050_CONFIG_EXT_SYNC_SET_S \ + 3 +#define MPU6050_CONFIG_DLPF_CFG_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_GYRO_CONFIG +// register. +// +//***************************************************************************** +#define MPU6050_GYRO_CONFIG_FS_SEL_M \ + 0x18 // Gyro full-scale range +#define MPU6050_GYRO_CONFIG_FS_SEL_250 \ + 0x00 // Gyro full-scale range +/- 250 + // degrees/sec +#define MPU6050_GYRO_CONFIG_FS_SEL_500 \ + 0x08 // Gyro full-scale range +/- 500 + // degrees/sec +#define MPU6050_GYRO_CONFIG_FS_SEL_1000 \ + 0x10 // Gyro full-scale range +/- 1000 + // degrees/sec +#define MPU6050_GYRO_CONFIG_FS_SEL_2000 \ + 0x18 // Gyro full-scale range +/- 2000 + // degrees/sec +#define MPU6050_GYRO_CONFIG_FS_SEL_S \ + 3 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_ACCEL_CONFIG +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_CONFIG_XA_ST \ + 0x80 // X-axis accelerometer self-test + // enable +#define MPU6050_ACCEL_CONFIG_YA_ST \ + 0x40 // Y-axis accelerometer self-test + // enable +#define MPU6050_ACCEL_CONFIG_ZA_ST \ + 0x20 // Z-axis accelerometer self-test + // enable +#define MPU6050_ACCEL_CONFIG_AFS_SEL_M \ + 0x18 // Accelerometer full-scale range +#define MPU6050_ACCEL_CONFIG_AFS_SEL_2G \ + 0x00 // Accelerometer full-scale range 2 + // g +#define MPU6050_ACCEL_CONFIG_AFS_SEL_4G \ + 0x08 // Accelerometer full-scale range 4 + // g +#define MPU6050_ACCEL_CONFIG_AFS_SEL_8G \ + 0x10 // Accelerometer full-scale range 8 + // g +#define MPU6050_ACCEL_CONFIG_AFS_SEL_16G \ + 0x18 // Accelerometer full-scale range + // 16 g +#define MPU6050_ACCEL_CONFIG_AFS_SEL_S \ + 3 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_MOT_THR +// register. +// +//***************************************************************************** +#define MPU6050_MOT_THR_M 0xFF // Motion detection threshold value +#define MPU6050_MOT_THR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_FIFO_EN +// register. +// +//***************************************************************************** +#define MPU6050_FIFO_EN_TEMP 0x80 // Temperature sensor FIFO enable +#define MPU6050_FIFO_EN_XG 0x40 // X-axis gyro FIFO enable +#define MPU6050_FIFO_EN_YG 0x20 // Y-axis gyro FIFO enable +#define MPU6050_FIFO_EN_ZG 0x10 // Z-axis gyro FIFO enable +#define MPU6050_FIFO_EN_ACCEL 0x08 // Accelerometer FIFO enable +#define MPU6050_FIFO_EN_SLV2 0x04 // Slave 2 FIFO enable +#define MPU6050_FIFO_EN_SLV1 0x02 // Slave 1 FIFO enable +#define MPU6050_FIFO_EN_SLV0 0x01 // Slave 0 FIFO enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_MST_CTRL +// register. +// +//***************************************************************************** +#define MPU6050_I2C_MST_CTRL_MULT_MST_EN \ + 0x80 // Multi-master enable +#define MPU6050_I2C_MST_CTRL_WAIT_FOR_ES \ + 0x40 // Wait for external sensor data +#define MPU6050_I2C_MST_CTRL_SLV3_FIFO_EN \ + 0x20 // Slave 3 FIFO enable +#define MPU6050_I2C_MST_CTRL_I2C_MST_P_NSR \ + 0x10 // No repeated start conditions +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_M \ + 0x0F // I2C master clock speed +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_348 \ + 0x00 // 348 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_333 \ + 0x01 // 333 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_320 \ + 0x02 // 320 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_308 \ + 0x03 // 308 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_296 \ + 0x04 // 296 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_286 \ + 0x05 // 286 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_276 \ + 0x06 // 276 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_267 \ + 0x07 // 267 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_258 \ + 0x08 // 258 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_500 \ + 0x09 // 500 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_471 \ + 0x0A // 471 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_444 \ + 0x0B // 444 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_421 \ + 0x0C // 421 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_400 \ + 0x0D // 400 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_381 \ + 0x0E // 381 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_364 \ + 0x0F // 364 kHz I2C master clock +#define MPU6050_I2C_MST_CTRL_I2C_MST_CLK_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV0_ADDR +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV0_ADDR_RW \ + 0x80 // Read/not write +#define MPU6050_I2C_SLV0_ADDR_M 0x7F // Slave address +#define MPU6050_I2C_SLV0_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV0_REG +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV0_REG_M 0xFF // Slave register number +#define MPU6050_I2C_SLV0_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV0_CTRL +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV0_CTRL_EN \ + 0x80 // Enable slave +#define MPU6050_I2C_SLV0_CTRL_BYTE_SW \ + 0x40 // Byte-swap word pairs +#define MPU6050_I2C_SLV0_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU6050_I2C_SLV0_CTRL_GRP \ + 0x10 // Word pair grouping +#define MPU6050_I2C_SLV0_CTRL_LEN_M \ + 0x0F // Number of bytes to transfer +#define MPU6050_I2C_SLV0_CTRL_LEN_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV1_ADDR +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV1_ADDR_RW \ + 0x80 // Read/not write +#define MPU6050_I2C_SLV1_ADDR_M 0x7F // Slave address +#define MPU6050_I2C_SLV1_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV1_REG +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV1_REG_M 0xFF // Slave register number +#define MPU6050_I2C_SLV1_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV1_CTRL +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV1_CTRL_EN \ + 0x80 // Enable slave +#define MPU6050_I2C_SLV1_CTRL_BYTE_SW \ + 0x40 // Byte-swap word pairs +#define MPU6050_I2C_SLV1_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU6050_I2C_SLV1_CTRL_GRP \ + 0x10 // Word pair grouping +#define MPU6050_I2C_SLV1_CTRL_LEN_M \ + 0x0F // Number of bytes to transfer +#define MPU6050_I2C_SLV1_CTRL_LEN_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV2_ADDR +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV2_ADDR_RW \ + 0x80 // Read/not write +#define MPU6050_I2C_SLV2_ADDR_M 0x7F // Slave address +#define MPU6050_I2C_SLV2_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV2_REG +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV2_REG_M 0xFF // Slave register number +#define MPU6050_I2C_SLV2_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV2_CTRL +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV2_CTRL_EN \ + 0x80 // Enable slave +#define MPU6050_I2C_SLV2_CTRL_BYTE_SW \ + 0x40 // Byte-swap word pairs +#define MPU6050_I2C_SLV2_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU6050_I2C_SLV2_CTRL_GRP \ + 0x10 // Word pair grouping +#define MPU6050_I2C_SLV2_CTRL_LEN_M \ + 0x0F // Number of bytes to transfer +#define MPU6050_I2C_SLV2_CTRL_LEN_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV3_ADDR +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV3_ADDR_RW \ + 0x80 // Read/not write +#define MPU6050_I2C_SLV3_ADDR_M 0x7F // Slave address +#define MPU6050_I2C_SLV3_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV3_REG +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV3_REG_M 0xFF // Slave register number +#define MPU6050_I2C_SLV3_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV3_CTRL +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV3_CTRL_EN \ + 0x80 // Enable slave +#define MPU6050_I2C_SLV3_CTRL_BYTE_SW \ + 0x40 // Byte-swap word pairs +#define MPU6050_I2C_SLV3_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU6050_I2C_SLV3_CTRL_GRP \ + 0x10 // Word pair grouping +#define MPU6050_I2C_SLV3_CTRL_LEN_M \ + 0x0F // Number of bytes to transfer +#define MPU6050_I2C_SLV3_CTRL_LEN_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV4_ADDR +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV4_ADDR_RW \ + 0x80 // Read/not write +#define MPU6050_I2C_SLV4_ADDR_M 0x7F // Slave address +#define MPU6050_I2C_SLV4_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV4_REG +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV4_REG_M 0xFF // Slave register number +#define MPU6050_I2C_SLV4_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV4_CTRL +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV4_CTRL_EN \ + 0x80 // Enable slave +#define MPU6050_I2C_SLV4_CTRL_INT_EN \ + 0x40 // Interrupt enable +#define MPU6050_I2C_SLV4_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU6050_I2C_SLV4_CTRL_I2C_MST_DLY_M \ + 0x1F // Slave access delay +#define MPU6050_I2C_SLV4_CTRL_I2C_MST_DLY_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV4_DI +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV4_DI_M 0xFF // Input data +#define MPU6050_I2C_SLV4_DI_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_MST_STATUS +// register. +// +//***************************************************************************** +#define MPU6050_I2C_MST_STATUS_PASS_THROUGH \ + 0x80 // Pass through FSYNC interrupt + // status +#define MPU6050_I2C_MST_STATUS_I2C_SLV4_DONE \ + 0x40 // I2C slave 4 completion status +#define MPU6050_I2C_MST_STATUS_I2C_LOST_ARB \ + 0x20 // I2C arbitration lost status +#define MPU6050_I2C_MST_STATUS_I2C_SLV4_NACK \ + 0x10 // I2C slave 4 NACK status +#define MPU6050_I2C_MST_STATUS_I2C_SLV3_NACK \ + 0x08 // I2C slave 3 NACK status +#define MPU6050_I2C_MST_STATUS_I2C_SLV2_NACK \ + 0x04 // I2C slave 2 NACK status +#define MPU6050_I2C_MST_STATUS_I2C_SLV1_NACK \ + 0x02 // I2C slave 1 NACK status +#define MPU6050_I2C_MST_STATUS_I2C_SLV0_NACK \ + 0x01 // I2C slave 0 NACK status + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_INT_PIN_CFG +// register. +// +//***************************************************************************** +#define MPU6050_INT_PIN_CFG_INT_LEVEL \ + 0x80 // INT pin active low +#define MPU6050_INT_PIN_CFG_INT_OPEN \ + 0x40 // INT pin open-drain +#define MPU6050_INT_PIN_CFG_LATCH_INT_EN \ + 0x20 // Latch INT pin output +#define MPU6050_INT_PIN_CFG_INT_RD_CLEAR \ + 0x10 // Interrupt clear on any read +#define MPU6050_INT_PIN_CFG_FSYNC_INT_LEVEL \ + 0x08 // FSYNC pin active low +#define MPU6050_INT_PIN_CFG_FSYNC_INT_EN \ + 0x04 // FSYNC pin interrupt enable +#define MPU6050_INT_PIN_CFG_I2C_BYPASS_EN \ + 0x02 // I2C bypass enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_INT_ENABLE +// register. +// +//***************************************************************************** +#define MPU6050_INT_ENABLE_MOT_EN \ + 0x40 // Motion detection interrupt + // enable +#define MPU6050_INT_ENABLE_FIFO_OFLOW_EN \ + 0x10 // FIFO overflow interrupt enable +#define MPU6050_INT_ENABLE_I2C_MST_INT_EN \ + 0x08 // I2C master interrupt enable +#define MPU6050_INT_ENABLE_DATA_RDY_EN \ + 0x01 // Data ready interrupt enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_INT_STATUS +// register. +// +//***************************************************************************** +#define MPU6050_INT_STATUS_MOT_INT \ + 0x40 // Motion detection interrupt + // status +#define MPU6050_INT_STATUS_FIFO_OFLOW_INT \ + 0x10 // FIFO overflow interrupt status +#define MPU6050_INT_STATUS_I2C_MST_INT \ + 0x08 // I2C master interrupt status +#define MPU6050_INT_STATUS_DATA_RDY_INT \ + 0x01 // Data ready interrupt status + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_ACCEL_XOUT_H +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_XOUT_H_M 0xFF // Bits [15:8] of X-axis + // acceleration data +#define MPU6050_ACCEL_XOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_ACCEL_XOUT_L +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_XOUT_L_M 0xFF // Bits [7:0] of X-axis + // acceleration data +#define MPU6050_ACCEL_XOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_ACCEL_YOUT_H +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_YOUT_H_M 0xFF // Bits [15:8] of Y-axis + // acceleration data +#define MPU6050_ACCEL_YOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_ACCEL_YOUT_L +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_YOUT_L_M 0xFF // Bits [7:0] of Y-axis + // acceleration data +#define MPU6050_ACCEL_YOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_ACCEL_ZOUT_H +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_ZOUT_H_M 0xFF // Bits [15:8] of Z-axis + // acceleration data +#define MPU6050_ACCEL_ZOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_ACCEL_ZOUT_L +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_ZOUT_L_M 0xFF // Bits [7:0] of Z-axis + // acceleration data +#define MPU6050_ACCEL_ZOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_TEMP_OUT_H +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_TEMP_OUT_H_M \ + 0xFF // Bits [15:8] of temperature data +#define MPU6050_ACCEL_TEMP_OUT_H_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_TEMP_OUT_L +// register. +// +//***************************************************************************** +#define MPU6050_ACCEL_TEMP_OUT_L_M \ + 0xFF // Bits [7:0] of temperature data +#define MPU6050_ACCEL_TEMP_OUT_L_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_GYRO_XOUT_H +// register. +// +//***************************************************************************** +#define MPU6050_GYRO_XOUT_H_M 0xFF // Bits [15:8] of X-axis gyro data +#define MPU6050_GYRO_XOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_GYRO_XOUT_L +// register. +// +//***************************************************************************** +#define MPU6050_GYRO_XOUT_L_M 0xFF // Bits [7:0] of X-axis gyro data +#define MPU6050_GYRO_XOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_GYRO_YOUT_H +// register. +// +//***************************************************************************** +#define MPU6050_GYRO_YOUT_H_M 0xFF // Bits [15:8] of Y-axis gyro data +#define MPU6050_GYRO_YOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_GYRO_YOUT_L +// register. +// +//***************************************************************************** +#define MPU6050_GYRO_YOUT_L_M 0xFF // Bits [7:0] of Y-axis gyro data +#define MPU6050_GYRO_YOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_GYRO_ZOUT_H +// register. +// +//***************************************************************************** +#define MPU6050_GYRO_ZOUT_H_M 0xFF // Bits [15:8] of Z-axis gyro data +#define MPU6050_GYRO_ZOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_GYRO_ZOUT_L +// register. +// +//***************************************************************************** +#define MPU6050_GYRO_ZOUT_L_M 0xFF // Bits [7:0] of Z-axis gyro data +#define MPU6050_GYRO_ZOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_00 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_00_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_00_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_01 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_01_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_01_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_02 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_02_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_02_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_03 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_03_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_03_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_04 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_04_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_04_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_05 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_05_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_05_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_06 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_06_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_06_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_07 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_07_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_07_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_08 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_08_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_08_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_09 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_09_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_09_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_10 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_10_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_10_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_11 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_11_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_11_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_12 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_12_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_12_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_13 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_13_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_13_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_14 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_14_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_14_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_15 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_15_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_15_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_16 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_16_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_16_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_17 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_17_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_17_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_18 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_18_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_18_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_19 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_19_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_19_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_20 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_20_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_20_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_21 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_21_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_21_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_22 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_22_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_22_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_EXT_SENS_DATA_23 register. +// +//***************************************************************************** +#define MPU6050_EXT_SENS_DATA_23_M \ + 0xFF // External sensor data +#define MPU6050_EXT_SENS_DATA_23_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV0_DO +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV0_DO_M 0xFF // Output data +#define MPU6050_I2C_SLV0_DO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV1_DO +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV1_DO_M 0xFF // Output data +#define MPU6050_I2C_SLV1_DO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV2_DO +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV2_DO_M 0xFF // Output data +#define MPU6050_I2C_SLV2_DO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_I2C_SLV3_DO +// register. +// +//***************************************************************************** +#define MPU6050_I2C_SLV3_DO_M 0xFF // Output data +#define MPU6050_I2C_SLV3_DO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_I2C_MST_DELAY_CTRL register. +// +//***************************************************************************** +#define MPU6050_I2C_MST_DELAY_CTRL_DELAY_ES_SHADOW \ + 0x80 // Delay external sensor data +#define MPU6050_I2C_MST_DELAY_CTRL_I2C_SLV4_DLY_EN \ + 0x10 // I2C slave 4 delay enable +#define MPU6050_I2C_MST_DELAY_CTRL_I2C_SLV3_DLY_EN \ + 0x08 // I2C slave 3 delay enable +#define MPU6050_I2C_MST_DELAY_CTRL_I2C_SLV2_DLY_EN \ + 0x04 // I2C slave 2 delay enable +#define MPU6050_I2C_MST_DELAY_CTRL_I2C_SLV1_DLY_EN \ + 0x02 // I2C slave 1 delay enable +#define MPU6050_I2C_MST_DELAY_CTRL_I2C_SLV0_DLY_EN \ + 0x01 // I2C slave 0 delay enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_SIGNAL_PATH_RESET register. +// +//***************************************************************************** +#define MPU6050_SIGNAL_PATH_RESET_GYRO \ + 0x04 // Reset gyro +#define MPU6050_SIGNAL_PATH_RESET_ACCEL \ + 0x02 // Reset accelerometer +#define MPU6050_SIGNAL_PATH_RESET_TEMP \ + 0x01 // Reset temperature sensor + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU6050_O_MOT_DETECT_CTRL register. +// +//***************************************************************************** +#define MPU6050_MOT_DETECT_CTRL_ACCEL_ON_DELAY_M \ + 0x30 // Accelerometer wake-up delay +#define MPU6050_MOT_DETECT_CTRL_ACCEL_ON_DELAY_4MS \ + 0x00 // Delay 4 ms +#define MPU6050_MOT_DETECT_CTRL_ACCEL_ON_DELAY_5MS \ + 0x10 // Delay 5 ms +#define MPU6050_MOT_DETECT_CTRL_ACCEL_ON_DELAY_6MS \ + 0x20 // Delay 6 ms +#define MPU6050_MOT_DETECT_CTRL_ACCEL_ON_DELAY_7MS \ + 0x30 // Delay 7 ms +#define MPU6050_MOT_DETECT_CTRL_ACCEL_ON_DELAY_S \ + 4 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_USER_CTRL +// register. +// +//***************************************************************************** +#define MPU6050_USER_CTRL_FIFO_EN \ + 0x40 // FIFO enable +#define MPU6050_USER_CTRL_I2C_MST_EN \ + 0x20 // I2C master mode enable +#define MPU6050_USER_CTRL_I2C_IF_DIS \ + 0x10 // Write as zero +#define MPU6050_USER_CTRL_FIFO_RESET \ + 0x04 // Reset FIFO buffer +#define MPU6050_USER_CTRL_I2C_MST_RESET \ + 0x02 // Reset I2C master +#define MPU6050_USER_CTRL_SIG_COND_RESET \ + 0x01 // Reset all sensors + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_PWR_MGMT_1 +// register. +// +//***************************************************************************** +#define MPU6050_PWR_MGMT_1_DEVICE_RESET \ + 0x80 // Device reset +#define MPU6050_PWR_MGMT_1_SLEEP \ + 0x40 // Enter sleep mode +#define MPU6050_PWR_MGMT_1_CYCLE \ + 0x20 // Enable automatic sleep +#define MPU6050_PWR_MGMT_1_TEMP_DIS \ + 0x08 // Disable temperature sensor +#define MPU6050_PWR_MGMT_1_CLKSEL_M \ + 0x07 // Clock source select +#define MPU6050_PWR_MGMT_1_CLKSEL_INT \ + 0x00 // Internal 8 MHz oscillator +#define MPU6050_PWR_MGMT_1_CLKSEL_XG \ + 0x01 // PLL with X-axis gyro reference +#define MPU6050_PWR_MGMT_1_CLKSEL_YG \ + 0x02 // PLL with Y-axis gyro reference +#define MPU6050_PWR_MGMT_1_CLKSEL_ZG \ + 0x03 // PLL with Z-axis gyro reference +#define MPU6050_PWR_MGMT_1_CLKSEL_EXT32K \ + 0x04 // PLL with external 32.768 kHz + // reference +#define MPU6050_PWR_MGMT_1_CLKSEL_EXT19M \ + 0x05 // PLL with external 19.2 MHz + // reference +#define MPU6050_PWR_MGMT_1_CLKSEL_STOP \ + 0x07 // Clock disable +#define MPU6050_PWR_MGMT_1_CLKSEL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_PWR_MGMT_2 +// register. +// +//***************************************************************************** +#define MPU6050_PWR_MGMT_2_LP_WAKE_CTRL_M \ + 0xC0 // Wake-up frequency +#define MPU6050_PWR_MGMT_2_LP_WAKE_CTRL_1_25 \ + 0x00 // Wake-up at 1.25 Hz +#define MPU6050_PWR_MGMT_2_LP_WAKE_CTRL_5 \ + 0x40 // Wake-up at 5 Hz +#define MPU6050_PWR_MGMT_2_LP_WAKE_CTRL_20 \ + 0x80 // Wake-up at 20 Hz +#define MPU6050_PWR_MGMT_2_LP_WAKE_CTRL_40 \ + 0xC0 // Wake-up at 40 Hz +#define MPU6050_PWR_MGMT_2_STBY_XA \ + 0x20 // Put X-axis accelerometer into + // standby mode +#define MPU6050_PWR_MGMT_2_STBY_YA \ + 0x10 // Put Y-axis accelerometer into + // standby mode +#define MPU6050_PWR_MGMT_2_STBY_ZA \ + 0x08 // Put Z-axis accelerometer into + // standby mode +#define MPU6050_PWR_MGMT_2_STBY_XG \ + 0x04 // Put X-axis gyro into standby + // mode +#define MPU6050_PWR_MGMT_2_STBY_YG \ + 0x02 // Put Y-axis gyro into standby + // mode +#define MPU6050_PWR_MGMT_2_STBY_ZG \ + 0x01 // Put Z-axis gyro into standby + // mode +#define MPU6050_PWR_MGMT_2_LP_WAKE_CTRL_S \ + 6 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_FIFO_COUNTH +// register. +// +//***************************************************************************** +#define MPU6050_FIFO_COUNTH_M 0xFF // FIFO count [15:8] +#define MPU6050_FIFO_COUNTH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_FIFO_COUNTL +// register. +// +//***************************************************************************** +#define MPU6050_FIFO_COUNTL_M 0xFF // FIFO count [7:0] +#define MPU6050_FIFO_COUNTL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_FIFO_R_W +// register. +// +//***************************************************************************** +#define MPU6050_FIFO_R_W_M 0xFF // FIFO data +#define MPU6050_FIFO_R_W_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU6050_O_WHO_AM_I +// register. +// +//***************************************************************************** +#define MPU6050_WHO_AM_I_M 0x7E // I2C address +#define MPU6050_WHO_AM_I_MPU6050 \ + 0x68 // MPU6050 +#define MPU6050_WHO_AM_I_S 1 + +#endif // __SENSORLIB_HW_MPU6050_H__ diff --git a/sensorlib/hw_mpu9150.h b/sensorlib/hw_mpu9150.h new file mode 100644 index 0000000..b586d1b --- /dev/null +++ b/sensorlib/hw_mpu9150.h @@ -0,0 +1,1454 @@ +//***************************************************************************** +// +// hw_mpu9150.h - Macros used when accessing the Invensense MPU9150 +// accelerometer/gyroscope/magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_MPU9150_H__ +#define __SENSORLIB_HW_MPU9150_H__ + +//***************************************************************************** +// +// The following are defines for the MPU9150 register addresses. +// +//***************************************************************************** +#define MPU9150_O_SELF_TEST_X 0x0D // Self test X register +#define MPU9150_O_SELF_TEST_Y 0x0E // Self test Y register +#define MPU9150_O_SELF_TEST_Z 0x0F // Self test Z register +#define MPU9150_O_SELF_TEST_A 0x10 // Self test A register +#define MPU9150_O_SMPLRT_DIV 0x19 // Sample rate divider register +#define MPU9150_O_CONFIG 0x1A // Configuration register +#define MPU9150_O_GYRO_CONFIG 0x1B // Gyro configuration register +#define MPU9150_O_ACCEL_CONFIG 0x1C // Accelerometer configuration + // register +#define MPU9150_O_FF_THR 0x1D // Free-fall threshold register +#define MPU9150_O_FF_DUR 0x1E // Free-fall duration register +#define MPU9150_O_MOT_THR 0x1F // Motion detection threshold + // register +#define MPU9150_O_MOT_DUR 0x20 // Motion detection duration + // register +#define MPU9150_O_ZRMOT_THR 0x21 // Zero motion detection threshold + // register +#define MPU9150_O_ZRMOT_DUR 0x22 // Zero motion detection duration + // register +#define MPU9150_O_FIFO_EN 0x23 // FIFO enable register +#define MPU9150_O_I2C_MST_CTRL 0x24 // I2C master control register +#define MPU9150_O_I2C_SLV0_ADDR 0x25 // I2C slave 0 address register +#define MPU9150_O_I2C_SLV0_REG 0x26 // I2C slave 0 register number + // register +#define MPU9150_O_I2C_SLV0_CTRL 0x27 // I2C slave 0 control register +#define MPU9150_O_I2C_SLV1_ADDR 0x28 // I2C slave 1 address register +#define MPU9150_O_I2C_SLV1_REG 0x29 // I2C slave 1 register number + // register +#define MPU9150_O_I2C_SLV1_CTRL 0x2A // I2C slave 1 control register +#define MPU9150_O_I2C_SLV2_ADDR 0x2B // I2C slave 2 address register +#define MPU9150_O_I2C_SLV2_REG 0x2C // I2C slave 2 register number + // register +#define MPU9150_O_I2C_SLV2_CTRL 0x2D // I2C slave 2 control register +#define MPU9150_O_I2C_SLV3_ADDR 0x2E // I2C slave 3 address register +#define MPU9150_O_I2C_SLV3_REG 0x2F // I2C slave 3 register number + // register +#define MPU9150_O_I2C_SLV3_CTRL 0x30 // I2C slave 3 control register +#define MPU9150_O_I2C_SLV4_ADDR 0x31 // I2C slave 4 address register +#define MPU9150_O_I2C_SLV4_REG 0x32 // I2C slave 4 register number + // register +#define MPU9150_O_I2C_SLV4_DO 0x33 // I2C slave 4 output data register +#define MPU9150_O_I2C_SLV4_CTRL 0x34 // I2C slave 4 control register +#define MPU9150_O_I2C_SLV4_DI 0x35 // I2C slave 4 input data register +#define MPU9150_O_I2C_MST_STATUS \ + 0x36 // I2C master status register +#define MPU9150_O_INT_PIN_CFG 0x37 // INT pin configuration register +#define MPU9150_O_INT_ENABLE 0x38 // Interrupt enable register +#define MPU9150_O_INT_STATUS 0x3A // Interrupt status register +#define MPU9150_O_ACCEL_XOUT_H 0x3B // X-axis acceleration data MSB + // register +#define MPU9150_O_ACCEL_XOUT_L 0x3C // X-axis acceleration data LSB + // register +#define MPU9150_O_ACCEL_YOUT_H 0x3D // Y-axis acceleration data MSB + // register +#define MPU9150_O_ACCEL_YOUT_L 0x3E // Y-axis accelearation data LSB + // register +#define MPU9150_O_ACCEL_ZOUT_H 0x3F // Z-axis acceleration data MSB + // register +#define MPU9150_O_ACCEL_ZOUT_L 0x40 // Z-axis acceleration data LSB + // register +#define MPU9150_O_TEMP_OUT_H 0x41 // Temperature data MSB register +#define MPU9150_O_TEMP_OUT_L 0x42 // Temperature data LSB register +#define MPU9150_O_GYRO_XOUT_H 0x43 // X-axis gyro data MSB register +#define MPU9150_O_GYRO_XOUT_L 0x44 // X-axis gyro data LSB register +#define MPU9150_O_GYRO_YOUT_H 0x45 // Y-axis gyro data MSB register +#define MPU9150_O_GYRO_YOUT_L 0x46 // Y-axis gyro data LSB register +#define MPU9150_O_GYRO_ZOUT_H 0x47 // Z-axis gyro data MSB register +#define MPU9150_O_GYRO_ZOUT_L 0x48 // Z-axis gyro data LSB register +#define MPU9150_O_EXT_SENS_DATA_00 \ + 0x49 // External sensor data 0 register +#define MPU9150_O_EXT_SENS_DATA_01 \ + 0x4A // External sensor data 1 register +#define MPU9150_O_EXT_SENS_DATA_02 \ + 0x4B // External sensor data 2 register +#define MPU9150_O_EXT_SENS_DATA_03 \ + 0x4C // External sensor data 3 register +#define MPU9150_O_EXT_SENS_DATA_04 \ + 0x4D // External sensor data 4 register +#define MPU9150_O_EXT_SENS_DATA_05 \ + 0x4E // External sensor data 5 register +#define MPU9150_O_EXT_SENS_DATA_06 \ + 0x4F // External sensor data 6 register +#define MPU9150_O_EXT_SENS_DATA_07 \ + 0x50 // External sensor data 7 register +#define MPU9150_O_EXT_SENS_DATA_08 \ + 0x51 // External sensor data 8 register +#define MPU9150_O_EXT_SENS_DATA_09 \ + 0x52 // External sensor data 9 register +#define MPU9150_O_EXT_SENS_DATA_10 \ + 0x53 // External sensor data 10 register +#define MPU9150_O_EXT_SENS_DATA_11 \ + 0x54 // External sensor data 11 register +#define MPU9150_O_EXT_SENS_DATA_12 \ + 0x55 // External sensor data 12 register +#define MPU9150_O_EXT_SENS_DATA_13 \ + 0x56 // External sensor data 13 register +#define MPU9150_O_EXT_SENS_DATA_14 \ + 0x57 // External sensor data 14 register +#define MPU9150_O_EXT_SENS_DATA_15 \ + 0x58 // External sensor data 15 register +#define MPU9150_O_EXT_SENS_DATA_16 \ + 0x59 // External sensor data 16 register +#define MPU9150_O_EXT_SENS_DATA_17 \ + 0x5A // External sensor data 17 register +#define MPU9150_O_EXT_SENS_DATA_18 \ + 0x5B // External sensor data 18 register +#define MPU9150_O_EXT_SENS_DATA_19 \ + 0x5C // External sensor data 19 register +#define MPU9150_O_EXT_SENS_DATA_20 \ + 0x5D // External sensor data 20 register +#define MPU9150_O_EXT_SENS_DATA_21 \ + 0x5E // External sensor data 21 register +#define MPU9150_O_EXT_SENS_DATA_22 \ + 0x5F // External sensor data 22 register +#define MPU9150_O_EXT_SENS_DATA_23 \ + 0x60 // External sensor data 23 register +#define MPU9150_O_MOT_DETECT_STATUS \ + 0x61 // Motion detection status register +#define MPU9150_O_I2C_SLV0_DO 0x63 // I2C slave 0 output data register +#define MPU9150_O_I2C_SLV1_DO 0x64 // I2C slave 1 output data register +#define MPU9150_O_I2C_SLV2_DO 0x65 // I2C slave 2 output data register +#define MPU9150_O_I2C_SLV3_DO 0x66 // I2C slave 3 output data register +#define MPU9150_O_I2C_MST_DELAY_CTRL \ + 0x67 // I2C master delay control + // register +#define MPU9150_O_SIGNAL_PATH_RESET \ + 0x68 // Signal path reset register +#define MPU9150_O_MOT_DETECT_CTRL \ + 0x69 // Motion detection control + // register +#define MPU9150_O_USER_CTRL 0x6A // User control register +#define MPU9150_O_PWR_MGMT_1 0x6B // Power management 1 register +#define MPU9150_O_PWR_MGMT_2 0x6C // Power management 2 register +#define MPU9150_O_FIFO_COUNTH 0x72 // FIFO count MSB register +#define MPU9150_O_FIFO_COUNTL 0x73 // FIFO count LSB register +#define MPU9150_O_FIFO_R_W 0x74 // FIFO read write register +#define MPU9150_O_WHO_AM_I 0x75 // Who am I register + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_SELF_TEST_X +// register. +// +//***************************************************************************** +#define MPU9150_SELF_TEST_X_XA_TEST_M \ + 0xE0 // Accelerometer XA_TEST[4:2] +#define MPU9150_SELF_TEST_X_XG_TEST_M \ + 0x1F // Gyro XG_TEST[4:0] +#define MPU9150_SELF_TEST_X_XA_TEST_S \ + 5 +#define MPU9150_SELF_TEST_X_XG_TEST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_SELF_TEST_Y +// register. +// +//***************************************************************************** +#define MPU9150_SELF_TEST_Y_YA_TEST_M \ + 0xE0 // Accelerometer YA_TEST[4:2] +#define MPU9150_SELF_TEST_Y_YG_TEST_M \ + 0x1F // Gyro YG_TEST[4:0] +#define MPU9150_SELF_TEST_Y_YA_TEST_S \ + 5 +#define MPU9150_SELF_TEST_Y_YG_TEST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_SELF_TEST_Z +// register. +// +//***************************************************************************** +#define MPU9150_SELF_TEST_Z_ZA_TEST_M \ + 0xE0 // Accelerometer ZA_TEST[4:2] +#define MPU9150_SELF_TEST_Z_ZG_TEST_M \ + 0x1F // Gyro ZG_TEST[4:0] +#define MPU9150_SELF_TEST_Z_ZA_TEST_S \ + 5 +#define MPU9150_SELF_TEST_Z_ZG_TEST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_SELF_TEST_A +// register. +// +//***************************************************************************** +#define MPU9150_SELF_TEST_A_XA_TEST_M \ + 0x30 // Accelerometer XA_TEST[1:0] +#define MPU9150_SELF_TEST_A_YA_TEST_M \ + 0x0C // Accelerometer YA_TEST[1:0] +#define MPU9150_SELF_TEST_A_ZA_TEST_M \ + 0x03 // Accelerometer ZA_TEST[1:0] +#define MPU9150_SELF_TEST_A_XA_TEST_S \ + 4 +#define MPU9150_SELF_TEST_A_YA_TEST_S \ + 2 +#define MPU9150_SELF_TEST_A_ZA_TEST_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_SMPLRT_DIV +// register. +// +//***************************************************************************** +#define MPU9150_SMPLRT_DIV_M 0xFF // Gyro output rate divider +#define MPU9150_SMPLRT_DIV_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_CONFIG +// register. +// +//***************************************************************************** +#define MPU9150_CONFIG_EXT_SYNC_SET_M \ + 0x38 // FSYNC pin sample location +#define MPU9150_CONFIG_EXT_SYNC_SET_DIS \ + 0x00 // FSYNC input disabled +#define MPU9150_CONFIG_EXT_SYNC_SET_TEMP_OUT_L \ + 0x08 // FSYNC on TEMP_OUT_L[0] +#define MPU9150_CONFIG_EXT_SYNC_SET_GYRO_XOUT_L \ + 0x10 // FSYNC on GYRO_XOUT_L[0] +#define MPU9150_CONFIG_EXT_SYNC_SET_GYRO_YOUT_L \ + 0x18 // FSYNC on GYRO_YOUT_L[0] +#define MPU9150_CONFIG_EXT_SYNC_SET_GYRO_ZOUT_L \ + 0x20 // FSYNC on GYRO_ZOUT_L[0] +#define MPU9150_CONFIG_EXT_SYNC_SET_ACCEL_XOUT_L \ + 0x28 // FSYNC on ACCEL_XOUT_L[0] +#define MPU9150_CONFIG_EXT_SYNC_SET_ACCEL_YOUT_L \ + 0x30 // FSYNC on ACCEL_YOUT_L[0] +#define MPU9150_CONFIG_EXT_SYNC_SET_ACCEL_ZOUT_L \ + 0x38 // FSYNC on ACCEL_ZOUT_L[0] +#define MPU9150_CONFIG_DLPF_CFG_M \ + 0x07 // Digital low-pass filter + // configuration +#define MPU9150_CONFIG_DLPF_CFG_260_256 \ + 0x00 // 260 Hz accelerometer bandwidth, + // 256 Hz gyro bandwidth +#define MPU9150_CONFIG_DLPF_CFG_184_188 \ + 0x01 // 184 Hz accelerometer bandwidth, + // 188 Hz gyro bandwidth +#define MPU9150_CONFIG_DLPF_CFG_94_98 \ + 0x02 // 94 Hz accelerometer bandwidth, + // 98 Hz gyro bandwidth +#define MPU9150_CONFIG_DLPF_CFG_44_42 \ + 0x03 // 44 Hz accelerometer bandwidth, + // 42 Hz gyro bandwidth +#define MPU9150_CONFIG_DLPF_CFG_21_20 \ + 0x04 // 21 Hz accelerometer bandwidth, + // 20 Hz gyro bandwidth +#define MPU9150_CONFIG_DLPF_CFG_10_10 \ + 0x05 // 10 Hz accelerometer bandwidth, + // 10 Hz gyro bandwidth +#define MPU9150_CONFIG_DLPF_CFG_5_5 \ + 0x06 // 5 Hz accelerometer bandwidth, 5 + // Hz gyro bandwidth +#define MPU9150_CONFIG_EXT_SYNC_SET_S \ + 3 +#define MPU9150_CONFIG_DLPF_CFG_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_GYRO_CONFIG +// register. +// +//***************************************************************************** +#define MPU9150_GYRO_CONFIG_XG_ST \ + 0x80 // X-axis gyro self-test enable +#define MPU9150_GYRO_CONFIG_YG_ST \ + 0x40 // Y-axis gyro self-test enable +#define MPU9150_GYRO_CONFIG_ZG_ST \ + 0x20 // Z-axis gyro self-test enable +#define MPU9150_GYRO_CONFIG_FS_SEL_M \ + 0x18 // Gyro full-scale range +#define MPU9150_GYRO_CONFIG_FS_SEL_250 \ + 0x00 // Gyro full-scale range +/- 250 + // degrees/sec +#define MPU9150_GYRO_CONFIG_FS_SEL_500 \ + 0x08 // Gyro full-scale range +/- 500 + // degrees/sec +#define MPU9150_GYRO_CONFIG_FS_SEL_1000 \ + 0x10 // Gyro full-scale range +/- 1000 + // degrees/sec +#define MPU9150_GYRO_CONFIG_FS_SEL_2000 \ + 0x18 // Gyro full-scale range +/- 2000 + // degrees/sec +#define MPU9150_GYRO_CONFIG_FS_SEL_S \ + 3 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ACCEL_CONFIG +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_CONFIG_XA_ST \ + 0x80 // X-axis accelerometer self-test + // enable +#define MPU9150_ACCEL_CONFIG_YA_ST \ + 0x40 // Y-axis accelerometer self-test + // enable +#define MPU9150_ACCEL_CONFIG_ZA_ST \ + 0x20 // Z-axis accelerometer self-test + // enable +#define MPU9150_ACCEL_CONFIG_AFS_SEL_M \ + 0x18 // Accelerometer full-scale range +#define MPU9150_ACCEL_CONFIG_AFS_SEL_2G \ + 0x00 // Accelerometer full-scale range 2 + // g +#define MPU9150_ACCEL_CONFIG_AFS_SEL_4G \ + 0x08 // Accelerometer full-scale range 4 + // g +#define MPU9150_ACCEL_CONFIG_AFS_SEL_8G \ + 0x10 // Accelerometer full-scale range 8 + // g +#define MPU9150_ACCEL_CONFIG_AFS_SEL_16G \ + 0x18 // Accelerometer full-scale range + // 16 g +#define MPU9150_ACCEL_CONFIG_ACCEL_HPF_M \ + 0x07 // High-pass filter setting +#define MPU9150_ACCEL_CONFIG_ACCEL_HPF_RESET \ + 0x00 // High-pass filter reset +#define MPU9150_ACCEL_CONFIG_ACCEL_HPF_5HZ \ + 0x01 // High-pass filter at 5 Hz +#define MPU9150_ACCEL_CONFIG_ACCEL_HPF_2_5HZ \ + 0x02 // High-pass filter at 2.5 Hz +#define MPU9150_ACCEL_CONFIG_ACCEL_HPF_1_25HZ \ + 0x03 // High-pass filter at 1.25 Hz +#define MPU9150_ACCEL_CONFIG_ACCEL_HPF_0_63HZ \ + 0x04 // High-pass filter at 0.63 Hz +#define MPU9150_ACCEL_CONFIG_ACCEL_HPF_HOLD \ + 0x07 // High-pass filter hold +#define MPU9150_ACCEL_CONFIG_AFS_SEL_S \ + 3 +#define MPU9150_ACCEL_CONFIG_ACCEL_HPF_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_FF_THR +// register. +// +//***************************************************************************** +#define MPU9150_FF_THR_M 0xFF // Free-fall threshold value +#define MPU9150_FF_THR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_FF_DUR +// register. +// +//***************************************************************************** +#define MPU9150_FF_DUR_M 0xFF // Free-fall duration value +#define MPU9150_FF_DUR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_MOT_THR +// register. +// +//***************************************************************************** +#define MPU9150_MOT_THR_M 0xFF // Motion detection threshold value +#define MPU9150_MOT_THR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_MOT_DUR +// register. +// +//***************************************************************************** +#define MPU9150_MOT_DUR_M 0xFF // Motion detection duration value +#define MPU9150_MOT_DUR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ZRMOT_THR +// register. +// +//***************************************************************************** +#define MPU9150_ZRMOT_THR_M 0xFF // Zero motion detection threshold + // value +#define MPU9150_ZRMOT_THR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ZRMOT_DUR +// register. +// +//***************************************************************************** +#define MPU9150_ZRMOT_DUR_M 0xFF // Zero motion detection duration + // value +#define MPU9150_ZRMOT_DUR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_FIFO_EN +// register. +// +//***************************************************************************** +#define MPU9150_FIFO_EN_TEMP 0x80 // Temperature sensor FIFO enable +#define MPU9150_FIFO_EN_XG 0x40 // X-axis gyro FIFO enable +#define MPU9150_FIFO_EN_YG 0x20 // Y-axis gyro FIFO enable +#define MPU9150_FIFO_EN_ZG 0x10 // Z-axis gyro FIFO enable +#define MPU9150_FIFO_EN_ACCEL 0x08 // Accelerometer FIFO enable +#define MPU9150_FIFO_EN_SLV2 0x04 // Slave 2 FIFO enable +#define MPU9150_FIFO_EN_SLV1 0x02 // Slave 1 FIFO enable +#define MPU9150_FIFO_EN_SLV0 0x01 // Slave 0 FIFO enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_MST_CTRL +// register. +// +//***************************************************************************** +#define MPU9150_I2C_MST_CTRL_MULT_MST_EN \ + 0x80 // Multi-master enable +#define MPU9150_I2C_MST_CTRL_WAIT_FOR_ES \ + 0x40 // Wait for external sensor data +#define MPU9150_I2C_MST_CTRL_SLV3_FIFO_EN \ + 0x20 // Slave 3 FIFO enable +#define MPU9150_I2C_MST_CTRL_I2C_MST_P_NSR \ + 0x10 // No repeated start conditions +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_M \ + 0x0F // I2C master clock speed +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_348 \ + 0x00 // 348 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_333 \ + 0x01 // 333 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_320 \ + 0x02 // 320 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_308 \ + 0x03 // 308 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_296 \ + 0x04 // 296 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_286 \ + 0x05 // 286 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_276 \ + 0x06 // 276 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_267 \ + 0x07 // 267 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_258 \ + 0x08 // 258 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_500 \ + 0x09 // 500 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_471 \ + 0x0A // 471 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_444 \ + 0x0B // 444 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_421 \ + 0x0C // 421 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_400 \ + 0x0D // 400 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_381 \ + 0x0E // 381 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_364 \ + 0x0F // 364 kHz I2C master clock +#define MPU9150_I2C_MST_CTRL_I2C_MST_CLK_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV0_ADDR +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV0_ADDR_RW \ + 0x80 // Read/not write +#define MPU9150_I2C_SLV0_ADDR_M 0x7F // Slave address +#define MPU9150_I2C_SLV0_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV0_REG +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV0_REG_M 0xFF // Slave register number +#define MPU9150_I2C_SLV0_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV0_CTRL +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV0_CTRL_EN \ + 0x80 // Enable slave +#define MPU9150_I2C_SLV0_CTRL_BYTE_SW \ + 0x40 // Byte-swap word pairs +#define MPU9150_I2C_SLV0_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU9150_I2C_SLV0_CTRL_GRP \ + 0x10 // Word pair grouping +#define MPU9150_I2C_SLV0_CTRL_LEN_M \ + 0x0F // Number of bytes to transfer +#define MPU9150_I2C_SLV0_CTRL_LEN_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV1_ADDR +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV1_ADDR_RW \ + 0x80 // Read/not write +#define MPU9150_I2C_SLV1_ADDR_M 0x7F // Slave address +#define MPU9150_I2C_SLV1_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV1_REG +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV1_REG_M 0xFF // Slave register number +#define MPU9150_I2C_SLV1_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV1_CTRL +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV1_CTRL_EN \ + 0x80 // Enable slave +#define MPU9150_I2C_SLV1_CTRL_BYTE_SW \ + 0x40 // Byte-swap word pairs +#define MPU9150_I2C_SLV1_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU9150_I2C_SLV1_CTRL_GRP \ + 0x10 // Word pair grouping +#define MPU9150_I2C_SLV1_CTRL_LEN_M \ + 0x0F // Number of bytes to transfer +#define MPU9150_I2C_SLV1_CTRL_LEN_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV2_ADDR +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV2_ADDR_RW \ + 0x80 // Read/not write +#define MPU9150_I2C_SLV2_ADDR_M 0x7F // Slave address +#define MPU9150_I2C_SLV2_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV2_REG +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV2_REG_M 0xFF // Slave register number +#define MPU9150_I2C_SLV2_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV2_CTRL +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV2_CTRL_EN \ + 0x80 // Enable slave +#define MPU9150_I2C_SLV2_CTRL_BYTE_SW \ + 0x40 // Byte-swap word pairs +#define MPU9150_I2C_SLV2_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU9150_I2C_SLV2_CTRL_GRP \ + 0x10 // Word pair grouping +#define MPU9150_I2C_SLV2_CTRL_LEN_M \ + 0x0F // Number of bytes to transfer +#define MPU9150_I2C_SLV2_CTRL_LEN_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV3_ADDR +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV3_ADDR_RW \ + 0x80 // Read/not write +#define MPU9150_I2C_SLV3_ADDR_M 0x7F // Slave address +#define MPU9150_I2C_SLV3_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV3_REG +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV3_REG_M 0xFF // Slave register number +#define MPU9150_I2C_SLV3_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV3_CTRL +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV3_CTRL_EN \ + 0x80 // Enable slave +#define MPU9150_I2C_SLV3_CTRL_BYTE_SW \ + 0x40 // Byte-swap word pairs +#define MPU9150_I2C_SLV3_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU9150_I2C_SLV3_CTRL_GRP \ + 0x10 // Word pair grouping +#define MPU9150_I2C_SLV3_CTRL_LEN_M \ + 0x0F // Number of bytes to transfer +#define MPU9150_I2C_SLV3_CTRL_LEN_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV4_ADDR +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV4_ADDR_RW \ + 0x80 // Read/not write +#define MPU9150_I2C_SLV4_ADDR_M 0x7F // Slave address +#define MPU9150_I2C_SLV4_ADDR_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV4_REG +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV4_REG_M 0xFF // Slave register number +#define MPU9150_I2C_SLV4_REG_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV4_CTRL +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV4_CTRL_EN \ + 0x80 // Enable slave +#define MPU9150_I2C_SLV4_CTRL_INT_EN \ + 0x40 // Interrupt enable +#define MPU9150_I2C_SLV4_CTRL_REG_DIS \ + 0x20 // Disable register number transfer +#define MPU9150_I2C_SLV4_CTRL_I2C_MST_DLY_M \ + 0x1F // Slave access delay +#define MPU9150_I2C_SLV4_CTRL_I2C_MST_DLY_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV4_DI +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV4_DI_M 0xFF // Input data +#define MPU9150_I2C_SLV4_DI_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_MST_STATUS +// register. +// +//***************************************************************************** +#define MPU9150_I2C_MST_STATUS_PASS_THROUGH \ + 0x80 // Pass through FSYNC interrupt + // status +#define MPU9150_I2C_MST_STATUS_I2C_SLV4_DONE \ + 0x40 // I2C slave 4 completion status +#define MPU9150_I2C_MST_STATUS_I2C_LOST_ARB \ + 0x20 // I2C arbitration lost status +#define MPU9150_I2C_MST_STATUS_I2C_SLV4_NACK \ + 0x10 // I2C slave 4 NACK status +#define MPU9150_I2C_MST_STATUS_I2C_SLV3_NACK \ + 0x08 // I2C slave 3 NACK status +#define MPU9150_I2C_MST_STATUS_I2C_SLV2_NACK \ + 0x04 // I2C slave 2 NACK status +#define MPU9150_I2C_MST_STATUS_I2C_SLV1_NACK \ + 0x02 // I2C slave 1 NACK status +#define MPU9150_I2C_MST_STATUS_I2C_SLV0_NACK \ + 0x01 // I2C slave 0 NACK status + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_INT_PIN_CFG +// register. +// +//***************************************************************************** +#define MPU9150_INT_PIN_CFG_INT_LEVEL \ + 0x80 // INT pin active low +#define MPU9150_INT_PIN_CFG_INT_OPEN \ + 0x40 // INT pin open-drain +#define MPU9150_INT_PIN_CFG_LATCH_INT_EN \ + 0x20 // Latch INT pin output +#define MPU9150_INT_PIN_CFG_INT_RD_CLEAR \ + 0x10 // Interrupt clear on any read +#define MPU9150_INT_PIN_CFG_FSYNC_INT_LEVEL \ + 0x08 // FSYNC pin active low +#define MPU9150_INT_PIN_CFG_FSYNC_INT_EN \ + 0x04 // FSYNC pin interrupt enable +#define MPU9150_INT_PIN_CFG_I2C_BYPASS_EN \ + 0x02 // I2C bypass enable +#define MPU9150_INT_PIN_CFG_CLKOUT_EN \ + 0x01 // CLKOUT enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_INT_ENABLE +// register. +// +//***************************************************************************** +#define MPU9150_INT_ENABLE_FF_EN \ + 0x80 // Free-fall interrupt enable +#define MPU9150_INT_ENABLE_MOT_EN \ + 0x40 // Motion detection interrupt + // enable +#define MPU9150_INT_ENABLE_ZMOT_EN \ + 0x20 // Zero motion interrupt enable +#define MPU9150_INT_ENABLE_FIFO_OFLOW_EN \ + 0x10 // FIFO overflow interrupt enable +#define MPU9150_INT_ENABLE_I2C_MST_INT_EN \ + 0x08 // I2C master interrupt enable +#define MPU9150_INT_ENABLE_DATA_RDY_EN \ + 0x01 // Data ready interrupt enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_INT_STATUS +// register. +// +//***************************************************************************** +#define MPU9150_INT_STATUS_FF_INT \ + 0x80 // Free-fall interrupt status +#define MPU9150_INT_STATUS_MOT_INT \ + 0x40 // Motion detection interrupt + // status +#define MPU9150_INT_STATUS_ZMOT_INT \ + 0x20 // Zero motion interrupt status +#define MPU9150_INT_STATUS_FIFO_OFLOW_INT \ + 0x10 // FIFO overflow interrupt status +#define MPU9150_INT_STATUS_I2C_MST_INT \ + 0x08 // I2C master interrupt status +#define MPU9150_INT_STATUS_DATA_RDY_INT \ + 0x01 // Data ready interrupt status + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ACCEL_XOUT_H +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_XOUT_H_M 0xFF // Bits [15:8] of X-axis + // acceleration data +#define MPU9150_ACCEL_XOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ACCEL_XOUT_L +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_XOUT_L_M 0xFF // Bits [7:0] of X-axis + // acceleration data +#define MPU9150_ACCEL_XOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ACCEL_YOUT_H +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_YOUT_H_M 0xFF // Bits [15:8] of Y-axis + // acceleration data +#define MPU9150_ACCEL_YOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ACCEL_YOUT_L +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_YOUT_L_M 0xFF // Bits [7:0] of Y-axis + // acceleration data +#define MPU9150_ACCEL_YOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ACCEL_ZOUT_H +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_ZOUT_H_M 0xFF // Bits [15:8] of Z-axis + // acceleration data +#define MPU9150_ACCEL_ZOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_ACCEL_ZOUT_L +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_ZOUT_L_M 0xFF // Bits [7:0] of Z-axis + // acceleration data +#define MPU9150_ACCEL_ZOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_TEMP_OUT_H +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_TEMP_OUT_H_M \ + 0xFF // Bits [15:8] of temperature data +#define MPU9150_ACCEL_TEMP_OUT_H_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_TEMP_OUT_L +// register. +// +//***************************************************************************** +#define MPU9150_ACCEL_TEMP_OUT_L_M \ + 0xFF // Bits [7:0] of temperature data +#define MPU9150_ACCEL_TEMP_OUT_L_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_GYRO_XOUT_H +// register. +// +//***************************************************************************** +#define MPU9150_GYRO_XOUT_H_M 0xFF // Bits [15:8] of X-axis gyro data +#define MPU9150_GYRO_XOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_GYRO_XOUT_L +// register. +// +//***************************************************************************** +#define MPU9150_GYRO_XOUT_L_M 0xFF // Bits [7:0] of X-axis gyro data +#define MPU9150_GYRO_XOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_GYRO_YOUT_H +// register. +// +//***************************************************************************** +#define MPU9150_GYRO_YOUT_H_M 0xFF // Bits [15:8] of Y-axis gyro data +#define MPU9150_GYRO_YOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_GYRO_YOUT_L +// register. +// +//***************************************************************************** +#define MPU9150_GYRO_YOUT_L_M 0xFF // Bits [7:0] of Y-axis gyro data +#define MPU9150_GYRO_YOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_GYRO_ZOUT_H +// register. +// +//***************************************************************************** +#define MPU9150_GYRO_ZOUT_H_M 0xFF // Bits [15:8] of Z-axis gyro data +#define MPU9150_GYRO_ZOUT_H_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_GYRO_ZOUT_L +// register. +// +//***************************************************************************** +#define MPU9150_GYRO_ZOUT_L_M 0xFF // Bits [7:0] of Z-axis gyro data +#define MPU9150_GYRO_ZOUT_L_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_00 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_00_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_00_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_01 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_01_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_01_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_02 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_02_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_02_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_03 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_03_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_03_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_04 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_04_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_04_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_05 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_05_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_05_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_06 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_06_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_06_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_07 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_07_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_07_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_08 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_08_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_08_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_09 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_09_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_09_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_10 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_10_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_10_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_11 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_11_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_11_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_12 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_12_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_12_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_13 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_13_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_13_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_14 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_14_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_14_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_15 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_15_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_15_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_16 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_16_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_16_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_17 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_17_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_17_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_18 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_18_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_18_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_19 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_19_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_19_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_20 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_20_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_20_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_21 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_21_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_21_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_22 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_22_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_22_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_EXT_SENS_DATA_23 register. +// +//***************************************************************************** +#define MPU9150_EXT_SENS_DATA_23_M \ + 0xFF // External sensor data +#define MPU9150_EXT_SENS_DATA_23_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_MOT_DETECT_STATUS register. +// +//***************************************************************************** +#define MPU9150_MOT_DETECT_STATUS_MOT_XNEG \ + 0x80 // Negative X-axis motion detect + // status +#define MPU9150_MOT_DETECT_STATUS_MOT_XPOS \ + 0x40 // Positive X-axis motion detect + // status +#define MPU9150_MOT_DETECT_STATUS_MOT_YNEG \ + 0x20 // Negative Y-axis motion detect + // status +#define MPU9150_MOT_DETECT_STATUS_MOT_YPOS \ + 0x10 // Positive Y-axis motion detect + // status +#define MPU9150_MOT_DETECT_STATUS_MOT_ZNEG \ + 0x08 // Negative Z-axis motion detect + // status +#define MPU9150_MOT_DETECT_STATUS_MOT_ZPOS \ + 0x04 // Positive Z-axis motion detect + // status +#define MPU9150_MOT_DETECT_STATUS_MOT_ZRMOT \ + 0x01 // Zero motion detect status + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV0_DO +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV0_DO_M 0xFF // Output data +#define MPU9150_I2C_SLV0_DO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV1_DO +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV1_DO_M 0xFF // Output data +#define MPU9150_I2C_SLV1_DO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV2_DO +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV2_DO_M 0xFF // Output data +#define MPU9150_I2C_SLV2_DO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_I2C_SLV3_DO +// register. +// +//***************************************************************************** +#define MPU9150_I2C_SLV3_DO_M 0xFF // Output data +#define MPU9150_I2C_SLV3_DO_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_I2C_MST_DELAY_CTRL register. +// +//***************************************************************************** +#define MPU9150_I2C_MST_DELAY_CTRL_DELAY_ES_SHADOW \ + 0x80 // Delay external sensor data +#define MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV4_DLY_EN \ + 0x10 // I2C slave 4 delay enable +#define MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV3_DLY_EN \ + 0x08 // I2C slave 3 delay enable +#define MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV2_DLY_EN \ + 0x04 // I2C slave 2 delay enable +#define MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV1_DLY_EN \ + 0x02 // I2C slave 1 delay enable +#define MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV0_DLY_EN \ + 0x01 // I2C slave 0 delay enable + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_SIGNAL_PATH_RESET register. +// +//***************************************************************************** +#define MPU9150_SIGNAL_PATH_RESET_GYRO \ + 0x04 // Reset gyro +#define MPU9150_SIGNAL_PATH_RESET_ACCEL \ + 0x02 // Reset accelerometer +#define MPU9150_SIGNAL_PATH_RESET_TEMP \ + 0x01 // Reset temperature sensor + +//***************************************************************************** +// +// The following are defines for the bit fields in the +// MPU9150_O_MOT_DETECT_CTRL register. +// +//***************************************************************************** +#define MPU9150_MOT_DETECT_CTRL_ACCEL_ON_DELAY_M \ + 0x30 // Accelerometer wake-up delay +#define MPU9150_MOT_DETECT_CTRL_ACCEL_ON_DELAY_4MS \ + 0x00 // Delay 4 ms +#define MPU9150_MOT_DETECT_CTRL_ACCEL_ON_DELAY_5MS \ + 0x10 // Delay 5 ms +#define MPU9150_MOT_DETECT_CTRL_ACCEL_ON_DELAY_6MS \ + 0x20 // Delay 6 ms +#define MPU9150_MOT_DETECT_CTRL_ACCEL_ON_DELAY_7MS \ + 0x30 // Delay 7 ms +#define MPU9150_MOT_DETECT_CTRL_FF_COUNT_M \ + 0x0C // Free-fall counter decrement rate +#define MPU9150_MOT_DETECT_CTRL_FF_COUNT_RESET \ + 0x00 // Reset counter +#define MPU9150_MOT_DETECT_CTRL_FF_COUNT_1 \ + 0x04 // Decrement by 1 +#define MPU9150_MOT_DETECT_CTRL_FF_COUNT_2 \ + 0x08 // Decrement by 2 +#define MPU9150_MOT_DETECT_CTRL_FF_COUNT_4 \ + 0x0C // Decrement by 4 +#define MPU9150_MOT_DETECT_CTRL_MOT_COUNT_M \ + 0x03 // Motion detect counter decrement + // rate +#define MPU9150_MOT_DETECT_CTRL_MOT_COUNT_RESET \ + 0x00 // Reset counter +#define MPU9150_MOT_DETECT_CTRL_MOT_COUNT_1 \ + 0x04 // Decrement by 1 +#define MPU9150_MOT_DETECT_CTRL_MOT_COUNT_2 \ + 0x08 // Decrement by 2 +#define MPU9150_MOT_DETECT_CTRL_MOT_COUNT_4 \ + 0x0C // Decrement by 4 +#define MPU9150_MOT_DETECT_CTRL_ACCEL_ON_DELAY_S \ + 4 +#define MPU9150_MOT_DETECT_CTRL_FF_COUNT_S \ + 2 +#define MPU9150_MOT_DETECT_CTRL_MOT_COUNT_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_USER_CTRL +// register. +// +//***************************************************************************** +#define MPU9150_USER_CTRL_FIFO_EN \ + 0x40 // FIFO enable +#define MPU9150_USER_CTRL_I2C_MST_EN \ + 0x20 // I2C master mode enable +#define MPU9150_USER_CTRL_I2C_IF_DIS \ + 0x10 // Write as zero +#define MPU9150_USER_CTRL_FIFO_RESET \ + 0x04 // Reset FIFO buffer +#define MPU9150_USER_CTRL_I2C_MST_RESET \ + 0x02 // Reset I2C master +#define MPU9150_USER_CTRL_SIG_COND_RESET \ + 0x01 // Reset all sensors + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_PWR_MGMT_1 +// register. +// +//***************************************************************************** +#define MPU9150_PWR_MGMT_1_DEVICE_RESET \ + 0x80 // Device reset +#define MPU9150_PWR_MGMT_1_SLEEP \ + 0x40 // Enter sleep mode +#define MPU9150_PWR_MGMT_1_CYCLE \ + 0x20 // Enable automatic sleep +#define MPU9150_PWR_MGMT_1_TEMP_DIS \ + 0x08 // Disable temperature sensor +#define MPU9150_PWR_MGMT_1_CLKSEL_M \ + 0x07 // Clock source select +#define MPU9150_PWR_MGMT_1_CLKSEL_INT \ + 0x00 // Internal 8 MHz oscillator +#define MPU9150_PWR_MGMT_1_CLKSEL_XG \ + 0x01 // PLL with X-axis gyro reference +#define MPU9150_PWR_MGMT_1_CLKSEL_YG \ + 0x02 // PLL with Y-axis gyro reference +#define MPU9150_PWR_MGMT_1_CLKSEL_ZG \ + 0x03 // PLL with Z-axis gyro reference +#define MPU9150_PWR_MGMT_1_CLKSEL_EXT32K \ + 0x04 // PLL with external 32.768 kHz + // reference +#define MPU9150_PWR_MGMT_1_CLKSEL_EXT19M \ + 0x05 // PLL with external 19.2 MHz + // reference +#define MPU9150_PWR_MGMT_1_CLKSEL_STOP \ + 0x07 // Clock disable +#define MPU9150_PWR_MGMT_1_CLKSEL_S \ + 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_PWR_MGMT_2 +// register. +// +//***************************************************************************** +#define MPU9150_PWR_MGMT_2_LP_WAKE_CTRL_M \ + 0xC0 // Wake-up frequency +#define MPU9150_PWR_MGMT_2_LP_WAKE_CTRL_1_25 \ + 0x00 // Wake-up at 1.25 Hz +#define MPU9150_PWR_MGMT_2_LP_WAKE_CTRL_5 \ + 0x40 // Wake-up at 5 Hz +#define MPU9150_PWR_MGMT_2_LP_WAKE_CTRL_20 \ + 0x80 // Wake-up at 20 Hz +#define MPU9150_PWR_MGMT_2_LP_WAKE_CTRL_40 \ + 0xC0 // Wake-up at 40 Hz +#define MPU9150_PWR_MGMT_2_STBY_XA \ + 0x20 // Put X-axis accelerometer into + // standby mode +#define MPU9150_PWR_MGMT_2_STBY_YA \ + 0x10 // Put Y-axis accelerometer into + // standby mode +#define MPU9150_PWR_MGMT_2_STBY_ZA \ + 0x08 // Put Z-axis accelerometer into + // standby mode +#define MPU9150_PWR_MGMT_2_STBY_XG \ + 0x04 // Put X-axis gyro into standby + // mode +#define MPU9150_PWR_MGMT_2_STBY_YG \ + 0x02 // Put Y-axis gyro into standby + // mode +#define MPU9150_PWR_MGMT_2_STBY_ZG \ + 0x01 // Put Z-axis gyro into standby + // mode +#define MPU9150_PWR_MGMT_2_LP_WAKE_CTRL_S \ + 6 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_FIFO_COUNTH +// register. +// +//***************************************************************************** +#define MPU9150_FIFO_COUNTH_M 0x07 // FIFO count [10:8] +#define MPU9150_FIFO_COUNTH_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_FIFO_COUNTL +// register. +// +//***************************************************************************** +#define MPU9150_FIFO_COUNTL_M 0xFF // FIFO count [7:0] +#define MPU9150_FIFO_COUNTL_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_FIFO_R_W +// register. +// +//***************************************************************************** +#define MPU9150_FIFO_R_W_M 0xFF // FIFO data +#define MPU9150_FIFO_R_W_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the MPU9150_O_WHO_AM_I +// register. +// +//***************************************************************************** +#define MPU9150_WHO_AM_I_M 0x7E // I2C address +#define MPU9150_WHO_AM_I_MPU9150 \ + 0x68 // MPU9150 +#define MPU9150_WHO_AM_I_S 1 + +#endif // __SENSORLIB_HW_MPU9150_H__ diff --git a/sensorlib/hw_sht21.h b/sensorlib/hw_sht21.h new file mode 100644 index 0000000..550af75 --- /dev/null +++ b/sensorlib/hw_sht21.h @@ -0,0 +1,76 @@ +//***************************************************************************** +// +// hw_sht21.h - Macros used for accessing the Intersil SHT21 humidity sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_SHT21_H__ +#define __SENSORLIB_HW_SHT21_H__ + +//***************************************************************************** +// +// The following are defines for the SHT21 Commands and Registers +// +//***************************************************************************** +#define SHT21_CMD_MEAS_T_HOLD 0xE3 // Measure temperatue with I2C bus + // hold +#define SHT21_CMD_MEAS_RH_HOLD 0xE5 // Measure humidity with I2C bus + // hold +#define SHT21_CMD_WRITE_CONFIG 0xE6 // Write the user config register +#define SHT21_CMD_READ_CONFIG 0xE7 // Read the user config register +#define SHT21_CMD_MEAS_T 0xF3 // Measure temperature polled +#define SHT21_CMD_MEAS_RH 0xF5 // Measure humidity polled +#define SHT21_CMD_SOFT_RESET 0xFE // Perform a device reset + +//***************************************************************************** +// +// The following are defines for the bit fields in the SHT21_CONFIG register. +// +//***************************************************************************** +#define SHT21_CONFIG_RES_M 0x81 // Resolution config for + // temperature and humidity +#define SHT21_CONFIG_RES_12 0x00 // RH 12 bit, T 14 bit +#define SHT21_CONFIG_RES_8 0x01 // RH 8 bit, T 12 bit +#define SHT21_CONFIG_RES_10 0x80 // RH 10 bit, T 13 bit +#define SHT21_CONFIG_RES_11 0x81 // RH 11 bit, T 11 bit +#define SHT21_CONFIG_BATT_M 0x40 // Battery status indicator +#define SHT21_CONFIG_BATT_GOOD 0x00 +#define SHT21_CONFIG_BATT_LOW 0x40 +#define SHT21_CONFIG_HEATER_M 0x04 // On chip heater for test and + // diagnostics +#define SHT21_CONFIG_HEATER_DISABLE \ + 0x00 // Heater off +#define SHT21_CONFIG_HEATER_ENABLE \ + 0x04 // Heater on +#define SHT21_CONFIG_OTP_RELOAD_M \ + 0x02 // OTP reload control; soft reset + // is preferred +#define SHT21_CONFIG_OTP_RELOAD_ENABLE \ + 0x00 // OTP reload enabled +#define SHT21_CONFIG_OTP_RELOAD_DISABLE \ + 0x02 // OTP reload disabled +#define SHT21_CONFIG_BATT_S 6 +#define SHT21_CONFIG_HEATER_S 2 +#define SHT21_CONFIG_OTP_RELOAD_S \ + 1 +#define SHT21_CONFIG_RES_S 0 + +#endif // __SENSORLIB_HW_SHT21_H__ diff --git a/sensorlib/hw_tmp006.h b/sensorlib/hw_tmp006.h new file mode 100644 index 0000000..6c350c8 --- /dev/null +++ b/sensorlib/hw_tmp006.h @@ -0,0 +1,75 @@ +//***************************************************************************** +// +// hw_tmp006.h - Macros used when accessing the Texas Instruments TMP006 +// Infrared Temperature Sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_TMP006_H__ +#define __SENSORLIB_HW_TMP006_H__ + +//***************************************************************************** +// +// The following are defines for the TMP006 Register Addresses +// +//***************************************************************************** +#define TMP006_O_VOBJECT 0x00 // Raw object voltage measurement +#define TMP006_O_TAMBIENT 0x01 // Die temperature of the TMP006 +#define TMP006_O_CONFIG 0x02 // TMP006 Configuration +#define TMP006_O_MFG_ID 0xFE // TMP006 Manufacture + // Identification +#define TMP006_O_DEV_ID 0xFF // TMP006 Device Identification + +//***************************************************************************** +// +// The following are defines for the bit fields in the TMP006_O_CONFIG +// register. +// +//***************************************************************************** +#define TMP006_CONFIG_RESET_M 0x8000 // TMP006 device reset +#define TMP006_CONFIG_RESET_ASSERT \ + 0x8000 // Reset TMP006; self clearing +#define TMP006_CONFIG_MODE_M 0x7000 // Operation mode +#define TMP006_CONFIG_MODE_PD 0x0000 // Power down +#define TMP006_CONFIG_MODE_CONT 0x7000 // Continuous sampling +#define TMP006_CONFIG_CR_M 0x0E00 // Conversion rate setting +#define TMP006_CONFIG_CR_4 0x0000 // 4Hz conversion rate +#define TMP006_CONFIG_CR_2 0x0200 // 2Hz conversion rate +#define TMP006_CONFIG_CR_1 0x0400 // 1Hz conversion rate +#define TMP006_CONFIG_CR_0_5 0x0600 // 0.5Hz conversion rate +#define TMP006_CONFIG_CR_0_25 0x0800 // 0.25Hz conversion rate +#define TMP006_CONFIG_EN_DRDY_PIN_M \ + 0x0100 // Enable the DRDY output pin +#define TMP006_CONFIG_DIS_DRDY_PIN \ + 0x0000 // DRDY pin disabled +#define TMP006_CONFIG_EN_DRDY_PIN \ + 0x0100 // DRDY pin enabled +#define TMP006_CONFIG_DRDY_M 0x0080 // Data ready flag +#define TMP006_CONFIG_IN_PROG 0x0000 // Conversion in progress +#define TMP006_CONFIG_DRDY 0x0080 // Conversion complete +#define TMP006_CONFIG_RESET_S 15 +#define TMP006_CONFIG_MODE_S 12 +#define TMP006_CONFIG_CR_S 9 +#define TMP006_CONFIG_EN_DRDY_PIN_S \ + 8 +#define TMP006_CONFIG_DRDY_S 7 + +#endif // __SENSORLIB_HW_TMP006_H__ diff --git a/sensorlib/hw_tmp100.h b/sensorlib/hw_tmp100.h new file mode 100644 index 0000000..5debb87 --- /dev/null +++ b/sensorlib/hw_tmp100.h @@ -0,0 +1,93 @@ +//***************************************************************************** +// +// hw_tmp100.h - Macros used when accessing the Texas Instruments TMP100 +// Temperature Sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_HW_TMP100_H__ +#define __SENSORLIB_HW_TMP100_H__ + +//***************************************************************************** +// +// The following are defines for the TMP100 Register Addresses +// +//***************************************************************************** +#define TMP100_O_TEMP 0x00 // Temperature register +#define TMP100_O_CONFIG 0x01 // Configuration register +#define TMP100_O_TEMP_LOW 0x02 // Temperature low register +#define TMP100_O_TEMP_HIGH 0x03 // Temperature high register + +//***************************************************************************** +// +// The following are defines for the bit fields in the TMP100_O_TEMP register. +// +//***************************************************************************** +#define TMP100_TEMP_M 0xFFFF // Temperature data +#define TMP100_TEMP_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TMP100_O_CONFIG +// register. +// +//***************************************************************************** +#define TMP100_CONFIG_OS_ALERT 0x80 // Starts a one-shot when written, + // reports alert when read +#define TMP100_CONFIG_RES_M 0x60 // Converter resolution +#define TMP100_CONFIG_RES_9BIT 0x00 // 9-bit resolution (40 ms + // conversion time) +#define TMP100_CONFIG_RES_10BIT 0x20 // 10-bit resolution (80 ms + // conversion time) +#define TMP100_CONFIG_RES_11BIT 0x40 // 11-bit resolution (160 ms + // conversion time) +#define TMP100_CONFIG_RES_12BIT 0x60 // 12-bit resolution (320 ms + // conversion time) +#define TMP100_CONFIG_CR_M 0x18 // Consecutive fault configuration +#define TMP100_CONFIG_FAULT_1 0x00 // 1 consecutive fault +#define TMP100_CONFIG_FAULT_2 0x08 // 2 consecutive faults +#define TMP100_CONFIG_FAULT_4 0x10 // 4 consecutive faults +#define TMP100_CONFIG_FAULT_6 0x18 // 6 consecutive faults +#define TMP100_CONFIG_POL 0x04 // Alert pin polarity +#define TMP100_CONFIG_TM 0x02 // Thermostat mode +#define TMP100_CONFIG_SD 0x01 // Shutdown mode +#define TMP100_CONFIG_RES_S 5 +#define TMP100_CONFIG_FAULT_S 3 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TMP100_O_TEMP_LOW +// register. +// +//***************************************************************************** +#define TMP100_TEMP_LOW_M 0xFFFF // Temperature low data +#define TMP100_TEMP_LOW_S 0 + +//***************************************************************************** +// +// The following are defines for the bit fields in the TMP100_O_TEMP_HIGH +// register. +// +//***************************************************************************** +#define TMP100_TEMP_HIGH_M 0xFFFF // Temperature high data +#define TMP100_TEMP_HIGH_S 0 + +#endif // __SENSORLIB_HW_TMP100_H__ diff --git a/sensorlib/i2cm_drv.c b/sensorlib/i2cm_drv.c new file mode 100644 index 0000000..1e603e2 --- /dev/null +++ b/sensorlib/i2cm_drv.c @@ -0,0 +1,2256 @@ +//***************************************************************************** +// +// i2cm_drv.c - Interrupt-driven I2C master driver. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include +#include "inc/hw_i2c.h" +#include "inc/hw_memmap.h" +#include "inc/hw_types.h" +#include "driverlib/debug.h" +#include "driverlib/i2c.h" +#include "driverlib/interrupt.h" +#include "driverlib/rom.h" +#include "driverlib/rom_map.h" +#include "sensorlib/i2cm_drv.h" + +//***************************************************************************** +// +//! \addtogroup i2cm_drv_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states in the interrupt handler state machine. +// +//***************************************************************************** +#define STATE_IDLE 0 +#define STATE_WRITE_NEXT 1 +#define STATE_WRITE_FINAL 2 +#define STATE_WRITE_PAUSE 3 +#define STATE_READ_ONE 4 +#define STATE_READ_FIRST 5 +#define STATE_READ_NEXT 6 +#define STATE_READ_FINAL 7 +#define STATE_READ_PAUSE 8 +#define STATE_READ_WAIT 9 +#define STATE_CALLBACK 10 + +//***************************************************************************** +// +// The states in the I2C read-modify-write state machine. +// +//***************************************************************************** +#define I2CM_RMW_STATE_IDLE 0 +#define I2CM_RMW_STATE_READ 1 +#define I2CM_RMW_STATE_WRITE 2 + +//***************************************************************************** +// +//! Writes data to an I2C device. +//! +//! \param psInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param pui8Data is a pointer to the data buffer to be written. +//! \param ui16Count is the number of bytes to be written. +//! \param pfnCallback is the function to be called when the write has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function adds an I2C write to the queue of commands to be sent. If +//! successful, the I2C write is then performed in the background using the +//! interrupt handler. When the write is complete, the callback function, if +//! provided, is called in the context of the I2C master interrupt handler. +//! +//! The first byte of the data buffer contains the I2C address of the device to +//! access, and the remaining \e ui16Count bytes contain the data to be written +//! to the device. The \e ui16Count parameter can be zero if there are no +//! bytes to be written. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +// The extern here provides a non-inline definition for this function to handle +// the case where the compiler chooses not to inline the function (which is a +// valid choice for the compiler to make). +// +//***************************************************************************** +extern uint_fast8_t I2CMWrite(tI2CMInstance *psInst, uint_fast8_t ui8Addr, + const uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback pfnCallback, + void *pvCallbackData); + +//***************************************************************************** +// +//! Reads data from an I2C device. +//! +//! \param psInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param pui8WriteData is a pointer to the data buffer to be written. +//! \param ui16WriteCount is the number of bytes to be written. +//! \param pui8ReadData is a pointer to the buffer to be filled with the read +//! data. +//! \param ui16ReadCount is the number of bytes to be read. +//! \param pfnCallback is the function to be called when the transfer has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function adds an I2C read to the queue of commands to be sent. If +//! successful, the I2C read is then performed in the background using the +//! interrupt handler. When the read is complete, the callback function, if +//! provided, is called in the context of the I2C master interrupt handler. +//! +//! The first byte of \e pui8WriteData contains the I2C address of the device +//! to access, the next \e ui16WriteCount bytes contains the data to be written +//! to the device. The data read from the device is written into the first +//! \e ui16ReadCount bytes of \e pui8ReadData. The \e ui16WriteCount or +//! \e ui16ReadCount parameters can be zero if there are no bytes to be read or +//! written. The write bytes are sent to the device first, and then the read +//! bytes are read from the device afterward. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +// The extern here provides a non-inline definition for this function to handle +// the case where the compiler chooses not to inline the function (which is a +// valid choice for the compiler to make). +// +//***************************************************************************** +extern uint_fast8_t I2CMRead(tI2CMInstance *psInst, uint_fast8_t ui8Addr, + const uint8_t *pui8WriteData, + uint_fast16_t ui16WriteCount, + uint8_t *pui8ReadData, + uint_fast16_t ui16ReadCount, + tSensorCallback pfnCallback, + void *pvCallbackData); + +//***************************************************************************** +// +//! Writes data in batches to an I2C device. +//! +//! \param psInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param pui8Data is a pointer to the data buffer to be written. +//! \param ui16Count is the number of bytes to be written. +//! \param ui16BatchSize is the number of bytes in each write batch. +//! \param pfnCallback is the function to be called when the transfer has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function adds an I2C write to the queue of commands to be sent. If +//! successful, the I2C write is then performed in the background using the +//! interrupt handler. When the write is complete, the callback function, if +//! provided, is called in the context of the I2C master interrupt handler. +//! +//! The first byte of the data buffer contains the I2C address of the device to +//! access, and the remaining \e ui16Count bytes contain the data to be written +//! to the device. The \e ui16Count parameter can be zero if there are no +//! bytes to be written. +//! +//! The data is written in batches of \e ui16WriteBatchSize. The callback +//! function is called after each batch is written, and I2CMTransferResume() +//! must be called when the next batch should be written. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +// The extern here provides a non-inline definition for this function to handle +// the case where the compiler chooses not to inline the function (which is a +// valid choice for the compiler to make). +// +//***************************************************************************** +extern uint_fast8_t I2CMWriteBatched(tI2CMInstance *psInst, + uint_fast8_t ui8Addr, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + uint_fast16_t ui16BatchSize, + tSensorCallback pfnCallback, + void *pvCallbackData); + +//***************************************************************************** +// +//! Reads data in batches from an I2C device. +//! +//! \param psInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param pui8WriteData is a pointer to the data buffer to be written. +//! \param ui16WriteCount is the number of bytes to be written. +//! \param ui16WriteBatchSize is the number of bytes in each write batch. +//! \param pui8ReadData is a pointer to the buffer to be filled with the read +//! data. +//! \param ui16ReadCount is the number of bytes to be read. +//! \param ui16ReadBatchSize is the number of bytes in each read batch. +//! \param pfnCallback is the function to be called when the transfer has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function adds an I2C read to the queue of commands to be sent. If +//! successful, the I2C read is then performed in the background using the +//! interrupt handler. When the read is complete, the callback function, if +//! provided, is called in the context of the I2C master interrupt handler. +//! +//! The first byte of \e pui8WriteData contains the I2C address of the device +//! to access, the next \e ui16WriteCount bytes contains the data to be written +//! to the device. The data read from the device is written into the first +//! \e ui16ReadCount bytes of \e pui8ReadData. The \e ui16WriteCount or +//! \e ui16ReadCount parameters can be zero if there are no bytes to be read or +//! written. The write bytes are sent to the device first, and then the read +//! bytes are read from the device afterward. +//! +//! The data is written in batches of \e ui16WriteBatchSize. The callback +//! function is called after each batch is written, and I2CMTransferResume() +//! must be called when the next batch should be written. +//! +//! The data is read in batches of \e ui16ReadBatchSize. The callback function +//! is called after each batch is read, and I2CMTransferResume() must be called +//! when the next batch should be read. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +// The extern here provides a non-inline definition for this function to handle +// the case where the compiler chooses not to inline the function (which is a +// valid choice for the compiler to make). +// +//***************************************************************************** +extern uint_fast8_t I2CMReadBatched(tI2CMInstance *psInst, + uint_fast8_t ui8Addr, + const uint8_t *pui8WriteData, + uint_fast16_t ui16WriteCount, + uint_fast16_t ui16WriteBatchSize, + uint8_t *pui8ReadData, + uint_fast16_t ui16ReadCount, + uint_fast16_t ui16ReadBatchSize, + tSensorCallback pfnCallback, + void *pvCallbackData); + +//***************************************************************************** +// +//! Performs a read-modify-write of 16 bits of big-endian data in an I2C +//! device. +//! +//! \param psInst is a pointer to the read-modify-write instance data. +//! \param psI2CInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param ui8Reg is the register in the I2C device to access. +//! \param ui16Mask is the mask indicating the register bits that should be +//! maintained. +//! \param ui16Value is the value indicating the new value for the register +//! bits that are not maintained. +//! \param pfnCallback is the function to be called when the write has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read-modify-write transaction of 16 bits of +//! big-endian data in an I2C device. The modify portion of the operation is +//! performed by AND-ing the register value with \e ui16Mask and then OR-ing +//! the result with \e ui16Value. When the read-modify-write is complete, the +//! callback function, if provided, is called in the context of the I2C master +//! interrupt handler. +//! +//! If the mask (in \e ui16Mask) is zero, then none of the bits in the current +//! register value are maintained. In this case, the read portion of the +//! read-modify-write is bypassed, and the new register value (in \e ui16Value) +//! is directly written to the I2C device. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +// The extern here provides a non-inline definition for this function to handle +// the case where the compiler chooses not to inline the function (which is a +// valid choice for the compiler to make). +// +//***************************************************************************** +extern uint_fast8_t I2CMReadModifyWrite16BE(tI2CMReadModifyWrite16 *psInst, + tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, + uint_fast8_t ui8Reg, + uint_fast16_t ui16Mask, + uint_fast16_t ui16Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); + +//***************************************************************************** +// +// This function handles the idle state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateIdle(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // Do nothing if there is not another transfer in the queue. + // + if(psInst->ui8ReadPtr == psInst->ui8WritePtr) + { + return; + } + + // + // See if there is any data to be written. + // + if(pCommand->ui16WriteCount != 0) + { + // + // Set the slave address and indicate a write. + // + MAP_I2CMasterSlaveAddrSet(psInst->ui32Base, pCommand->ui8Addr, false); + + // + // Place the first data byte to be written in the data register. + // + MAP_I2CMasterDataPut(psInst->ui32Base, pCommand->pui8WriteData[0]); + + // + // See if there is just a single byte to be written and no bytes to be + // read. + // + if((pCommand->ui16WriteCount == 1) && (pCommand->ui16ReadCount == 0)) + { + // + // Perform a single byte send. + // + MAP_I2CMasterControl(psInst->ui32Base, I2C_MASTER_CMD_SINGLE_SEND); + + // + // The next state is the callback state. + // + psInst->ui8State = STATE_CALLBACK; + } + + // + // Otherwise, see if there is just a single byte to be written and at + // least one byte to be read. + // + else if(pCommand->ui16WriteCount == 1) + { + // + // Perform a single send, writing the first byte as the only byte. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_SEND_START); + + // + // Set the next state of the interrupt state machine based on the + // number of bytes to read. + // + psInst->ui8State = ((pCommand->ui16ReadCount == 1) ? + STATE_READ_ONE : STATE_READ_FIRST); + } + + // + // Otherwise, there is more than one byte to be written. + // + else + { + // + // Start the burst cycle, writing the first byte. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_SEND_START); + + // + // Set the index to indicate that the first byte has been + // transmitted. + // + psInst->ui16Index = 1; + + // + // Set the next state of the interrupt state machine based on the + // number of bytes to write. + // + psInst->ui8State = ((pCommand->ui16WriteCount != 2) ? + STATE_WRITE_NEXT : STATE_WRITE_FINAL); + } + } + else + { + // + // Set the slave address and indicate a read. + // + MAP_I2CMasterSlaveAddrSet(psInst->ui32Base, pCommand->ui8Addr, true); + + // + // Set the index to indicate that the first byte is being read. + // + psInst->ui16Index = 0; + + // + // See if there is just a single byte to be read. + // + if(pCommand->ui16ReadCount == 1) + { + // + // Perform a single byte read. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_SINGLE_RECEIVE); + + // + // The next state is the wait for final read state. + // + psInst->ui8State = STATE_READ_WAIT; + } + else + { + // + // Start the burst receive. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_RECEIVE_START); + + // + // Set the next state appropriately. If the read count is two, the + // next state must finish the transaction. If it is greater than + // two, the burst read must be continued. + // + psInst->ui8State = ((pCommand->ui16ReadCount == 2) ? + STATE_READ_FINAL : STATE_READ_NEXT); + } + } +} + +//***************************************************************************** +// +// This function handles the write next state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateWriteNext(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // See if the write batch has been sent. + // + if(psInst->ui16Index == pCommand->ui16WriteBatchSize) + { + // + // Move to the write pause state. + // + psInst->ui8State = STATE_WRITE_PAUSE; + + // + // Call the callback function. + // + if(pCommand->pfnCallback) + { + pCommand->pfnCallback(pCommand->pvCallbackData, + I2CM_STATUS_BATCH_DONE); + } + } + else + { + // + // Write the next byte to the data register. + // + MAP_I2CMasterDataPut(psInst->ui32Base, + pCommand->pui8WriteData[psInst->ui16Index]); + psInst->ui16Index++; + + // + // Continue the burst write. + // + MAP_I2CMasterControl(psInst->ui32Base, I2C_MASTER_CMD_BURST_SEND_CONT); + + // + // If there is one byte left, set the next state to the final write + // state. + // + if((pCommand->ui16WriteCount - psInst->ui16Index) == 1) + { + psInst->ui8State = STATE_WRITE_FINAL; + } + } +} + +//***************************************************************************** +// +// This function handles the write final state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateWriteFinal(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // See if the write batch has been sent. + // + if(psInst->ui16Index == pCommand->ui16WriteBatchSize) + { + // + // Move to the write pause state. + // + psInst->ui8State = STATE_WRITE_PAUSE; + + // + // Call the callback function. + // + if(pCommand->pfnCallback) + { + pCommand->pfnCallback(pCommand->pvCallbackData, + I2CM_STATUS_BATCH_DONE); + } + } + else + { + // + // Write the final byte to the data register. + // + MAP_I2CMasterDataPut(psInst->ui32Base, + pCommand->pui8WriteData[psInst->ui16Index]); + + // + // See if there is data to be read after this byte is written. + // + if(pCommand->ui16ReadCount == 0) + { + // + // Finish the burst write. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_SEND_FINISH); + + // + // The next state is the callback state. + // + psInst->ui8State = STATE_CALLBACK; + } + else + { + // + // Finish the burst write. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_SEND_CONT); + + // + // Set the next state of the interrupt state machine based on the + // number of bytes to read. + // + psInst->ui8State = ((pCommand->ui16ReadCount == 1) ? + STATE_READ_ONE : STATE_READ_FIRST); + } + } +} + +//***************************************************************************** +// +// This function handles the write pause state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateWritePause(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // Decrement the write count by the batch size. + // + pCommand->ui16WriteCount -= pCommand->ui16WriteBatchSize; + + // + // Write the next byte to the data register. + // + MAP_I2CMasterDataPut(psInst->ui32Base, pCommand->pui8WriteData[0]); + + // + // Set the index to indicate that the first byte has been transmitted. + // + psInst->ui16Index = 1; + + // + // See if there is more than one byte left to be written. + // + if((pCommand->ui16WriteCount - psInst->ui16Index) == 0) + { + // + // See if there is data to be read after this byte is written. + // + if(pCommand->ui16ReadCount == 0) + { + // + // Finish the burst write. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_SEND_FINISH); + + // + // The next state is the callback state. + // + psInst->ui8State = STATE_CALLBACK; + } + else + { + // + // Finish the burst write. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_SEND_CONT); + + // + // Set the next state of the interrupt state machine based on the + // number of bytes to read. + // + psInst->ui8State = ((pCommand->ui16ReadCount == 1) ? + STATE_READ_ONE : STATE_READ_FIRST); + } + } + else + { + // + // Continue the burst write. + // + MAP_I2CMasterControl(psInst->ui32Base, I2C_MASTER_CMD_BURST_SEND_CONT); + + // + // The next state is the write next state. + // + if((pCommand->ui16WriteCount - psInst->ui16Index) == 1) + { + psInst->ui8State = STATE_WRITE_FINAL; + } + else + { + psInst->ui8State = STATE_WRITE_NEXT; + } + } +} + +//***************************************************************************** +// +// This function handles the read one state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateReadOne(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // Put the I2C master into receive mode. + // + MAP_I2CMasterSlaveAddrSet(psInst->ui32Base, pCommand->ui8Addr, true); + + // + // Perform a single byte read. + // + MAP_I2CMasterControl(psInst->ui32Base, I2C_MASTER_CMD_SINGLE_RECEIVE); + + // + // Set the index to indicate that the first byte is being read. + // + psInst->ui16Index = 0; + + // + // The next state is the wait for final read state. + // + psInst->ui8State = STATE_READ_WAIT; +} + +//***************************************************************************** +// +// This function handles the read first state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateReadFirst(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // Put the I2C master into receive mode. + // + MAP_I2CMasterSlaveAddrSet(psInst->ui32Base, pCommand->ui8Addr, true); + + // + // Start the burst receive. + // + MAP_I2CMasterControl(psInst->ui32Base, I2C_MASTER_CMD_BURST_RECEIVE_START); + + // + // Set the index to indicate that the first byte is being read. + // + psInst->ui16Index = 0; + + // + // Set the next state appropriately. If the count is greater than two it + // is the middle of the burst read. If exactly two, the next state must + // finish the transaction. + // + psInst->ui8State = ((pCommand->ui16ReadCount == 2) ? + STATE_READ_FINAL : STATE_READ_NEXT); +} + +//***************************************************************************** +// +// This function handles the read next state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateReadNext(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // Read the received character. + // + pCommand->pui8ReadData[psInst->ui16Index] = + MAP_I2CMasterDataGet(psInst->ui32Base); + psInst->ui16Index++; + + // + // See if the read batch has been filled. + // + if(psInst->ui16Index == pCommand->ui16ReadBatchSize) + { + // + // Move to the read pause state. + // + psInst->ui8State = STATE_READ_PAUSE; + + // + // Call the callback function. + // + if(pCommand->pfnCallback) + { + pCommand->pfnCallback(pCommand->pvCallbackData, + I2CM_STATUS_BATCH_READY); + } + } + else + { + // + // Continue the burst read. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_RECEIVE_CONT); + + // + // If there are two characters left to be read, make the next state be + // the end of burst read state. + // + if((pCommand->ui16ReadCount - psInst->ui16Index) == 2) + { + psInst->ui8State = STATE_READ_FINAL; + } + } +} + +//***************************************************************************** +// +// This function handles the read final state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateReadFinal(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // Read the received character. + // + pCommand->pui8ReadData[psInst->ui16Index] = + MAP_I2CMasterDataGet(psInst->ui32Base); + psInst->ui16Index++; + + // + // See if the read batch has been filled. + // + if(psInst->ui16Index == pCommand->ui16ReadBatchSize) + { + // + // Move to the read pause state. + // + psInst->ui8State = STATE_READ_PAUSE; + + // + // Call the callback function. + // + if(pCommand->pfnCallback) + { + pCommand->pfnCallback(pCommand->pvCallbackData, + I2CM_STATUS_BATCH_READY); + } + } + else + { + // + // Finish the burst read. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_RECEIVE_FINISH); + + // + // The next state is the wait for final read state. + // + psInst->ui8State = STATE_READ_WAIT; + } +} + +//***************************************************************************** +// +// This function handles the read pause state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateReadPause(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // Decrement the read count by the batch size. + // + pCommand->ui16ReadCount -= pCommand->ui16ReadBatchSize; + + // + // Reset the read index. + // + psInst->ui16Index = 0; + + // + // See if there is more than one byte left to be read. + // + if((pCommand->ui16ReadCount - psInst->ui16Index) == 1) + { + // + // Finish the burst read. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_RECEIVE_FINISH); + + // + // The next state is the wait for final read state. + // + psInst->ui8State = STATE_READ_WAIT; + } + else + { + // + // Continue the burst read. + // + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_RECEIVE_CONT); + + // + // Determine the next state based on the number of bytes left to read. + // + if((pCommand->ui16ReadCount - psInst->ui16Index) == 2) + { + psInst->ui8State = STATE_READ_FINAL; + } + else + { + psInst->ui8State = STATE_READ_NEXT; + } + } +} + +//***************************************************************************** +// +// This function handles the read wait state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateReadWait(tI2CMInstance *psInst, tI2CMCommand *pCommand) +{ + // + // Read the received character. + // + pCommand->pui8ReadData[psInst->ui16Index] = + MAP_I2CMasterDataGet(psInst->ui32Base); + + // + // The state machine is now in the callback state. + // + psInst->ui8State = STATE_CALLBACK; +} + +//***************************************************************************** +// +// This function handles the callback state of the I2C master state machine. +// +//***************************************************************************** +static void +I2CMStateCallback(tI2CMInstance *psInst, tI2CMCommand *pCommand, + uint32_t ui32Status) +{ + tSensorCallback *pfnCallback; + void *pvCallbackData; + + // + // Save the callback information. + // + pfnCallback = pCommand->pfnCallback; + pvCallbackData = pCommand->pvCallbackData; + + // + // This command has been completed, so increment the read pointer. + // + psInst->ui8ReadPtr++; + if(psInst->ui8ReadPtr == NUM_I2CM_COMMANDS) + { + psInst->ui8ReadPtr = 0; + } + + // + // If there is a callback function then call it now. + // + if(pfnCallback) + { + // + // Convert the status from the I2C driver into the I2C master + // driver status. + // + if((ui32Status & (I2C_MCS_ARBLST | I2C_MCS_ERROR)) == 0) + { + ui32Status = I2CM_STATUS_SUCCESS; + } + else if(ui32Status & I2C_MCS_ARBLST) + { + ui32Status = I2CM_STATUS_ARB_LOST; + } + else if(ui32Status & I2C_MCS_ADRACK) + { + ui32Status = I2CM_STATUS_ADDR_NACK; + } + else if(ui32Status & I2C_MCS_DATACK) + { + ui32Status = I2CM_STATUS_DATA_NACK; + } + else + { + ui32Status = I2CM_STATUS_ERROR; + } + + // + // Call the callback function. + // + pfnCallback(pvCallbackData, ui32Status); + } + + // + // The state machine is now idle. + // + psInst->ui8State = STATE_IDLE; +} + +//***************************************************************************** +// +//! Handles I2C master interrupts. +//! +//! \param psInst is a pointer to the I2C master instance data. +//! +//! This function performs the processing required in response to an I2C +//! interrupt. The application-supplied interrupt handler should call this +//! function with the correct instance data in response to the I2C interrupt. +//! +//! \return None. +// +//***************************************************************************** +void +I2CMIntHandler(tI2CMInstance *psInst) +{ + tI2CMCommand *pCommand; + uint32_t ui32Status; + + // + // Clear the I2C interrupt. + // + MAP_I2CMasterIntClear(psInst->ui32Base); + ui32Status = HWREG(psInst->ui32Base + I2C_O_MCS); + + // + // Get a pointer to the current command. + // + pCommand = &(psInst->pCommands[psInst->ui8ReadPtr]); + + // + // See if an error occurred during the last transaction. + // + if((ui32Status & (I2C_MCS_ERROR | I2C_MCS_ARBLST)) && + (psInst->ui8State != STATE_IDLE)) + { + // + // An error occurred, so halt the I2C transaction. The error stop + // command for send and receive is identical, so it does not matter + // which one is used here. Only issue the stop if the bus is busy. + // + if(ui32Status & I2C_MCS_BUSBSY) + { + MAP_I2CMasterControl(psInst->ui32Base, + I2C_MASTER_CMD_BURST_SEND_ERROR_STOP); + } + + // + // Move to the callback state. + // + psInst->ui8State = STATE_CALLBACK; + } + + // + // Loop forever. Most states will return when they have completed their + // action. However, a few states require multi-state processing, so those + // states will break and this loop repeated. + // + while(1) + { + // + // Determine what to do based on the current state. + // + switch(psInst->ui8State) + { + // + // The idle state. + // + case STATE_IDLE: + { + // + // Handle the idle state. + // + I2CMStateIdle(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // The state for the middle of a burst write. + // + case STATE_WRITE_NEXT: + { + // + // Handle the write next state. + // + I2CMStateWriteNext(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // The state for the final write of a burst sequence. + // + case STATE_WRITE_FINAL: + { + // + // Handle the write final state. + // + I2CMStateWriteFinal(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // The state for a paused write. + // + case STATE_WRITE_PAUSE: + { + // + // Handle the write pause state. + // + I2CMStateWritePause(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // The state for a single byte read. + // + case STATE_READ_ONE: + { + // + // Handle the read one state. + // + I2CMStateReadOne(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // The state for the start of a burst read. + // + case STATE_READ_FIRST: + { + // + // Handle the read first state. + // + I2CMStateReadFirst(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // The state for the middle of a burst read. + // + case STATE_READ_NEXT: + { + // + // Handle the read next state. + // + I2CMStateReadNext(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // The state for the end of a burst read. + // + case STATE_READ_FINAL: + { + // + // Handle the read final state. + // + I2CMStateReadFinal(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // The state for a paused read. + // + case STATE_READ_PAUSE: + { + // + // Handle the read pause state. + // + I2CMStateReadPause(psInst, pCommand); + + // + // This state is done and the next state should be handled at + // the next interrupt. + // + return; + } + + // + // This state is for the final read of a single or burst read. + // + case STATE_READ_WAIT: + { + // + // Handle the read wait state. + // + I2CMStateReadWait(psInst, pCommand); + + // + // This state is done and the next state needs to be handled + // immediately. + // + break; + } + + // + // This state is for providing the transaction complete callback. + // + case STATE_CALLBACK: + { + // + // Handle the callback state. + // + I2CMStateCallback(psInst, pCommand, ui32Status); + + // + // If an error occurred, this state is done. The completion of + // the error handling stop condition above, if issued, will + // cause the next state to be processed. + // + if((ui32Status & (I2C_MCS_ERROR | I2C_MCS_ARBLST)) && + (ui32Status & I2C_MCS_BUSBSY)) + { + return; + } + + // + // Update the pointer to the current command. + // + pCommand = &(psInst->pCommands[psInst->ui8ReadPtr]); + + // + // This state is done and the next state needs to be handled + // immediately. + // + break; + } + } + } +} + +//***************************************************************************** +// +//! Initializes the I2C master driver. +//! +//! \param psInst is a pointer to the I2C master instance data. +//! \param ui32Base is the base address of the I2C module. +//! \param ui8Int is the interrupt number for the I2C module. +//! \param ui8TxDMA is the uDMA channel number used for transmitting data to +//! the I2C module. +//! \param ui8RxDMA is the uDMA channel number used for receiving data from +//! the I2C module. +//! \param ui32Clock is the clock frequency of the input clock to the I2C +//! module. +//! +//! This function prepares both the I2C master module and driver for operation, +//! and must be the first I2C master driver function called for each I2C master +//! instance. It is assumed that the application has enabled the I2C module, +//! configured the I2C pins, and provided an I2C interrupt handler that calls +//! I2CMIntHandler(). +//! +//! The uDMA module cannot be used at present to transmit/receive data, so the +//! \e ui8TxDMA and \e ui8RxDMA parameters are unused. They are reserved for +//! future use and should be set to 0xff in order to ensure future +//! compatibility. +//! +//! \return None. +// +//***************************************************************************** +void +I2CMInit(tI2CMInstance *psInst, uint32_t ui32Base, uint_fast8_t ui8Int, + uint_fast8_t ui8TxDMA, uint_fast8_t ui8RxDMA, uint32_t ui32Clock) +{ + // + // Check the arguments. + // + ASSERT(psInst); + ASSERT((ui32Base == I2C0_BASE) || (ui32Base == I2C1_BASE) || + (ui32Base == I2C2_BASE) || (ui32Base == I2C3_BASE) || + (ui32Base == I2C4_BASE) || (ui32Base == I2C5_BASE) || + (ui32Base == I2C6_BASE) || (ui32Base == I2C7_BASE) || + (ui32Base == I2C8_BASE) || (ui32Base == I2C9_BASE)); + ASSERT(ui8Int); + ASSERT(ui32Clock); + + // + // Initialize the state structure. + // + psInst->ui32Base = ui32Base; + psInst->ui8Int = ui8Int; + psInst->ui8TxDMA = ui8TxDMA; + psInst->ui8RxDMA = ui8RxDMA; + psInst->ui8State = STATE_IDLE; + psInst->ui8ReadPtr = 0; + psInst->ui8WritePtr = 0; + + // + // Initialize the I2C master module. + // + MAP_I2CMasterInitExpClk(ui32Base, ui32Clock, true); + + // + // Enable the I2C interrupt. + // + MAP_IntEnable(ui8Int); + MAP_I2CMasterIntEnableEx(ui32Base, I2C_MASTER_INT_DATA); +} + +//***************************************************************************** +// +//! Sends a command to an I2C device. +//! +//! \param psInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param pui8WriteData is a pointer to the data buffer to be written. +//! \param ui16WriteCount is the number of bytes to be written. +//! \param ui16WriteBatchSize is the number of bytes in each write batch. +//! \param pui8ReadData is a pointer to the buffer to be filled with the read +//! data. +//! \param ui16ReadCount is the number of bytes to be read. +//! \param ui16ReadBatchSize is the number of bytes to be read in each batch. +//! \param pfnCallback is the function to be called when the transfer has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function adds an I2C command to the queue of commands to be sent. If +//! successful, the I2C command is then transferred in the background using the +//! interrupt handler. When the transfer is complete, the callback function, +//! if provided, is called in the context of the I2C master interrupt handler. +//! +//! The first byte of \e pui8WriteData contains the I2C address of the device +//! to access, the next \e ui16WriteCount bytes contains the data to be written +//! to the device. The data read from the device is written into the first +//! \e ui16ReadCount bytes of \e pui8ReadData. The \e ui16WriteCount or +//! \e ui16ReadCount parameters can be zero if there are no bytes to be read or +//! written. The write bytes are sent to the device first, and then the read +//! bytes are read from the device afterward. +//! +//! If \e ui16WriteBatchSize is less than \e ui16WriteCount, the write portion +//! of the transfer is broken up into as many \e ui16WriteBatchSize batches as +//! required to write \e ui16WriteCount bytes. After each batch, the callback +//! function is called with an \b I2CM_STATUS_BATCH_DONE status, and the +//! transfer is paused (with the I2C bus held). The transfer is resumed when +//! I2CMTransferResume() is called. This procedure can be used to perform very +//! large writes without requiring all the data be available at once, at the +//! expense of tying up the I2C bus for the extended duration of the transfer. +//! +//! If \e ui16ReadBatchSize is less than \e ui16ReadCount, the read portion of +//! the transfer is broken up into as many \e ui16ReadBatchSize batches as +//! required to read \e ui16ReadCount bytes. After each batch, the callback +//! function is called with an \b I2CM_STATUS_BATCH_READY status, and the +//! transfer is paused (with the I2C bus held). The transfer is resumed when +//! I2CMTransferResume() is called. This procedure can be used to perform very +//! large reads without requiring a large SRAM buffer, at the expense of tying +//! up the I2C bus for the extended duration of the transfer. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +I2CMCommand(tI2CMInstance *psInst, uint_fast8_t ui8Addr, + const uint8_t *pui8WriteData, uint_fast16_t ui16WriteCount, + uint_fast16_t ui16WriteBatchSize, uint8_t *pui8ReadData, + uint_fast16_t ui16ReadCount, uint_fast16_t ui16ReadBatchSize, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + uint_fast8_t ui8Next, ui8Enabled; + tI2CMCommand *pCommand; + + // + // Check the arguments. + // + ASSERT(psInst); + ASSERT(pui8WriteData || !ui16WriteCount); + ASSERT(!ui16WriteCount || (ui16WriteBatchSize > 0)); + ASSERT(pui8ReadData || !ui16ReadCount); + ASSERT(!ui16ReadCount || (ui16ReadBatchSize > 0)); + + // + // Disable the I2C interrupt. + // + if(MAP_IntIsEnabled(psInst->ui8Int)) + { + ui8Enabled = 1; + MAP_IntDisable(psInst->ui8Int); + } + else + { + ui8Enabled = 0; + } + + // + // Compute the new value of the write pointer (after this command is added + // to the queue). + // + ui8Next = psInst->ui8WritePtr + 1; + if(ui8Next == NUM_I2CM_COMMANDS) + { + ui8Next = 0; + } + + // + // Return a failure if the command queue is full. + // + if(psInst->ui8ReadPtr == ui8Next) + { + if(ui8Enabled) + { + MAP_IntEnable(psInst->ui8Int); + } + return(0); + } + + // + // Get a pointer to the command structure. + // + pCommand = &(psInst->pCommands[psInst->ui8WritePtr]); + + // + // Fill in the command structure with the details of this command. + // + pCommand->ui8Addr = ui8Addr; + pCommand->pui8WriteData = pui8WriteData; + pCommand->ui16WriteCount = ui16WriteCount; + pCommand->ui16WriteBatchSize = ui16WriteBatchSize; + pCommand->pui8ReadData = pui8ReadData; + pCommand->ui16ReadCount = ui16ReadCount; + pCommand->ui16ReadBatchSize = ui16ReadBatchSize; + pCommand->pfnCallback = pfnCallback; + pCommand->pvCallbackData = pvCallbackData; + + // + // Update the write pointer. + // + psInst->ui8WritePtr = ui8Next; + + // + // See if the state machine is idle. + // + if(psInst->ui8State == STATE_IDLE) + { + // + // Generate a fake I2C interrupt, which will commence the I2C transfer. + // + IntTrigger(psInst->ui8Int); + } + + // + // Re-enable the I2C master interrupt. + // + if(ui8Enabled) + { + MAP_IntEnable(psInst->ui8Int); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Resumes an I2C transfer. +//! +//! \param psInst is a pointer to the I2C master instance data. +//! \param pui8Data is a pointer to the buffer to be used for the next batch of +//! data. +//! +//! This function resumes an I2C transfer that has been paused via the use of +//! the write or read batch size capability. +//! +//! \return Returns 1 if the transfer was resumed and 0 if there was not a +//! paused transfer to resume. +// +//***************************************************************************** +uint_fast8_t +I2CMTransferResume(tI2CMInstance *psInst, uint8_t *pui8Data) +{ + // + // Check the arguments. + // + ASSERT(psInst); + ASSERT(pui8Data); + + // + // Return an error if there is not a paused transfer. + // + if((psInst->ui8State != STATE_WRITE_PAUSE) && + (psInst->ui8State != STATE_READ_PAUSE)) + { + return(0); + } + + // + // Save the pointer for the next buffer. + // + if(psInst->ui8State == STATE_WRITE_PAUSE) + { + psInst->pCommands[psInst->ui8ReadPtr].pui8WriteData = pui8Data; + } + else + { + psInst->pCommands[psInst->ui8ReadPtr].pui8ReadData = pui8Data; + } + + // + // Trigger the I2C interrupt, resuming the transfer. + // + IntTrigger(psInst->ui8Int); + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +// The callback function that is called when I2C transactions as part of of a +// read-modify-write operation of 8 bits of data have completed. +// +//***************************************************************************** +static void +I2CMReadModifyWrite8Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tI2CMReadModifyWrite8 *psInst; + + // + // Convert the instance data into a pointer to a tI2CMReadModifyWrite8 + // structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result ina callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = I2CM_RMW_STATE_IDLE; + } + + // + // Determine the current state of the I2C master read-modify-write state + // machine. + // + switch(psInst->ui8State) + { + // + // The read portion of the read-modify-write has completed. + // + case I2CM_RMW_STATE_READ: + { + // + // Modify the register data that was just read. + // + psInst->pui8Buffer[1] = ((psInst->pui8Buffer[1] & + psInst->ui8Mask) | psInst->ui8Value); + + // + // Write the data back to the device. + // + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Buffer, + 2, I2CMReadModifyWrite8Callback, psInst); + + // + // Move to the wait for write state. + // + psInst->ui8State = I2CM_RMW_STATE_WRITE; + + // + // Done. + // + break; + } + + // + // The write portion of the read-modify-write has completed. + // + case I2CM_RMW_STATE_WRITE: + { + // + // Move to the idle state. + // + psInst->ui8State = I2CM_RMW_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == I2CM_RMW_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Performs a read-modify-write of 8 bits of data in an I2C device. +//! +//! \param psInst is a pointer to the read-modify-write instance data. +//! \param psI2CInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param ui8Reg is the register in the I2C device to access. +//! \param ui8Mask is the mask indicating the register bits that should be +//! maintained. +//! \param ui8Value is the value indicating the new value for the register bits +//! that are not maintained. +//! \param pfnCallback is the function to be called when the write has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read-modify-write transaction of 8 bits of data +//! in an I2C device. The modify portion of the operation is performed by +//! AND-ing the register value with \e ui8Mask and then OR-ing the result with +//! \e ui8Value. When the read-modify-write is complete, the callback +//! function, if provided, is called in the context of the I2C master interrupt +//! handler. +//! +//! If the mask (in \e ui8Mask) is zero, then none of the bits in the current +//! register value are maintained. In this case, the read portion of the +//! read-modify-write is bypassed, and the new register value (in \e ui8Value) +//! is directly written to the I2C device. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +I2CMReadModifyWrite8(tI2CMReadModifyWrite8 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Check the arguments. + // + ASSERT(psInst); + ASSERT(psI2CInst); + + // + // Fill in the read-modify-write structure with the details of this + // request. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8Addr; + psInst->ui8Mask = ui8Mask; + psInst->ui8Value = ui8Value; + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Construct the I2C command to access the requested register. + // + psInst->pui8Buffer[0] = ui8Reg; + + // + // See if this is a write or a read-modify-write. + // + if(ui8Mask == 0) + { + // + // Set the state to waiting for the write portion of the + // read-modify-write. + // + psInst->ui8State = I2CM_RMW_STATE_WRITE; + + // + // Set the new register value in the command buffer. + // + psInst->pui8Buffer[1] = ui8Value; + + // + // Add the write command to the I2C master queue. + // + if(I2CMWrite(psI2CInst, ui8Addr, psInst->pui8Buffer, 2, + I2CMReadModifyWrite8Callback, psInst) == 0) + { + return(0); + } + } + else + { + // + // Set the state to waiting for the read portion of the + // read-modify-write. + // + psInst->ui8State = I2CM_RMW_STATE_READ; + + // + // Add the read command to the I2C master queue. + // + if(I2CMRead(psI2CInst, ui8Addr, psInst->pui8Buffer, 1, + psInst->pui8Buffer + 1, 1, I2CMReadModifyWrite8Callback, + psInst) == 0) + { + return(0); + } + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +// The callback function that is called when I2C transactions as part of a +// read-modify-write operation of 16 bits of little-endian data have completed. +// +//***************************************************************************** +static void +I2CMReadModifyWrite16LECallback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tI2CMReadModifyWrite16 *psInst; + uint16_t ui16Value; + + // + // Convert the instance data into a pointer to a tI2CMReadModifyWrite16 + // structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result ina callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = I2CM_RMW_STATE_IDLE; + } + + // + // Determine the current state of the I2C master read-modify-write state + // machine. + // + switch(psInst->ui8State) + { + // + // The read portion of the read-modify-write has completed. + // + case I2CM_RMW_STATE_READ: + { + // + // Modify the register data that was just read. + // + ui16Value = (psInst->pui8Buffer[2] << 8) | psInst->pui8Buffer[1]; + ui16Value = (ui16Value & psInst->ui16Mask) | psInst->ui16Value; + psInst->pui8Buffer[1] = ui16Value & 0xff; + psInst->pui8Buffer[2] = (ui16Value >> 8) & 0xff; + + // + // Write the data back to the device. + // + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Buffer, + 3, I2CMReadModifyWrite16LECallback, psInst); + + // + // Move to the wait for write state. + // + psInst->ui8State = I2CM_RMW_STATE_WRITE; + + // + // Done. + // + break; + } + + // + // The write portion of the read-modify-write has completed. + // + case I2CM_RMW_STATE_WRITE: + { + // + // Move to the idle state. + // + psInst->ui8State = I2CM_RMW_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == I2CM_RMW_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Performs a read-modify-write of 16 bits of little-endian data in an I2C +//! device. +//! +//! \param psInst is a pointer to the read-modify-write instance data. +//! \param psI2CInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param ui8Reg is the register in the I2C device to access. +//! \param ui16Mask is the mask indicating the register bits that should be +//! maintained. +//! \param ui16Value is the value indicating the new value for the register +//! bits that are not maintained. +//! \param pfnCallback is the function to be called when the write has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read-modify-write transaction of 16 bits of +//! little-endian data in an I2C device. The modify portion of the operation +//! is performed by AND-ing the register value with \e ui16Mask and then OR-ing +//! the result with \e ui16Value. When the read-modify-write is complete, the +//! callback function, if provided, is called in the context of the I2C master +//! interrupt handler. +//! +//! If the mask (in \e ui16Mask) is zero, then none of the bits in the current +//! register value are maintained. In this case, the read portion of the +//! read-modify-write is bypassed, and the new register value (in \e ui16Value) +//! is directly written to the I2C device. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +I2CMReadModifyWrite16LE(tI2CMReadModifyWrite16 *psInst, + tI2CMInstance *psI2CInst, uint_fast8_t ui8Addr, + uint_fast8_t ui8Reg, uint_fast16_t ui16Mask, + uint_fast16_t ui16Value, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Check the arguments. + // + ASSERT(psInst); + ASSERT(psI2CInst); + + // + // Fill in the read-modify-write structure with the details of this + // request. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8Addr; + psInst->ui16Mask = ui16Mask; + psInst->ui16Value = ui16Value; + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Construct the I2C command to access the requested register. + // + psInst->pui8Buffer[0] = ui8Reg; + + // + // See if this is a write or a read-modify-write. + // + if(ui16Mask == 0) + { + // + // Set the state to waiting for the write portion of the + // read-modify-write. + // + psInst->ui8State = I2CM_RMW_STATE_WRITE; + + // + // Set the new register value in the command buffer. + // + psInst->pui8Buffer[1] = ui16Value & 0xff; + psInst->pui8Buffer[2] = (ui16Value >> 8) & 0xff; + + // + // Add the write command to the I2C master queue. + // + if(I2CMWrite(psI2CInst, ui8Addr, psInst->pui8Buffer, 3, + I2CMReadModifyWrite16LECallback, psInst) == 0) + { + return(0); + } + } + else + { + // + // Set the state to waiting for the read portion of the + // read-modify-write. + // + psInst->ui8State = I2CM_RMW_STATE_READ; + + // + // Add the read command to the I2C master queue. + // + if(I2CMRead(psI2CInst, ui8Addr, psInst->pui8Buffer, 1, + psInst->pui8Buffer + 1, 2, I2CMReadModifyWrite16LECallback, + psInst) == 0) + { + return(0); + } + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +// The callback function that is called when I2C transactions as part of a +// write operation of 8-bit data have completed. +// +//***************************************************************************** +static void +I2CMWrite8Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tI2CMWrite8 *psInst; + + // + // Convert the instance data into a pointer to a tI2CMWrite8 structure. + // + psInst = pvCallbackData; + + // + // See if the current batch is done and more data is needed. + // + if(ui8Status == I2CM_STATUS_BATCH_DONE) + { + // + // Place the next two bytes into the write buffer. + // + psInst->pui8Buffer[0] = psInst->pui8Data[0]; + if(psInst->ui16Count > 1) + { + psInst->pui8Buffer[1] = psInst->pui8Data[1]; + } + + // + // Advance past the next two bytes of the input buffer. + // + psInst->pui8Data += 2; + psInst->ui16Count -= 2; + + // + // Resume the batched write. + // + I2CMTransferResume(psInst->psI2CInst, psInst->pui8Buffer); + } + + // + // The transfer has completed, or an error has occurred. In both cases, + // see if there is a callback function. + // + else if(psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Performs a write of 8-bit data to an I2C device. +//! +//! \param psInst is a pointer to the 8-bit write instance data. +//! \param psI2CInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param ui8Reg is the register in the I2C device to access. +//! \param pui8Data is a pointer to the register data to be written. +//! \param ui16Count is the number of register values to be written. +//! \param pfnCallback is the function to be called when the write has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a write transaction of 8-bit data to an I2C device. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +I2CMWrite8(tI2CMWrite8 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8Addr, + uint_fast8_t ui8Reg, const uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Check the arguments. + // + ASSERT(psInst); + ASSERT(psI2CInst); + + // + // Fill in the write structure with the details of this request. + // + psInst->psI2CInst = psI2CInst; + psInst->pui8Data = pui8Data + 1; + psInst->ui16Count = ui16Count - 1; + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Initiate the I2C write to this device. + // + psInst->pui8Buffer[0] = ui8Reg; + psInst->pui8Buffer[1] = pui8Data[0]; + if(I2CMWriteBatched(psI2CInst, ui8Addr, psInst->pui8Buffer, ui16Count + 1, + 2, I2CMWrite8Callback, psInst) == 0) + { + // + // The I2C write failed, so return a failure. + // + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +// The callback function that is called when I2C transactions as part of a read +// operation of 16-bit big-endian data have completed. +// +//***************************************************************************** +static void +I2CMRead16BECallback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tI2CMRead16BE *psInst; + uint8_t ui8Temp; + + // + // Convert the instance data into a pointer to a tI2CMRead16BE structure. + // + psInst = pvCallbackData; + + // + // See if the transaction completed successfully. + // + if(ui8Status == I2CM_STATUS_SUCCESS) + { + // + // Loop through the 16-bit values read from the I2C device. + // + while(psInst->ui16Count--) + { + // + // Byte swap this value. + // + ui8Temp = psInst->pui8Data[0]; + psInst->pui8Data[0] = psInst->pui8Data[1]; + psInst->pui8Data[1] = ui8Temp; + + // + // Skip to the next value. + // + psInst->pui8Data += 2; + } + } + + // + // See if there is a callback function. + // + if(psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Performs a read of 16-bit big-endian data from an I2C device. +//! +//! \param psInst is a pointer to the 16-bit big-endian read instance data. +//! \param psI2CInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param ui8Reg is the register in the I2C device to access. +//! \param pui16Data is a pointer to the buffer to be filled with the register +//! data. +//! \param ui16Count is the number of 16-bit register values to be read. +//! \param pfnCallback is the function to be called when the read has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read transaction of 16-bit big-endian data from +//! an I2C device. The data is provided by the device in big-endian format and +//! is byte-swapped as it is read from the I2C device, returning the data in +//! little-endian format. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +I2CMRead16BE(tI2CMRead16BE *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, uint_fast8_t ui8Reg, + uint16_t *pui16Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Check the arguments. + // + ASSERT(psInst); + ASSERT(psI2CInst); + + // + // Fill in the read structure with the details of this request. + // + psInst->psI2CInst = psI2CInst; + psInst->pui8Data = (uint8_t *)pui16Data; + psInst->ui16Count = ui16Count; + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Initiate the I2C write to this device. + // + psInst->pui8Data[0] = ui8Reg; + if(I2CMRead(psI2CInst, ui8Addr, psInst->pui8Data, 1, psInst->pui8Data, + ui16Count * 2, I2CMRead16BECallback, psInst) == 0) + { + // + // The I2C write failed, so return a failure. + // + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +// The callback function that is called when I2C transactions as part of a +// write operation of 16-bit big-endian data have completed. +// +//***************************************************************************** +static void +I2CMWrite16BECallback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tI2CMWrite16BE *psInst; + + // + // Convert the instance data into a pointer to a tI2CMWrite16BE structure. + // + psInst = pvCallbackData; + + // + // See if the current batch is done and more data is needed. + // + if(ui8Status == I2CM_STATUS_BATCH_DONE) + { + // + // Place the next two bytes into the write buffer. + // + psInst->pui8Buffer[0] = psInst->pui8Data[0]; + if(psInst->ui16Count > 1) + { + psInst->pui8Buffer[1] = psInst->pui8Data[3]; + } + + // + // Advance past the next two bytes of the input buffer. + // + psInst->pui8Data += 2; + psInst->ui16Count--; + + // + // Resume the batched write. + // + I2CMTransferResume(psInst->psI2CInst, psInst->pui8Buffer); + } + + // + // The transfer has completed, or an error has occurred. In both cases, + // see if there is a callback function. + // + else if(psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Performs a write of 16-bit big-endian data to an I2C device. +//! +//! \param psInst is a pointer to the 16-bit big-endian write instance data. +//! \param psI2CInst is a pointer to the I2C master instance data. +//! \param ui8Addr is the address of the I2C device to access. +//! \param ui8Reg is the register in the I2C device to access. +//! \param pui16Data is a pointer to the register data to be written. +//! \param ui16Count is the number of 16-bit register values to be written. +//! \param pfnCallback is the function to be called when the write has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a write transaction of 16-bit big-endian data to an +//! I2C device. The data in the buffer is provided in little-endian format and +//! is byte-swapped as it is being written to the I2C device. +//! +//! \return Returns 1 if the command was successfully added to the queue and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +I2CMWrite16BE(tI2CMWrite16BE *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, uint_fast8_t ui8Reg, + const uint16_t *pui16Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Check the arguments. + // + ASSERT(psInst); + ASSERT(psI2CInst); + + // + // Fill in the write structure with the details of this request. + // + psInst->psI2CInst = psI2CInst; + psInst->pui8Data = (const uint8_t *)pui16Data; + psInst->ui16Count = ui16Count; + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Initiate the I2C write to this device. + // + psInst->pui8Buffer[0] = ui8Reg; + psInst->pui8Buffer[1] = psInst->pui8Data[1]; + if(I2CMWriteBatched(psI2CInst, ui8Addr, psInst->pui8Buffer, + (ui16Count * 2) + 1, 2, I2CMWrite16BECallback, + psInst) == 0) + { + // + // The I2C write failed, so return a failure. + // + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/i2cm_drv.h b/sensorlib/i2cm_drv.h new file mode 100644 index 0000000..397c04d --- /dev/null +++ b/sensorlib/i2cm_drv.h @@ -0,0 +1,544 @@ +//***************************************************************************** +// +// i2cm_drv.h - Prototypes for the interrupt-driven I2C master driver. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_I2CM_DRV_H__ +#define __SENSORLIB_I2CM_DRV_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// A prototype for the callback function used by the I2C master driver. +// +//***************************************************************************** +typedef void (tSensorCallback)(void *pvData, uint_fast8_t ui8Status); + +//***************************************************************************** +// +// The possible status values that can be returned by the I2C command callback. +// +//***************************************************************************** +#define I2CM_STATUS_SUCCESS 0 +#define I2CM_STATUS_ADDR_NACK 1 +#define I2CM_STATUS_DATA_NACK 2 +#define I2CM_STATUS_ARB_LOST 3 +#define I2CM_STATUS_ERROR 4 +#define I2CM_STATUS_BATCH_DONE 5 +#define I2CM_STATUS_BATCH_READY 6 + +//***************************************************************************** +// +// The maximum number of outstanding commands for each I2C master instance. +// +//***************************************************************************** +#define NUM_I2CM_COMMANDS 10 + +//***************************************************************************** +// +// The structure that defines an I2C master command. +// +//***************************************************************************** +typedef struct +{ + // + // The I2C address of the device being accessed. + // + uint8_t ui8Addr; + + // + // The data buffer containing the data to be written. + // + const uint8_t *pui8WriteData; + + // + // The total number of bytes to be written by the command. + // + uint16_t ui16WriteCount; + + // + // The number of bytes to be written in each batch. + // + uint16_t ui16WriteBatchSize; + + // + // The data buffer to store data that has been read. + // + uint8_t *pui8ReadData; + + // + // The total number of bytes to be read by the command. + // + uint16_t ui16ReadCount; + + // + // The number of bytes to be read in each chuck. + // + uint16_t ui16ReadBatchSize; + + // + // The function that is called when this command has been transferred. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; +} +tI2CMCommand; + +//***************************************************************************** +// +// The structure that contains the state of an I2C master instance. +// +//***************************************************************************** +typedef struct +{ + // + // The base address of the I2C module. + // + uint32_t ui32Base; + + // + // The interrupt number associated with the I2C module. + // + uint8_t ui8Int; + + // + // The uDMA channel used to write data to the I2C module. + // + uint8_t ui8TxDMA; + + // + // The uDMA channel used to read data from the I2C module. + // + uint8_t ui8RxDMA; + + // + // The current state of the I2C master driver. + // + uint8_t ui8State; + + // + // The offset of the next command to be read. The buffer is empty when + // this value is equal to the write pointer. + // + uint8_t ui8ReadPtr; + + // + // The offset of the next space in the buffer to write a command. The + // buffer is full if this value is one less than the read pointer. + // + uint8_t ui8WritePtr; + + // + // The index into the data buffer of the next byte to be transferred. + // + uint16_t ui16Index; + + // + // An array of commands queued up to be sent via the I2C module. + // + tI2CMCommand pCommands[NUM_I2CM_COMMANDS]; +} +tI2CMInstance; + +//***************************************************************************** +// +// The structure that contains the state of an I2C read-modify-write request of +// 8 bits of data. +// +//***************************************************************************** +typedef struct +{ + // + // A pointer to the I2C master interface instance used for the + // read-modify-write request. + // + tI2CMInstance *psI2CInst; + + // + // The buffer used for the I2C transfers. + // + uint8_t pui8Buffer[4]; + + // + // The current state of the I2C read-modify-write state machine. + // + uint8_t ui8State; + + // + // The I2C address of the device being accessed. + // + uint8_t ui8Addr; + + // + // The value to AND with the I2C register data. + // + uint8_t ui8Mask; + + // + // The value to OR with the I2C register data. + // + uint8_t ui8Value; + + // + // The function that is called when the read-modify-write has been + // completed. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; +} +tI2CMReadModifyWrite8; + +//***************************************************************************** +// +// The structure that contains the state of an I2C read-modify-write request of +// 16 bits of data. +// +//***************************************************************************** +typedef struct +{ + // + // A pointer to the I2C master interface instance used for the + // read-modify-write request. + // + tI2CMInstance *psI2CInst; + + // + // The buffer used for the I2C transfers. + // + uint8_t pui8Buffer[4]; + + // + // The current state of the I2C read-modify-write state machine. + // + uint8_t ui8State; + + // + // The I2C address of the device being accessed. + // + uint8_t ui8Addr; + + // + // The value to AND with the I2C register data. + // + uint16_t ui16Mask; + + // + // The value to OR with the I2C register data. + // + uint16_t ui16Value; + + // + // The function that is called when the read-modify-write has been + // completed. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; +} +tI2CMReadModifyWrite16; + +//***************************************************************************** +// +// The structure that contains the state of an I2C write request of 8-bit data. +// +//***************************************************************************** +typedef struct +{ + // + // A pointer to the I2C master interface instance used for the write + // request. + // + tI2CMInstance *psI2CInst; + + // + // The buffer used for the I2C transfers. + // + uint8_t pui8Buffer[2]; + + // + // The number of values to write to the I2C device. + // + uint16_t ui16Count; + + // + // A pointer to the buffer containing the data to write to the I2C device. + // + const uint8_t *pui8Data; + + // + // The function that is called when the write has been completed. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; +} +tI2CMWrite8; + +//***************************************************************************** +// +// The structure that contains the state of an I2C read request of 16-bit data +// from a big-endian device. +// +//***************************************************************************** +typedef struct +{ + // + // A pointer to the I2C master interface instance used for the read + // request. + // + tI2CMInstance *psI2CInst; + + // + // A pointer to the buffer containing the data read from the I2C device. + // + uint8_t *pui8Data; + + // + // The number of 16-bit values to read from the I2C device. + // + uint16_t ui16Count; + + // + // The function that is called when the read has been completed. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; +} +tI2CMRead16BE; + +//***************************************************************************** +// +// The structure that contains the state of an I2C write request of 16-bit data +// to a big-endian device. +// +//***************************************************************************** +typedef struct +{ + // + // A pointer to the I2C master interface instance used for the write + // request. + // + tI2CMInstance *psI2CInst; + + // + // The buffer used for the I2C transfers. + // + uint8_t pui8Buffer[2]; + + // + // The number of 16-bit values to write to the I2C device. + // + uint16_t ui16Count; + + // + // A pointer to the buffer containing the data to write to the I2C device. + // + const uint8_t *pui8Data; + + // + // The function that is called when the write has been completed. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; +} +tI2CMWrite16BE; + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern void I2CMIntHandler(tI2CMInstance *psInst); +extern void I2CMInit(tI2CMInstance *psInst, uint32_t ui32Base, + uint_fast8_t ui8Int, uint_fast8_t ui8TxDMA, + uint_fast8_t ui8RxDMA, uint32_t ui32Clock); +extern uint_fast8_t I2CMCommand(tI2CMInstance *psInst, uint_fast8_t ui8Addr, + const uint8_t *pui8WriteData, + uint_fast16_t ui16WriteCount, + uint_fast16_t ui16WriteBatchSize, + uint8_t *pui8ReadData, + uint_fast16_t ui16ReadCount, + uint_fast16_t ui16ReadBatchSize, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t I2CMTransferResume(tI2CMInstance *psInst, + uint8_t *pui8Data); +extern uint_fast8_t I2CMReadModifyWrite8(tI2CMReadModifyWrite8 *psInst, + tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t I2CMReadModifyWrite16LE(tI2CMReadModifyWrite16 *psInst, + tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, + uint_fast8_t ui8Reg, + uint_fast16_t ui16Mask, + uint_fast16_t ui16Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t I2CMWrite8(tI2CMWrite8 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t I2CMRead16BE(tI2CMRead16BE *psInst, + tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, uint_fast8_t ui8Reg, + uint16_t *pui16Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t I2CMWrite16BE(tI2CMWrite16BE *psInst, + tI2CMInstance *psI2CInst, + uint_fast8_t ui8Addr, uint_fast8_t ui8Reg, + const uint16_t *pui16Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); + +//***************************************************************************** +// +// A convenience wrapper around I2CMCommand to perform a write. +// +//***************************************************************************** +inline uint_fast8_t +I2CMWrite(tI2CMInstance *psInst, uint_fast8_t ui8Addr, const uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + return(I2CMCommand(psInst, ui8Addr, pui8Data, ui16Count, ui16Count, 0, 0, + 0, pfnCallback, pvCallbackData)); +} + +//***************************************************************************** +// +// A convenience wrapper around I2CMCommand to perform a read. +// +//***************************************************************************** +inline uint_fast8_t +I2CMRead(tI2CMInstance *psInst, uint_fast8_t ui8Addr, + const uint8_t *pui8WriteData, uint_fast16_t ui16WriteCount, + uint8_t *pui8ReadData, uint_fast16_t ui16ReadCount, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + return(I2CMCommand(psInst, ui8Addr, pui8WriteData, ui16WriteCount, + ui16WriteCount, pui8ReadData, ui16ReadCount, + ui16ReadCount, pfnCallback, pvCallbackData)); +} + +//***************************************************************************** +// +// A convenience wrapper around I2CMCommand to perform a batched write. +// +//***************************************************************************** +inline uint_fast8_t +I2CMWriteBatched(tI2CMInstance *psInst, uint_fast8_t ui8Addr, + const uint8_t *pui8Data, uint_fast16_t ui16Count, + uint_fast16_t ui16BatchSize, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + return(I2CMCommand(psInst, ui8Addr, pui8Data, ui16Count, ui16BatchSize, 0, + 0, 0, pfnCallback, pvCallbackData)); +} + +//***************************************************************************** +// +// A convenience wrapper around I2CMCommand to perform a batched read. +// +//***************************************************************************** +inline uint_fast8_t +I2CMReadBatched(tI2CMInstance *psInst, uint_fast8_t ui8Addr, + const uint8_t *pui8WriteData, uint_fast16_t ui16WriteCount, + uint_fast16_t ui16WriteBatchSize, uint8_t *pui8ReadData, + uint_fast16_t ui16ReadCount, uint_fast16_t ui16ReadBatchSize, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + return(I2CMCommand(psInst, ui8Addr, pui8WriteData, ui16WriteCount, + ui16WriteBatchSize, pui8ReadData, ui16ReadCount, + ui16ReadBatchSize, pfnCallback, pvCallbackData)); +} + +//***************************************************************************** +// +// A 16-bit big-endian read-modify-write in terms of the little-endian version. +// +//***************************************************************************** +inline uint_fast8_t +I2CMReadModifyWrite16BE(tI2CMReadModifyWrite16 *psInst, + tI2CMInstance *psI2CInst, uint_fast8_t ui8Addr, + uint_fast8_t ui8Reg, uint_fast16_t ui16Mask, + uint_fast16_t ui16Value, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + return(I2CMReadModifyWrite16LE(psInst, psI2CInst, ui8Addr, ui8Reg, + (((ui16Mask & 0xff00) >> 8) | + ((ui16Mask & 0x00ff) << 8)), + (((ui16Value & 0xff00) >> 8) | + ((ui16Value & 0x00ff) << 8)), + pfnCallback, pvCallbackData)); +} + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_I2CM_DRV_H__ diff --git a/sensorlib/isl29023.c b/sensorlib/isl29023.c new file mode 100644 index 0000000..313ced9 --- /dev/null +++ b/sensorlib/isl29023.c @@ -0,0 +1,668 @@ +//***************************************************************************** +// +// isl29023.c - Driver for the ISL29023 Light Sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include +#include "sensorlib/hw_isl29023.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/isl29023.h" + +//***************************************************************************** +// +//! \addtogroup isl29023_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// Range setting to floating point range value lookup table +// +//***************************************************************************** +const float g_fRangeLookup[4] = +{ + 1000.0, + 4000.0, + 16000.0, + 64000.0 +}; + +//***************************************************************************** +// +// Resolution setting to floating point resolution value lookup table +// +//***************************************************************************** +const float g_fResolutionLookup[4] = +{ + 65536.0, + 4096.0, + 256.0, + 16.0 +}; + +//***************************************************************************** +// +// Beta value lookup based on datasheet typical values for DATA_IR1, DATA_IR2, +// DATA_IR3, DATA_IR4. These should be reasonable for 16 bit conversions. +// However, Beta changes with resolution and background IR conditions. +// +//***************************************************************************** +const float g_fBetaLookup[4] = +{ + 95.238, + 23.810, + 5.952, + 1.486 +}; + +//***************************************************************************** +// +// The states of the ISL29023 state machine. +// +//***************************************************************************** +#define ISL29023_STATE_IDLE 0 +#define ISL29023_STATE_INIT 1 +#define ISL29023_STATE_READ 2 +#define ISL29023_STATE_WRITE 3 +#define ISL29023_STATE_RMW 4 +#define ISL29023_STATE_READ_DATA 5 + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// ISL29023 have completed. +// +//***************************************************************************** +static void +ISL29023Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tISL29023 *psInst; + uint8_t *pui8Data; + + // + // Convert the instance data into a pointer to a tBMA180 structure. + // + psInst = (tISL29023 *)pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = ISL29023_STATE_IDLE; + } + + // + // Determine the current state of the ISL29023 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case ISL29023_STATE_INIT: + case ISL29023_STATE_READ: + case ISL29023_STATE_READ_DATA: + default: + { + // + // A register operation is complete. Return to IDLE state + // the value read from the register is in the pui8Data buffer and + // can be accessed directly by the calling application after + // receiving the callback. + // + psInst->ui8State = ISL29023_STATE_IDLE; + break; + } + + // + // A write to the ISL29023 control and config registers is complete. + // + case ISL29023_STATE_WRITE: + { + // + // Set the range and resolution to the new values. If the register + // was not modified, the values will be the same so this has no + // effect. + // + psInst->ui8Range = psInst->ui8NewRange; + psInst->ui8Resolution = psInst->ui8NewResolution; + + // + // The state machine is now idle. + // + psInst->ui8State = ISL29023_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read modify write operation has just completed. + // + case ISL29023_STATE_RMW: + { + // + // Check if the register that was written contained the range or + // resolution data that we need to track. + // + pui8Data = psInst->uCommand.sReadModifyWriteState.pui8Buffer; + if((pui8Data[0] == ISL29023_O_CMD_II) && + (ui8Status == I2CM_STATUS_SUCCESS)) + { + // + // Store the latest range and resolution settings + // + psInst->ui8Range = ((pui8Data[1] & ISL29023_CMD_II_RANGE_M) >> + ISL29023_CMD_II_RANGE_S); + psInst->ui8Resolution = ((pui8Data[1] & + ISL29023_CMD_II_ADC_RES_M) >> + ISL29023_CMD_II_ADC_RES_S); + } + + // + // The state machine is now idle. + // + psInst->ui8State = ISL29023_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == ISL29023_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the ISL29023 driver. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param psI2CInst is a pointer to the I2C driver instance data. +//! \param ui8I2CAddr is the I2C address of the ISL29023 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the ISL29023 driver, preparing it for operation. +//! This function also asserts a reset signal to the ISL29023 to clear any +//! previous configuration data. +//! +//! \return Returns 1 if the ISL29023 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +ISL29023Init(tISL29023 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Initialize the ISL29023 instance structure + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = ISL29023_STATE_INIT; + psInst->ui8Range = ISL29023_CMD_II_RANGE_1K >> ISL29023_CMD_II_RANGE_S; + psInst->ui8NewRange = ISL29023_CMD_II_RANGE_1K >> ISL29023_CMD_II_RANGE_S; + psInst->ui8Resolution = (ISL29023_CMD_II_ADC_RES_16 >> + ISL29023_CMD_II_ADC_RES_S); + psInst->ui8NewResolution = (ISL29023_CMD_II_ADC_RES_16 >> + ISL29023_CMD_II_ADC_RES_S); + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Put the device into power down mode. + // + psInst->pui8Data[0] = ISL29023_O_CMD_I; + psInst->pui8Data[1] = ISL29023_CMD_I_OP_MODE_POWER_DOWN; + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 2, + ISL29023Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = ISL29023_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from ISL29023 registers. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the ISL29023. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +ISL29023Read(tISL29023 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the ISL29023 driver is not idle (in other words, + // there is already an outstanding request to the ISL29023). + // + if(psInst->ui8State != ISL29023_STATE_IDLE) + { + return(0); + } + // + // Store the Callback information + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // set ISL29023 state + // + psInst->ui8State = ISL29023_STATE_READ; + + // + // Load the command buffer with the appropriate register information + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + + // + // Start the I2CM read and return indication. + // + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + ISL29023Callback, psInst) == 0) + { + psInst->ui8State = ISL29023_STATE_IDLE; + return(0); + } + + return(1); +} + +//***************************************************************************** +// +//! Write register data to the ISL29023. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the ISL29023. The first byte of the \e pui8Data buffer contains the value +//! to be written into the \e ui8Reg register, the second value contains the +//! data to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +ISL29023Write(tISL29023 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the ISL29023 driver is not idle (in other words, + // there is already an outstanding request to the ISL29023). + // + if(psInst->ui8State != ISL29023_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the CMD_II register is being written. + // + if((ui8Reg <= ISL29023_O_CMD_II) && + ((ui8Reg + ui16Count) > ISL29023_O_CMD_II)) + { + // + // Extract the range and resolution from the CMD_II register value. + // + psInst->ui8NewRange = ((pui8Data[ui8Reg - ISL29023_O_CMD_II] & + ISL29023_CMD_II_RANGE_M) >> + ISL29023_CMD_II_RANGE_S); + psInst->ui8NewResolution = ((pui8Data[ui8Reg - ISL29023_O_CMD_II] & + ISL29023_CMD_II_ADC_RES_M) >> + ISL29023_CMD_II_ADC_RES_S); + } + + // + // Move state machine to the write state + // + psInst->ui8State = ISL29023_STATE_WRITE; + + // + // Add the i2c address and the register offset to the data buffer. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, + ISL29023Callback, psInst) == 0) + { + // + // I2C write failed, move to idle state and return the failure. + // + psInst->ui8State = ISL29023_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of an ISL29023 register. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the ISL29023 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! ISL29023. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +ISL29023ReadModifyWrite(tISL29023 *psInst, uint_fast8_t ui8Reg, + uint8_t ui8Mask, uint8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the ISL29023 driver is not in the idle state. + // + if(psInst->ui8State != ISL29023_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // set ISL29023 state + // + psInst->ui8State = ISL29023_STATE_RMW; + + // + // Submit the read-modify-write request to the ISL29023. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, ISL29023Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = ISL29023_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the light data from the ISL29023. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the ISL29023 data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - ISL29023DataLightVisibleGetRaw() +//! - ISL29023DataLightVisibleGetFloat() +//! - ISL29023DataLightIRGetRaw() +//! - ISL29023DataLightIRGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +ISL29023DataRead(tISL29023 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the ISL29023 driver is not idle (in other words, + // there is already an outstanding request to the ISL29023). + // + if(psInst->ui8State != ISL29023_STATE_IDLE) + { + return(0); + } + + // + // Store the Callback information + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // set ISL29023 state + // + psInst->ui8State = ISL29023_STATE_READ_DATA; + + psInst->uCommand.pui8Buffer[0] = ISL29023_O_DATA_OUT_LSB; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 2, + ISL29023Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = ISL29023_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param pui16Visible is a pointer to the value into which the raw light data +//! is stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +ISL29023DataLightVisibleGetRaw(tISL29023 *psInst, uint16_t *pui16Visible) +{ + // + // Return the raw light value. + // + *pui16Visible = (psInst->pui8Data[1] << 8) | psInst->pui8Data[0]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param pfVisibleLight is a pointer to the value into which the light data +//! is stored as floating point lux. +//! +//! This function returns the light data from the most recent data read, +//! converted into lux. +//! +//! \return None. +// +//***************************************************************************** +void +ISL29023DataLightVisibleGetFloat(tISL29023 *psInst, float *pfVisibleLight) +{ + uint16_t ui16Light; + float fRange, fResolution; + + // + // Get the raw light data from the instance structure + // + ISL29023DataLightVisibleGetRaw(psInst, &ui16Light); + + // + // Get the floating point values for range and resolution from the lookup. + // + fRange = g_fRangeLookup[psInst->ui8Range]; + fResolution = g_fResolutionLookup[psInst->ui8Resolution]; + + // + // Calculate light reading in lux. + // + *pfVisibleLight = ((float)ui16Light) * (fRange / fResolution); +} + +//***************************************************************************** +// +//! Gets the raw measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param pui16IR is a pointer to the value into which the raw IR data is +//! stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +ISL29023DataLightIRGetRaw(tISL29023 *psInst, uint16_t *pui16IR) +{ + // + // Return the raw light value. + // + *pui16IR = (psInst->pui8Data[1] << 8) | psInst->pui8Data[0]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the ISL29023 instance data. +//! \param pfIR is a pointer to the value into which the IR data is stored as +//! floating point lux. +//! +//! This function returns the IR data from the most recent data read, converted +//! into lux. +//! +//! \return None. +// +//***************************************************************************** +void +ISL29023DataLightIRGetFloat(tISL29023 *psInst, float *pfIR) +{ + uint16_t i16IR; + + ISL29023DataLightIRGetRaw(psInst, &i16IR); + + *pfIR = ((float) i16IR) / g_fBetaLookup[psInst->ui8Range]; +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/isl29023.h b/sensorlib/isl29023.h new file mode 100644 index 0000000..184c702 --- /dev/null +++ b/sensorlib/isl29023.h @@ -0,0 +1,166 @@ +//***************************************************************************** +// +// isl29023.h - Prototypes for the ISL29023 light sensor driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_ISL29023_H__ +#define __SENSORLIB_ISL29023_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the ISL29023 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the ISL29023. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the ISL29023. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the ISL29023. + // + uint8_t ui8State; + + // + // The data buffer used for sending/receiving data to/from the ISL29023. + // + uint8_t pui8Data[4]; + + // + // Instance copy of the range setting. Used in GetFloat functions + // + uint8_t ui8Range; + + // + // The new range, which is used when a register write succeeds. + // + uint8_t ui8NewRange; + + // + // Instance copy of the resolution setting. Used in GetFloat function. + // + uint8_t ui8Resolution; + + // + // The new resolution, which is used when a register write succeeds. + // + uint8_t ui8NewResolution; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[3]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tISL29023; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t ISL29023Init(tISL29023 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t ISL29023Read(tISL29023 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t ISL29023Write(tISL29023 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t ISL29023ReadModifyWrite(tISL29023 *psInst, + uint_fast8_t ui8Reg, + uint8_t ui8Mask, uint8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t ISL29023DataRead(tISL29023 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void ISL29023DataLightVisibleGetRaw(tISL29023 *psInst, + uint16_t *pui16Visible); +extern void ISL29023DataLightVisibleGetFloat(tISL29023 *psInst, + float *pfVisible); +extern void ISL29023DataLightIRGetRaw(tISL29023 *psInst, uint16_t *pui16IR); +extern void ISL29023DataLightIRGetFloat(tISL29023 *psInst, float *pfIR); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_ISL29023_H__ + diff --git a/sensorlib/kxti9.c b/sensorlib/kxti9.c new file mode 100644 index 0000000..38de17b --- /dev/null +++ b/sensorlib/kxti9.c @@ -0,0 +1,777 @@ +//***************************************************************************** +// +// kxti9.c - Driver for the KXTI9 accelerometer. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_kxti9.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/kxti9.h" + +//***************************************************************************** +// +//! \addtogroup kxti9_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the KXTI9 state machine. +// +//***************************************************************************** +#define KXTI9_STATE_IDLE 0 // State machine is idle +#define KXTI9_STATE_INIT_RES 1 // Waiting for intialization +#define KXTI9_STATE_INIT_WAIT 2 // Waiting for reset to complete +#define KXTI9_STATE_LAST 3 // Last state of init +#define KXTI9_STATE_READ 4 // Waiting for read +#define KXTI9_STATE_WRITE 5 // Waiting for write +#define KXTI9_STATE_RMW 6 // Waiting for read-modify-write + +//***************************************************************************** +// +// The factors used to convert the 8-bit acceleration readings from the KXTI9 +// into floating point values in m/s^2. +// +//***************************************************************************** +static const float g_fAccelFactors8[] = +{ + (2.0 * 9.81) / 128.0, + (4.0 * 9.81) / 128.0, + (8.0 * 9.81) / 128.0 +}; + +//***************************************************************************** +// +// The factors used to convert the 12-bit acceleration readings from the KXTI9 +// into floating point values in m/s^2. +// +//***************************************************************************** +static const float g_fAccelFactors12[] = +{ + (2.0 * 9.81) / 2048.0, + (4.0 * 9.81) / 2048.0, + (8.0 * 9.81) / 2048.0 +}; + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the KXTI9 +// have completed. +// +//***************************************************************************** +static void +KXTI9Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tKXTI9 *psInst; + + // + // Convert the instance data into a pointer to a tKXTI9 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if((ui8Status != I2CM_STATUS_SUCCESS) && + (psInst->ui8State != KXTI9_STATE_INIT_WAIT)) + { + psInst->ui8State = KXTI9_STATE_IDLE; + } + + // + // Determine the current state of the KXTI9 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case KXTI9_STATE_LAST: + case KXTI9_STATE_READ: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = KXTI9_STATE_IDLE; + + // + // Done. + // + break; + } + + case KXTI9_STATE_INIT_RES: + { + // + // Try to read back to determine if reset is done. We expect to see + // a NAK. + // + psInst->uCommand.pui8Buffer[0] = KXTI9_O_CTRL3; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, + KXTI9Callback, psInst); + + psInst->ui8State = KXTI9_STATE_INIT_WAIT; + break; + } + + case KXTI9_STATE_INIT_WAIT: + { + // + // Check to see if there was finally an ACK. + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + // + // Read again. + // + psInst->uCommand.pui8Buffer[0] = KXTI9_O_CTRL3; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, + KXTI9Callback, psInst); + } + else + { + // + // Check the read data to make sure it jibes. + // + if(psInst->pui8Data[0] == 0x4d) + { + // + // Device is out of reset, enable the device. + // + psInst->uCommand.pui8Buffer[0] = KXTI9_O_CTRL1; + psInst->uCommand.pui8Buffer[1] = KXTI9_CTRL1_PC1; + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, KXTI9Callback, + psInst); + } + else + { + ui8Status = I2CM_STATUS_ERROR; + } + + // + // This is the last init write. + // + psInst->ui8State = KXTI9_STATE_LAST; + } + break; + } + + case KXTI9_STATE_WRITE: + { + // + // Set the accelerometer range and resolution to the new value. + // If the register was not modified, the values will be the same so + // this has no effect. + // + psInst->ui8Resolution = psInst->ui8NewResolution; + psInst->ui8Range = psInst->ui8NewRange; + + // + // The state machine is now idle. + // + psInst->ui8State = KXTI9_STATE_IDLE; + break; + } + + case KXTI9_STATE_RMW: + { + // + // See if the CTRL3 register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + KXTI9_O_CTRL3) + { + // + // See if a soft reset has been issued. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + KXTI9_CTRL3_SRST) + { + // + // Default range setting is +/- 2 g + // + psInst->ui8Range = 0; + psInst->ui8NewRange = 0; + + // + // Default resolution is 8-bit. + // + psInst->ui8Resolution = 0; + psInst->ui8NewResolution = 0; + } + } + + // + // See if the CTRL1 register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + KXTI9_O_CTRL1) + { + // + // Extract the range and resolution from the register value. + // + psInst->ui8Range = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + KXTI9_CTRL1_GSEL_M) >> KXTI9_CTRL1_GSEL_S); + psInst->ui8Resolution = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + KXTI9_CTRL1_RES) >> 6); + } + + // + // The state machine is now idle. + // + psInst->ui8State = KXTI9_STATE_IDLE; + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == KXTI9_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + //s + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the KXTI9 driver. +//! +//! \param psInst is a pointer to the KXTI9 instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the KXTI9 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the KXTI9 driver, preparing it for operation. +//! +//! \return Returns 1 if the KXTI9 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +KXTI9Init(tKXTI9 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Initialize the KXTI9 instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = KXTI9_STATE_INIT_RES; + psInst->ui8Resolution = 0; + psInst->ui8NewResolution = 0; + psInst->ui8Range = KXTI9_CTRL1_GSEL_2G >> KXTI9_CTRL1_GSEL_S; + psInst->ui8NewRange = KXTI9_CTRL1_GSEL_2G >> KXTI9_CTRL1_GSEL_S; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Write the EE_W bit of CTRL_REG0 (allowing the configuration registers to + // be modified). + // + psInst->pui8Data[0] = KXTI9_O_CTRL3; + psInst->pui8Data[1] = KXTI9_CTRL3_SRST; + if(I2CMWrite(psInst->psI2CInst, ui8I2CAddr, psInst->pui8Data, 2, + KXTI9Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = KXTI9_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from KXTI9 registers. +//! +//! \param psInst is a pointer to the KXTI9 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the KXTI9. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +KXTI9Read(tKXTI9 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the KXTI9 driver is not idle (in other words, there + // is already an outstanding request to the KXTI9). + // + if(psInst->ui8State != KXTI9_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = KXTI9_STATE_READ; + + // + // Read the requested registers from the KXTI9. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + KXTI9Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = KXTI9_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to KXTI9 registers. +//! +//! \param psInst is a pointer to the KXTI9 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the KXTI9. The first byte of the \e pui8Data buffer contains the value to +//! be written into the \e ui8Reg register, the second value contains the data +//! to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +KXTI9Write(tKXTI9 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the KXTI9 driver is not idle (in other words, there + // is already an outstanding request to the KXTI9). + // + if(psInst->ui8State != KXTI9_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + psInst->ui8NewRange = psInst->ui8Range; + psInst->ui8NewResolution = psInst->ui8Resolution; + + // + // See if the CTRL3 register is being written. + // + if((ui8Reg <= KXTI9_O_CTRL3) && + ((ui8Reg + ui16Count) > KXTI9_O_CTRL3)) + { + // + // See if a soft reset is being requested. + // + if(pui8Data[ui8Reg - KXTI9_O_CTRL3] & KXTI9_CTRL3_SRST) + { + // + // Default range setting is +/- 2 g. + // + psInst->ui8NewRange = 0; + + // + // Default resolution is 8-bit. + // + psInst->ui8NewResolution = 0; + } + } + + // + // See if the CTRL1 register is being written. + // + if((ui8Reg <= KXTI9_O_CTRL1) && + ((ui8Reg + ui16Count) > KXTI9_O_CTRL1)) + { + // + // Extract the range and resolution the register value. + // + psInst->ui8NewRange = + ((pui8Data[ui8Reg - KXTI9_O_CTRL1] & KXTI9_CTRL1_GSEL_M) + >> KXTI9_CTRL1_GSEL_S); + psInst->ui8NewResolution = + ((pui8Data[ui8Reg - KXTI9_O_CTRL1] & KXTI9_CTRL1_RES) >> 6); + } + + // + // Save the details of this write. + // + psInst->uCommand.sWriteState.pui8Data = pui8Data; + psInst->uCommand.sWriteState.ui16Count = ui16Count; + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = KXTI9_STATE_WRITE; + + // + // Write the requested registers to the KXTI9. + // + pui8Data[0] = ui8Reg; + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, pui8Data, ui16Count + 1, + KXTI9Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = KXTI9_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a KXTI9 register. +//! +//! \param psInst is a pointer to the KXTI9 instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the KXTI9 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! KXTI9. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +KXTI9ReadModifyWrite(tKXTI9 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the KXTI9 driver is not idle (in other words, there + // is already an outstanding request to the KXTI9). + // + if(psInst->ui8State != KXTI9_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = KXTI9_STATE_RMW; + + // + // Submit the read-modify-write request to the KXTI9. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, KXTI9Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = KXTI9_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the acceleration and temperature data from the KXTI9. +//! +//! \param psInst is a pointer to the KXTI9 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the KXTI9 data registers. When the read +//! has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - KXTI9DataAccelGetRaw() +//! - KXTI9DataAccelGetFloat() +//! - KXTI9DataTemperatureGetRaw() +//! - KXTI9DataTemperatureGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +KXTI9DataRead(tKXTI9 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the KXTI9 driver is not idle (in other words, there + // is already an outstanding request to the KXTI9). + // + if(psInst->ui8State != KXTI9_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = KXTI9_STATE_READ; + + // + // Read the data registers from the KXTI9. + // + psInst->pui8Data[0] = KXTI9_O_XOUT_L; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 1, + psInst->pui8Data, 6, KXTI9Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = KXTI9_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw acceleration data from the most recent data read. +//! +//! \param psInst is a pointer to the KXTI9 instance data. +//! \param pui16AccelX is a pointer to the value into which the raw X-axis +//! acceleration data is stored. +//! \param pui16AccelY is a pointer to the value into which the raw Y-axis +//! acceleration data is stored. +//! \param pui16AccelZ is a pointer to the value into which the raw Z-axis +//! acceleration data is stored. +//! +//! This function returns the raw acceleration data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +KXTI9DataAccelGetRaw(tKXTI9 *psInst, uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, uint_fast16_t *pui16AccelZ) +{ + // + // Return the raw acceleration values. + // + if(pui16AccelX) + { + *pui16AccelX = ((psInst->pui8Data[1] << 4) | + (psInst->pui8Data[0] >> 4)); + } + if(pui16AccelY) + { + *pui16AccelY = ((psInst->pui8Data[3] << 4) | + (psInst->pui8Data[2] >> 4)); + } + if(pui16AccelZ) + { + *pui16AccelZ = ((psInst->pui8Data[5] << 4) | + (psInst->pui8Data[4] >> 4)); + } +} + +//***************************************************************************** +// +//! Gets the acceleration data from the most recent data read. +//! +//! \param psInst is a pointer to the KXTI9 instance data. +//! \param pfAccelX is a pointer to the value into which the X-axis +//! acceleration data is stored. +//! \param pfAccelY is a pointer to the value into which the Y-axis +//! acceleration data is stored. +//! \param pfAccelZ is a pointer to the value into which the Z-axis +//! acceleration data is stored. +//! +//! This function returns the acceleration data from the most recent data read, +//! converted into g. If any of the output data pointers are \b NULL, the +//! corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +KXTI9DataAccelGetFloat(tKXTI9 *psInst, float *pfAccelX, float *pfAccelY, + float *pfAccelZ) +{ + float fFactor; + int16_t iX, iY, iZ; + + // + // Get the acceleration conversion factor for the current range. + // + fFactor = (psInst->ui8Resolution == 0) ? g_fAccelFactors8[psInst->ui8Range] : + g_fAccelFactors12[psInst->ui8Range]; + + if(psInst->ui8Resolution) + { + // + // Get conversion data and store in temporary variables. + // + iX = (int16_t)((psInst->pui8Data[1] << 4) | (psInst->pui8Data[0] >> 4)); + iY = (int16_t)((psInst->pui8Data[3] << 4) | (psInst->pui8Data[2] >> 4)); + iZ = (int16_t)((psInst->pui8Data[5] << 4) | (psInst->pui8Data[4] >> 4)); + + // + // Sign extend 12-bit data. + // + iX |= (iX & 0x800) ? 0xf000 : 0; + iY |= (iY & 0x800) ? 0xf000 : 0; + iZ |= (iZ & 0x800) ? 0xf000 : 0; + } + else + { + // + // Chop off the lower 4 bits of the data. 8-bit mode only returns 8 + // valid bits, but can have garbage in the lower 4. + // + iX = (int16_t)(psInst->pui8Data[1]); + iY = (int16_t)(psInst->pui8Data[3]); + iZ = (int16_t)(psInst->pui8Data[5]); + + // + // Sign extend 8-bit data. + // + iX |= (iX & 0x80) ? 0xff00 : 0; + iY |= (iY & 0x80) ? 0xff00 : 0; + iZ |= (iZ & 0x80) ? 0xff00 : 0; + } + + // + // Convert the acceleration values into floating-point g values. + // + if(pfAccelX) + { + *pfAccelX = (float)(iX) * fFactor; + } + if(pfAccelY) + { + *pfAccelY = (float)(iY) * fFactor; + } + if(pfAccelZ) + { + *pfAccelZ = (float)(iZ) * fFactor; + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/kxti9.h b/sensorlib/kxti9.h new file mode 100644 index 0000000..1c8e7fc --- /dev/null +++ b/sensorlib/kxti9.h @@ -0,0 +1,170 @@ +//***************************************************************************** +// +// KXTI9.h - Prototypes for the KXTI9 accelerometer driver. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_KXTI9_H__ +#define __SENSORLIB_KXTI9_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the KXTI9 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the KXTI9. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the KXTI9. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the KXTI9. + // + uint8_t ui8State; + + // + // The ADC resolution of the KXTI9. + // + uint8_t ui8Resolution; + + uint8_t ui8NewResolution; + + // + // The current operating range (g force) of the KXTI9. + // + uint8_t ui8Range; + + uint8_t ui8NewRange; + + // + // The data buffer used for sending/receiving data to/from the KXTI9. + // + uint8_t pui8Data[7]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + struct + { + // + // The buffer that is being written to the KXTI9. + // + uint8_t *pui8Data; + + // + // The number of bytes being written to the KXTI9. + // + uint16_t ui16Count; + } + sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tKXTI9; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t KXTI9Init(tKXTI9 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t KXTI9Read(tKXTI9 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t KXTI9Write(tKXTI9 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t KXTI9ReadModifyWrite(tKXTI9 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t KXTI9DataRead(tKXTI9 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void KXTI9DataAccelGetRaw(tKXTI9 *psInst, uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, + uint_fast16_t *pui16AccelZ); +extern void KXTI9DataAccelGetFloat(tKXTI9 *psInst, float *pfAccelX, + float *pfAccelY, float *pfAccelZ); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_KXTI9_H__ diff --git a/sensorlib/l3gd20h.c b/sensorlib/l3gd20h.c new file mode 100644 index 0000000..6694660 --- /dev/null +++ b/sensorlib/l3gd20h.c @@ -0,0 +1,722 @@ +//***************************************************************************** +// +// l3gd20h.c - Driver for the ST L3GD20H gyroscope. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_l3gd20h.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/l3gd20h.h" + +//***************************************************************************** +// +//! \addtogroup l3gd20h_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the L3GD20H state machine. +// +//***************************************************************************** +#define L3GD20H_STATE_IDLE 0 // State machine is idle +#define L3GD20H_STATE_INIT_RES 1 // Waiting for initialization +#define L3GD20H_STATE_INIT_WAIT 2 // Waiting for reset to complete +#define L3GD20H_STATE_READ 3 // Waiting for read +#define L3GD20H_STATE_WRITE 4 // Waiting for write +#define L3GD20H_STATE_RMW 5 // Waiting for read-modify-write + +//***************************************************************************** +// +// The factors used to convert the gyroscope readings from the L3GD20H into +// floating point values in radians per second. +// +// Per the data-sheet, the sensitivity is 8.75, 17.50, and 70.00 mdps/digit for +// for 245, 500, and 2000 DPS scales respectively. +// +// mdeg 1 deg PI rad +// 8.75 ---- * ---- * --- = 1.5271630955e-4f rad/sec per digit +// sec 1000 mdeg 180 deg +// +// Values are obtained by taking the degree per second conversion factors +// from the data sheet and then converting to radians per sec (1 degree = +// 0.0174532925 radians). +// +//***************************************************************************** +static const float g_pfL3GD20HGyroFactors[] = +{ + 1.5271631e-5f, // Range = +/- 245 dps + 3.0543262e-4f, // Range = +/- 500 dps + 1.2217305e-3f, // Range = +/- 2000 dps + 1.2217305e-3f // Range = +/- 2000 dps +}; + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// L3GD20H have completed. +// +//***************************************************************************** +static void +L3GD20HCallback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tL3GD20H *psInst; + + // + // Convert the instance data into a pointer to a tL3GD20H structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = L3GD20H_STATE_IDLE; + } + + // + // Determine the current state of the L3GD20H state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case L3GD20H_STATE_READ: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = L3GD20H_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // L3GD20H Device reset was issued + // + case L3GD20H_STATE_INIT_RES: + { + // + // Issue a read of the status register to confirm reset is done. + // + psInst->uCommand.pui8Buffer[0] = L3GD20H_O_LOW_ODR; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, + L3GD20HCallback, psInst); + + psInst->ui8State = L3GD20H_STATE_INIT_WAIT; + + // + // Done. + // + break; + } + + // + // Status register was read, check if reset is done before proceeding. + // + case L3GD20H_STATE_INIT_WAIT: + { + // + // Check the value read back from status to determine if device + // is still in reset or if it is ready. + // + if(psInst->pui8Data[0] & L3GD20H_LOW_ODR_SWRESET_M) + { + // + // Device still in reset so begin polling this register. + // + psInst->uCommand.pui8Buffer[0] = L3GD20H_O_LOW_ODR; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, + L3GD20HCallback, psInst); + } + else + { + // + // Device is out of reset, move to the idle state. + // + psInst->ui8State = L3GD20H_STATE_IDLE; + } + + // + // Done. + // + break; + } + + // + // A write just completed + // + case L3GD20H_STATE_WRITE: + { + // + // Set the gyroscope ranges to the new values. If the register was + // not modified, the values will be the same so this has no effect. + // + psInst->ui8GyroFsSel = psInst->ui8NewGyroFsSel; + + // + // The state machine is now idle. + // + psInst->ui8State = L3GD20H_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read-modify-write just completed + // + case L3GD20H_STATE_RMW: + { + // + // See if the PWR_MGMT_1 register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + L3GD20H_O_LOW_ODR) + { + // + // See if a soft reset has been issued. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + L3GD20H_LOW_ODR_SWRESET_M) + { + // + // Default range setting is +/- 245 degrees/s + // + psInst->ui8GyroFsSel = 0; + psInst->ui8NewGyroFsSel = 0; + } + } + + // + // See if the GYRO_CONFIG register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + L3GD20H_O_CTRL4) + { + // + // Extract the FS_SEL from the GYRO_CONFIG register value. + // + psInst->ui8GyroFsSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + L3GD20H_CTRL4_FS_M) >> + L3GD20H_CTRL4_FS_S); + } + + // + // The state machine is now idle. + // + psInst->ui8State = L3GD20H_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == L3GD20H_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the L3GD20H driver. +//! +//! \param psInst is a pointer to the L3GD20H instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the L3GD20H device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the L3GD20H driver, preparing it for operation. +//! +//! \return Returns 1 if the L3GD20H driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +L3GD20HInit(tL3GD20H *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Initialize the L3GD20H instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Default range setting is +/- 245 degrees/s + // + psInst->ui8GyroFsSel = + (L3GD20H_CTRL4_FS_245DPS & L3GD20H_CTRL4_FS_M) >> L3GD20H_CTRL4_FS_S; + psInst->ui8NewGyroFsSel = + (L3GD20H_CTRL4_FS_245DPS & L3GD20H_CTRL4_FS_M) >> L3GD20H_CTRL4_FS_S; + + // + // Set the state to show we are initiating a reset. + // + psInst->ui8State = L3GD20H_STATE_INIT_RES; + + // + // Load the buffer with command to perform device reset + // + psInst->pui8Data[0] = L3GD20H_O_LOW_ODR; + psInst->pui8Data[1] = L3GD20H_LOW_ODR_SWRESET_RESET; + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, L3GD20HCallback, psInst) == 0) + { + psInst->ui8State = L3GD20H_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from L3GD20H registers. +//! +//! \param psInst is a pointer to the L3GD20H instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the L3GD20H. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +L3GD20HRead(tL3GD20H *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the L3GD20H driver is not idle (in other words, + // there is already an outstanding request to the L3GD20H). + // + if(psInst->ui8State != L3GD20H_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = L3GD20H_STATE_READ; + + // + // Read the requested registers from the L3GD20H. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + L3GD20HCallback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = L3GD20H_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to L3GD20H registers. +//! +//! \param psInst is a pointer to the L3GD20H instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the L3GD20H. The first byte of the \e pui8Data buffer contains the value +//! to be written into the \e ui8Reg register, the second value contains the +//! data to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +L3GD20HWrite(tL3GD20H *psInst, uint_fast8_t ui8Reg, const uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the L3GD20H driver is not idle (in other words, + // there is already an outstanding request to the L3GD20H). + // + if(psInst->ui8State != L3GD20H_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the PWR_MGMT_1 register is being written. + // + if((ui8Reg <= L3GD20H_O_LOW_ODR) && + ((ui8Reg + ui16Count) > L3GD20H_O_LOW_ODR)) + { + // + // See if a soft reset is being requested. + // + if(pui8Data[ui8Reg - L3GD20H_O_LOW_ODR] & L3GD20H_LOW_ODR_SWRESET_M) + { + // + // Default range setting is +/- 245 degrees/s. + // + psInst->ui8NewGyroFsSel = 0; + } + } + + // + // See if the GYRO_CONFIG register is being written. + // + if((ui8Reg <= L3GD20H_O_CTRL4) && + ((ui8Reg + ui16Count) > L3GD20H_O_CTRL4)) + { + // + // Extract the FS_SEL from the GYRO_CONFIG register value. + // + psInst->ui8NewGyroFsSel = ((pui8Data[ui8Reg - L3GD20H_O_CTRL4] & + L3GD20H_CTRL4_FS_M) >> + L3GD20H_CTRL4_FS_S); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = L3GD20H_STATE_WRITE; + + // + // Write the requested registers to the L3GD20H. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, + L3GD20HCallback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = L3GD20H_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a L3GD20H register. +//! +//! \param psInst is a pointer to the L3GD20H instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the L3GD20H via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! L3GD20H. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +L3GD20HReadModifyWrite(tL3GD20H *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the L3GD20H driver is not idle (in other words, + // there is already an outstanding request to the L3GD20H). + // + if(psInst->ui8State != L3GD20H_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = L3GD20H_STATE_RMW; + + // + // Submit the read-modify-write request to the L3GD20H. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, L3GD20HCallback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = L3GD20H_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the gyroscope data from the L3GD20H. +//! +//! \param psInst is a pointer to the L3GD20H instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the L3GD20H data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - L3GD20HDataGyroGetRaw() +//! - L3GD20HDataGyroGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +L3GD20HDataRead(tL3GD20H *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the L3GD20H driver is not idle (in other words, + // there is already an outstanding request to the L3GD20H). + // + if(psInst->ui8State != L3GD20H_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = L3GD20H_STATE_READ; + + // + // Read the data registers from the L3GD20H. + // + psInst->pui8Data[0] = L3GD20H_O_STATUS | 0x80; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 1, + psInst->pui8Data, 7, L3GD20HCallback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = L3GD20H_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw gyroscope data from the most recent data read. +//! +//! \param psInst is a pointer to the L3GD20H instance data. +//! \param pui16GyroX is a pointer to the value into which the raw X-axis +//! gyroscope data is stored. +//! \param pui16GyroY is a pointer to the value into which the raw Y-axis +//! gyroscope data is stored. +//! \param pui16GyroZ is a pointer to the value into which the raw Z-axis +//! gyroscope data is stored. +//! +//! This function returns the raw gyroscope data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +L3GD20HDataGyroGetRaw(tL3GD20H *psInst, uint_fast16_t *pui16GyroX, + uint_fast16_t *pui16GyroY, uint_fast16_t *pui16GyroZ) +{ + // + // Return the raw gyroscope values. + // + if(pui16GyroX) + { + *pui16GyroX = (psInst->pui8Data[2] << 8) | psInst->pui8Data[1]; + } + if(pui16GyroY) + { + *pui16GyroY = (psInst->pui8Data[4] << 8) | psInst->pui8Data[3]; + } + if(pui16GyroZ) + { + *pui16GyroZ = (psInst->pui8Data[6] << 8) | psInst->pui8Data[5]; + } +} + +//***************************************************************************** +// +//! Gets the gyroscope data from the most recent data read. +//! +//! \param psInst is a pointer to the L3GD20H instance data. +//! \param pfGyroX is a pointer to the value into which the X-axis gyroscope +//! data is stored. +//! \param pfGyroY is a pointer to the value into which the Y-axis gyroscope +//! data is stored. +//! \param pfGyroZ is a pointer to the value into which the Z-axis gyroscope +//! data is stored. +//! +//! This function returns the gyroscope data from the most recent data read, +//! converted into radians per second. If any of the output data pointers are +//! \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +L3GD20HDataGyroGetFloat(tL3GD20H *psInst, float *pfGyroX, float *pfGyroY, + float *pfGyroZ) +{ + float fFactor; + + // + // Get the conversion factor for the current data format. + // + fFactor = g_pfL3GD20HGyroFactors[psInst->ui8GyroFsSel]; + + // + // Convert the gyroscope values into rad/sec. + // + if(pfGyroX) + { + *pfGyroX = ((float)(int16_t)((psInst->pui8Data[2] << 8) | + psInst->pui8Data[1]) * fFactor); + } + if(pfGyroY) + { + *pfGyroY = ((float)(int16_t)((psInst->pui8Data[4] << 8) | + psInst->pui8Data[3]) * fFactor); + } + if(pfGyroZ) + { + *pfGyroZ = ((float)(int16_t)((psInst->pui8Data[6] << 8) | + psInst->pui8Data[5]) * fFactor); + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/l3gd20h.h b/sensorlib/l3gd20h.h new file mode 100644 index 0000000..c56bf36 --- /dev/null +++ b/sensorlib/l3gd20h.h @@ -0,0 +1,158 @@ +//***************************************************************************** +// +// l3gd20h.c - Driver for the ST L3GD20H gyroscope. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_L3GD20H_H__ +#define __SENSORLIB_L3GD20H_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the L3GD20H driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the L3GD20H. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the L3GD20H. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the L3GD20H. + // + uint8_t ui8State; + + // + // The current gyroscope fs_sel setting. + // + uint8_t ui8GyroFsSel; + + // + // The new gyroscope fs_sel setting, which is used when a register write + // succeeds. + // + uint8_t ui8NewGyroFsSel; + + // + // The data buffer used for sending/receiving data to/from the L3GD20H. + // We need 7 bytes (1 status + 3axis * 2bytes per axis) + // + uint8_t pui8Data[8]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tL3GD20H; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t L3GD20HInit(tL3GD20H *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t L3GD20HRead(tL3GD20H *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t L3GD20HWrite(tL3GD20H *psInst, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t L3GD20HReadModifyWrite(tL3GD20H *psInst, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t L3GD20HDataRead(tL3GD20H *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void L3GD20HDataGyroGetRaw(tL3GD20H *psInst, uint_fast16_t *pui16GyroX, + uint_fast16_t *pui16GyroY, + uint_fast16_t *pui16GyroZ); +extern void L3GD20HDataGyroGetFloat(tL3GD20H *psInst, float *pfGyroX, + float *pfGyroY, float *pfGyroZ); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_L3GD20H_H__ diff --git a/sensorlib/lsm303d.c b/sensorlib/lsm303d.c new file mode 100644 index 0000000..e21a5b8 --- /dev/null +++ b/sensorlib/lsm303d.c @@ -0,0 +1,835 @@ +//***************************************************************************** +// +// lsm303d.c - Driver for the ST LSM303D accelerometer/magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_lsm303d.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/lsm303d.h" + +//***************************************************************************** +// +//! \addtogroup lsm303dlhc_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the LSM303D state machine. +// +//***************************************************************************** +#define LSM303D_STATE_IDLE 0 // State machine is idle +#define LSM303D_STATE_INIT 1 // Waiting for init +#define LSM303D_STATE_READ_MAG \ + 2 // Waiting for mag read +#define LSM303D_STATE_READ_ACCEL \ + 3 // Waiting for accel read +#define LSM303D_STATE_WRITE 4 // Waiting for write +#define LSM303D_STATE_RMW 5 // Waiting for read-modify-write + +//***************************************************************************** +// +// The factors used to convert the acceleration readings from the LSM303D +// into floating point values in meters per second squared. +// +// Values are obtained by taking the g conversion factors from the data sheet +// and multiplying by 9.81 (1 g = 9.81 m/s^2). +// +//***************************************************************************** +static const float g_pfLSM303DAccelFactors[] = +{ + 0.00059875, // Range = +/- 2 g (16384 lsb/g) + 0.00119751, // Range = +/- 4 g (8192 lsb/g) + 0.00239502, // Range = +/- 8 g (4096 lsb/g) + 0.00479004 // Range = +/- 16 g (2048 lsb/g) +}; +static const float g_pfLSM303DMagFactors[] = +{ + 8.0e-6f, // Range = +/- 2 (0.080 mgauss/lsb) + 1.6e-5f, // Range = +/- 4 (0.160 mgauss/lsb) + 3.2e-5f, // Range = +/- 8 (0.320 mgauss/lsb) + 4.79e-5f // Range = +/- 12 (0.479 mgauss/lsb) +}; +// +// Uninitialized values will default to zero which is what we want. 0x80 is +// ORed into the register address so the writes auto-increment +// +static const uint8_t g_pui8ZeroInit[] = +{ + 0x80 | LSM303D_O_MAG_INT_CTRL, + 0xE8, // MAG_INT_CTRL + 0x0, // int_src (RO) + 0x0, // THS_LSB + 0x0, // THS_MSB + 0x0, // OFFSET_X_LSB + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, // REF_X + 0x0, + 0x0, + 0x0, // CTRL0 + 0x7, + 0x0, + 0x0, + 0x0, + 0x18, // CTRL5 + 0x20, + 0x1, + 0x0, // status (RO) + 0x0, // out_x_lsb (RO) + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, // FIFO_CTRL + 0x0, // fifo_src (RO) + 0x0, // IG_CFG1 + 0x0, // ig_src1 (RO) + 0x0, + 0x0, + 0x0, + 0x0, // ig_src2 (RO) + 0x0, + 0x0, + 0x0, + 0x0, // clk_src (RO) + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0 +}; + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// LSM303D have completed. +// +//***************************************************************************** +static void +LSM303DCallback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tLSM303D *psInst; + + // + // Convert the instance data into a pointer to a tLSM303D structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = LSM303D_STATE_IDLE; + } + + // + // Determine the current state of the LSM303D state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = LSM303D_STATE_IDLE; + + // + // Done. + // + break; + } + + case LSM303D_STATE_READ_MAG: + { + // + // Move the state machine to the wait for accel data read state. + // + psInst->ui8State = LSM303D_STATE_READ_ACCEL; + + // + // Read the accel data registers from the LSM303D. + // + psInst->pui8DataAccel[0] = LSM303D_O_STATUS | 0x80; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8DataAccel, + 1, psInst->pui8DataAccel, 7, LSM303DCallback, psInst); + + // + // Done. + // + break; + } + case LSM303D_STATE_INIT: + { + psInst->ui8State = LSM303D_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A write just completed + // + case LSM303D_STATE_WRITE: + { + // + // Set the accelerometer ranges to the new values. If the register + // was not modified, the values will be the same so this has no + // effect. + // + psInst->ui8AccelFSSel = psInst->ui8NewAccelFSSel; + psInst->ui8MagFSSel = psInst->ui8NewMagFSSel; + + // + // The state machine is now idle. + // + psInst->ui8State = LSM303D_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read-modify-write just completed + // + case LSM303D_STATE_RMW: + { + // + // See if the accel scale register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + LSM303D_O_CTRL2) + { + // + // Extract the FS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8AccelFSSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + LSM303D_CTRL2_AFS_M) >> LSM303D_CTRL2_AFS_S); + } + + // + // See if the mag scale register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + LSM303D_O_CTRL6) + { + // + // Extract the FS_SEL from the mag scale register value. + // + psInst->ui8MagFSSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + LSM303D_CTRL6_MFS_M) >> LSM303D_CTRL6_MFS_S); + + } + + // + // The state machine is now idle. + // + psInst->ui8State = LSM303D_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == LSM303D_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the LSM303D driver. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the LSM303D device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the LSM303D driver, preparing it for +//! operation. +//! +//! \return Returns 1 if the LSM303D driver was successfully initialized and +//! 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DInit(tLSM303D *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Initialize the LSM303D instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Default range setting is +/- 2 g + // + psInst->ui8AccelFSSel = (LSM303D_CTRL2_AFS_2G >> LSM303D_CTRL2_AFS_S); + psInst->ui8NewAccelFSSel = (LSM303D_CTRL2_AFS_2G >> LSM303D_CTRL2_AFS_S); + psInst->ui8MagFSSel = (LSM303D_CTRL6_MFS_2G >> LSM303D_CTRL6_MFS_S); + psInst->ui8NewMagFSSel = (LSM303D_CTRL6_MFS_2G >> LSM303D_CTRL6_MFS_S); + + // + // There is no soft reset on the LSM303. Force registers back to their + // spec'ed POR defaults. + // + psInst->ui8State = LSM303D_STATE_INIT; + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, g_pui8ZeroInit, + sizeof(g_pui8ZeroInit), LSM303DCallback, (void *)psInst) == 0) + { + psInst->ui8State = LSM303D_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from LSM303D registers. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the LSM303D. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +LSM303DRead(tLSM303D *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the LSM303D driver is not idle (in other words, + // there is already an outstanding request to the LSM303D). + // + if(psInst->ui8State != LSM303D_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = LSM303D_STATE_READ_MAG; + + // + // Read the requested registers from the LSM303D. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + LSM303DCallback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = LSM303D_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to LSM303D registers. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the LSM303D. The first byte of the \e pui8Data buffer contains the +//! value to be written into the \e ui8Reg register, the second value contains +//! the data to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +LSM303DWrite(tLSM303D *psInst, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the LSM303D driver is not idle (in other words, + // there is already an outstanding request to the LSM303D). + // + if(psInst->ui8State != LSM303D_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the accel full scale select register is being written. + // + if((ui8Reg <= LSM303D_O_CTRL2) && + ((ui8Reg + ui16Count) > LSM303D_O_CTRL2)) + { + // + // Extract the AFS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8NewAccelFSSel = + ((pui8Data[ui8Reg - LSM303D_O_CTRL2] & + LSM303D_CTRL2_AFS_M) >> LSM303D_CTRL2_AFS_S); + } + + // + // See if the mag full scale select register is being written. + // + if((ui8Reg <= LSM303D_O_CTRL6) && + ((ui8Reg + ui16Count) > LSM303D_O_CTRL6)) + { + // + // Extract the AFS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8NewMagFSSel = + ((pui8Data[ui8Reg - LSM303D_O_CTRL6] & + LSM303D_CTRL6_MFS_M) >> LSM303D_CTRL6_MFS_S); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = LSM303D_STATE_WRITE; + + // + // Write the requested registers to the LSM303D. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, + LSM303DCallback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = LSM303D_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a LSM303D register. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the LSM303D via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! LSM303D. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DReadModifyWrite(tLSM303D *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the LSM303D driver is not idle (in other words, + // there is already an outstanding request to the LSM303D). + // + if(psInst->ui8State != LSM303D_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = LSM303D_STATE_RMW; + + // + // Submit the read-modify-write request to the LSM303D. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, LSM303DCallback, + psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = LSM303D_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the accelerometer data from the LSM303D. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the LSM303D data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - LSM303DDataAccelGetRaw() +//! - LSM303DDataAccelGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DDataRead(tLSM303D *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the LSM303D driver is not idle (in other words, + // there is already an outstanding request to the LSM303D). + // + if(psInst->ui8State != LSM303D_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for mag data read state. + // + psInst->ui8State = LSM303D_STATE_READ_MAG; + + // + // Read the data registers from the LSM303D. + // + psInst->pui8DataMag[0] = LSM303D_O_MAG_STATUS | 0x80; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8DataMag, 1, + psInst->pui8DataMag, 7, LSM303DCallback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = LSM303D_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param pui16AccelX is a pointer to the value into which the raw X-axis +//! accelerometer data is stored. +//! \param pui16AccelY is a pointer to the value into which the raw Y-axis +//! accelerometer data is stored. +//! \param pui16AccelZ is a pointer to the value into which the raw Z-axis +//! accelerometer data is stored. +//! +//! This function returns the raw accelerometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +LSM303DDataAccelGetRaw(tLSM303D *psInst, + uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, + uint_fast16_t *pui16AccelZ) +{ + // + // Return the raw accelerometer values. + // + if(pui16AccelX) + { + *pui16AccelX = (psInst->pui8DataAccel[2] << 8) | psInst->pui8DataAccel[1]; + } + if(pui16AccelY) + { + *pui16AccelY = (psInst->pui8DataAccel[4] << 8) | psInst->pui8DataAccel[3]; + } + if(pui16AccelZ) + { + *pui16AccelZ = (psInst->pui8DataAccel[6] << 8) | psInst->pui8DataAccel[5]; + } +} + +//***************************************************************************** +// +//! Gets the raw accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param pui16AccelX is a pointer to the value into which the raw X-axis +//! accelerometer data is stored. +//! \param pui16AccelY is a pointer to the value into which the raw Y-axis +//! accelerometer data is stored. +//! \param pui16AccelZ is a pointer to the value into which the raw Z-axis +//! accelerometer data is stored. +//! +//! This function returns the raw accelerometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +LSM303DDataMagnetoGetRaw(tLSM303D *psInst, + uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, + uint_fast16_t *pui16AccelZ) +{ + // + // Return the raw accelerometer values. + // + if(pui16AccelX) + { + *pui16AccelX = (psInst->pui8DataMag[2] << 8) | psInst->pui8DataMag[1]; + } + if(pui16AccelY) + { + *pui16AccelY = (psInst->pui8DataMag[4] << 8) | psInst->pui8DataMag[3]; + } + if(pui16AccelZ) + { + *pui16AccelZ = (psInst->pui8DataMag[6] << 8) | psInst->pui8DataMag[5]; + } +} + +//***************************************************************************** +// +//! Gets the accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param pfAccelX is a pointer to the value into which the X-axis +//! accelerometer data is stored. +//! \param pfAccelY is a pointer to the value into which the Y-axis +//! accelerometer data is stored. +//! \param pfAccelZ is a pointer to the value into which the Z-axis +//! accelerometer data is stored. +//! +//! This function returns the accelerometer data from the most recent data +//! read, converted into meters per second squared (m/s^2). If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +LSM303DDataAccelGetFloat(tLSM303D *psInst, float *pfAccelX, + float *pfAccelY, float *pfAccelZ) +{ + float fFactor; + + // + // Get the acceleration conversion factor for the current data format. + // + fFactor = g_pfLSM303DAccelFactors[psInst->ui8AccelFSSel]; + + // + // Convert the Accelerometer values into floating-point gravity values. + // + if(pfAccelX) + { + *pfAccelX = (float)(((int16_t)((psInst->pui8DataAccel[2] << 8) | + psInst->pui8DataAccel[1])) * fFactor); + } + if(pfAccelY) + { + *pfAccelY = (float)(((int16_t)((psInst->pui8DataAccel[4] << 8) | + psInst->pui8DataAccel[3])) * fFactor); + } + if(pfAccelZ) + { + *pfAccelZ = (float)(((int16_t)((psInst->pui8DataAccel[6] << 8) | + psInst->pui8DataAccel[5])) * fFactor); + } +} + +//***************************************************************************** +// +//! Gets the magnetometer data from the most recent data read. +//! +//! \param psInst is a pointer to the LSM303D instance data. +//! \param pfMagX is a pointer to the value into which the X-axis +//! accelerometer data is stored. +//! \param pfMagY is a pointer to the value into which the Y-axis +//! accelerometer data is stored. +//! \param pfMagZ is a pointer to the value into which the Z-axis +//! accelerometer data is stored. +//! +//! This function returns the magnetometer data from the most recent data +//! read, converted into tesla. If any of the output data pointers are +//! \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +LSM303DDataMagnetoGetFloat(tLSM303D *psInst, float *pfMagX, + float *pfMagY, float *pfMagZ) +{ + float fFactor; + + // + // Get the magnetometer conversion factor for the current data format. + // + fFactor = g_pfLSM303DMagFactors[psInst->ui8MagFSSel]; + + // + // Convert the Accelerometer values into floating-point gravity values. + // + if(pfMagX) + { + *pfMagX = (float)(((int16_t)((psInst->pui8DataMag[2] << 8) | + psInst->pui8DataMag[1])) * fFactor); + } + if(pfMagY) + { + *pfMagY = (float)(((int16_t)((psInst->pui8DataMag[4] << 8) | + psInst->pui8DataMag[3])) * fFactor); + } + if(pfMagZ) + { + *pfMagZ = (float)(((int16_t)((psInst->pui8DataMag[6] << 8) | + psInst->pui8DataMag[5])) * fFactor); + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/lsm303d.h b/sensorlib/lsm303d.h new file mode 100644 index 0000000..a236e0f --- /dev/null +++ b/sensorlib/lsm303d.h @@ -0,0 +1,186 @@ +//***************************************************************************** +// +// lsm303d.h - Driver for the ST LSM303D accelerometer/magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_LSM303D_H__ +#define __SENSORLIB_LSM303D_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the LSM303DLHC driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the LSM303DLHC. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the LSM303DLHC. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the LSM303DLHC. + // + uint8_t ui8State; + + // + // The current accelerometer afs_sel setting. + // + uint8_t ui8AccelFSSel; + + // + // The new accelerometer afs_sel setting, which is used when a register + // write succeeds. + // + uint8_t ui8NewAccelFSSel; + + // + // The current accelerometer afs_sel setting. + // + uint8_t ui8MagFSSel; + + // + // The new accelerometer afs_sel setting, which is used when a register + // write succeeds. + // + uint8_t ui8NewMagFSSel; + + // + // The data buffers used for sending/receiving data to/from the LSM303DLHC. + // + uint8_t pui8DataMag[8]; + + // + // The data buffers used for sending/receiving data to/from the LSM303DLHC. + // + uint8_t pui8DataAccel[8]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tLSM303D; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t LSM303DInit(tLSM303D *psInst, + tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DRead(tLSM303D *psInst, + uint_fast8_t ui8Reg, + uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DWrite(tLSM303D *psInst, + uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DReadModifyWrite(tLSM303D *psInst, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallbak, + void *pvCallbackData); +extern uint_fast8_t LSM303DDataRead(tLSM303D *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void LSM303DDataAccelGetRaw(tLSM303D *psInst, + uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, + uint_fast16_t *pui16AccelZ); +extern void LSM303DDataAccelGetFloat(tLSM303D *psInst, + float *pfAccelX, float *pfAccelY, + float *pfAccelZ); +extern void LSM303DDataMagnetoGetRaw(tLSM303D *psInst, + uint_fast16_t *pui16MagX, + uint_fast16_t *pui16MagY, + uint_fast16_t *pui16MagZ); +extern void LSM303DDataMagnetoGetFloat(tLSM303D *psInst, + float *pfMagX, float *pfMagY, + float *pfMagZ); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_LSM303D_H__ diff --git a/sensorlib/lsm303dlhc_accel.c b/sensorlib/lsm303dlhc_accel.c new file mode 100644 index 0000000..ad46b37 --- /dev/null +++ b/sensorlib/lsm303dlhc_accel.c @@ -0,0 +1,662 @@ +//***************************************************************************** +// +// lsm303dlhc.c - Driver for the ST LSM303DLHC accelerometer +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_lsm303dlhc.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/lsm303dlhc_accel.h" + +//***************************************************************************** +// +//! \addtogroup lsm303dlhc_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the LSM303DLHC state machine. +// +//***************************************************************************** +#define LSM303DLHC_STATE_IDLE 0 // State machine is idle +#define LSM303DLHC_STATE_INIT 1 // Waiting for init +#define LSM303DLHC_STATE_READ 2 // Waiting for read +#define LSM303DLHC_STATE_WRITE 3 // Waiting for write +#define LSM303DLHC_STATE_RMW 4 // Waiting for read-modify-write + +//***************************************************************************** +// +// The factors used to convert the acceleration readings from the LSM303DLHC +// into floating point values in meters per second squared. +// +// Values are obtained by taking the g conversion factors from the data sheet +// and multiplying by 9.81 (1 g = 9.81 m/s^2). +// +//***************************************************************************** +static const float g_pfLSM303DLHCAccelFactors[] = +{ + 0.00059875, // Range = +/- 2 g (16384 lsb/g) + 0.00119751, // Range = +/- 4 g (8192 lsb/g) + 0.00239502, // Range = +/- 8 g (4096 lsb/g) + 0.00479004 // Range = +/- 16 g (2048 lsb/g) +}; + +// +// Uninitialized values will default to zero which is what we want. 0x80 is +// ORed into the register address so the writes auto-increment +// +static const uint8_t g_pui8ZeroCtrl1[8] = +{ + 0x80 | LSM303DLHC_O_CTRL1 +}; +static const uint8_t g_pui8ZeroFifoCtl[14] = +{ + 0x80 | LSM303DLHC_O_FIFO_CTRL +}; + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// LSM303DLHC have completed. +// +//***************************************************************************** +static void +LSM303DLHCCallback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tLSM303DLHCAccel *psInst; + + // + // Convert the instance data into a pointer to a tLSM303DLHC structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = LSM303DLHC_STATE_IDLE; + } + + // + // Determine the current state of the LSM303DLHC state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case LSM303DLHC_STATE_READ: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + + // + // Done. + // + break; + } + + case LSM303DLHC_STATE_INIT: + { + psInst->ui8State = LSM303DLHC_STATE_IDLE; + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, g_pui8ZeroFifoCtl, + 14, LSM303DLHCCallback, pvCallbackData); + + // + // Done. + // + break; + } + + // + // A write just completed + // + case LSM303DLHC_STATE_WRITE: + { + // + // Set the accelerometer ranges to the new values. If the register + // was not modified, the values will be the same so this has no + // effect. + // + psInst->ui8AccelAfsSel = psInst->ui8NewAccelAfsSel; + + // + // The state machine is now idle. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read-modify-write just completed + // + case LSM303DLHC_STATE_RMW: + { + // + // See if the ACCEL_CONFIG register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + LSM303DLHC_O_CTRL4) + { + // + // Extract the FS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8AccelAfsSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + LSM303DLHC_CTRL4_FS_M) >> LSM303DLHC_CTRL4_FS_S); + } + + // + // The state machine is now idle. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == LSM303DLHC_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the LSM303DLHC driver. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the LSM303DLHC device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the LSM303DLHC driver, preparing it for +//! operation. +//! +//! \return Returns 1 if the LSM303DLHC driver was successfully initialized and +//! 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCAccelInit(tLSM303DLHCAccel *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Initialize the LSM303DLHC instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Default range setting is +/- 2 g + // + psInst->ui8AccelAfsSel = (LSM303DLHC_CTRL4_FS_2G >> LSM303DLHC_CTRL4_FS_S); + psInst->ui8NewAccelAfsSel = (LSM303DLHC_CTRL4_FS_2G >> LSM303DLHC_CTRL4_FS_S); + + // + // There is no soft reset on the LSM303. Force registers back to their + // spec'ed POR defaults. + // + psInst->ui8State = LSM303DLHC_STATE_INIT; + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, g_pui8ZeroCtrl1, 7, + LSM303DLHCCallback, (void *)psInst) == 0) + { + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from LSM303DLHC registers. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the LSM303DLHC. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCAccelRead(tLSM303DLHCAccel *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the LSM303DLHC driver is not idle (in other words, + // there is already an outstanding request to the LSM303DLHC). + // + if(psInst->ui8State != LSM303DLHC_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = LSM303DLHC_STATE_READ; + + // + // Read the requested registers from the LSM303DLHC. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + LSM303DLHCCallback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to LSM303DLHC registers. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the LSM303DLHC. The first byte of the \e pui8Data buffer contains the +//! value to be written into the \e ui8Reg register, the second value contains +//! the data to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCAccelWrite(tLSM303DLHCAccel *psInst, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the LSM303DLHC driver is not idle (in other words, + // there is already an outstanding request to the LSM303DLHC). + // + if(psInst->ui8State != LSM303DLHC_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if they're rebooting via CTRL5 + // + if((ui8Reg <= LSM303DLHC_O_CTRL5) && + ((ui8Reg + ui16Count) > LSM303DLHC_O_CTRL5)) + { + // + // See if a soft reset is being requested. + // + if(pui8Data[ui8Reg - LSM303DLHC_O_CTRL5] & LSM303DLHC_CTRL5_REBOOTCTL_M) + { + // + // Default range setting is +/- 2 g. + // + psInst->ui8NewAccelAfsSel = 0; + } + } + + // + // See if the ACCEL_CONFIG register is being written. + // + if((ui8Reg <= LSM303DLHC_O_CTRL4) && + ((ui8Reg + ui16Count) > LSM303DLHC_O_CTRL4)) + { + // + // Extract the AFS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8NewAccelAfsSel = + ((pui8Data[ui8Reg - LSM303DLHC_O_CTRL4] & + LSM303DLHC_CTRL4_FS_M) >> LSM303DLHC_CTRL4_FS_S); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = LSM303DLHC_STATE_WRITE; + + // + // Write the requested registers to the LSM303DLHC. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, + LSM303DLHCCallback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a LSM303DLHC register. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the LSM303DLHC via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! LSM303DLHC. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCAccelReadModifyWrite(tLSM303DLHCAccel *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the LSM303DLHC driver is not idle (in other words, + // there is already an outstanding request to the LSM303DLHC). + // + if(psInst->ui8State != LSM303DLHC_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = LSM303DLHC_STATE_RMW; + + // + // Submit the read-modify-write request to the LSM303DLHC. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, LSM303DLHCCallback, + psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the accelerometer data from the LSM303DLHC. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the LSM303DLHC data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - LSM303DLHCDataAccelGetRaw() +//! - LSM303DLHCDataAccelGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCAccelDataRead(tLSM303DLHCAccel *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the LSM303DLHC driver is not idle (in other words, + // there is already an outstanding request to the LSM303DLHC). + // + if(psInst->ui8State != LSM303DLHC_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = LSM303DLHC_STATE_READ; + + // + // Read the data registers from the LSM303DLHC. + // + psInst->pui8Data[0] = LSM303DLHC_O_OUT_X_LSB | 0x80; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 1, + psInst->pui8Data, 6, LSM303DLHCCallback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param pui16AccelX is a pointer to the value into which the raw X-axis +//! accelerometer data is stored. +//! \param pui16AccelY is a pointer to the value into which the raw Y-axis +//! accelerometer data is stored. +//! \param pui16AccelZ is a pointer to the value into which the raw Z-axis +//! accelerometer data is stored. +//! +//! This function returns the raw accelerometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +LSM303DLHCAccelDataAccelGetRaw(tLSM303DLHCAccel *psInst, + uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, + uint_fast16_t *pui16AccelZ) +{ + // + // Return the raw accelerometer values. + // + if(pui16AccelX) + { + *pui16AccelX = (psInst->pui8Data[1] << 8) | psInst->pui8Data[0]; + } + if(pui16AccelY) + { + *pui16AccelY = (psInst->pui8Data[3] << 8) | psInst->pui8Data[2]; + } + if(pui16AccelZ) + { + *pui16AccelZ = (psInst->pui8Data[5] << 8) | psInst->pui8Data[4]; + } +} + +//***************************************************************************** +// +//! Gets the accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param pfAccelX is a pointer to the value into which the X-axis +//! accelerometer data is stored. +//! \param pfAccelY is a pointer to the value into which the Y-axis +//! accelerometer data is stored. +//! \param pfAccelZ is a pointer to the value into which the Z-axis +//! accelerometer data is stored. +//! +//! This function returns the accelerometer data from the most recent data +//! read, converted into meters per second squared (m/s^2). If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +LSM303DLHCAccelDataAccelGetFloat(tLSM303DLHCAccel *psInst, float *pfAccelX, + float *pfAccelY, float *pfAccelZ) +{ + float fFactor; + + // + // Get the acceleration conversion factor for the current data format. + // + fFactor = g_pfLSM303DLHCAccelFactors[psInst->ui8AccelAfsSel]; + + // + // Convert the Accelerometer values into floating-point gravity values. + // + if(pfAccelX) + { + *pfAccelX = (float)(((int16_t)((psInst->pui8Data[1] << 8) | + psInst->pui8Data[0])) * fFactor); + } + if(pfAccelY) + { + *pfAccelY = (float)(((int16_t)((psInst->pui8Data[3] << 8) | + psInst->pui8Data[2])) * fFactor); + } + if(pfAccelZ) + { + *pfAccelZ = (float)(((int16_t)((psInst->pui8Data[5] << 8) | + psInst->pui8Data[4])) * fFactor); + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/lsm303dlhc_accel.h b/sensorlib/lsm303dlhc_accel.h new file mode 100644 index 0000000..00d72f7 --- /dev/null +++ b/sensorlib/lsm303dlhc_accel.h @@ -0,0 +1,163 @@ +//***************************************************************************** +// +// lsm303dlhc.c - Driver for the ST L3GD20H gyrometer +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_LSM303DLHC_ACCEL_H__ +#define __SENSORLIB_LSM303DLHC_ACCEL_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the LSM303DLHC driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the LSM303DLHC. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the LSM303DLHC. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the LSM303DLHC. + // + uint8_t ui8State; + + // + // The current accelerometer afs_sel setting. + // + uint8_t ui8AccelAfsSel; + + // + // The new accelerometer afs_sel setting, which is used when a register + // write succeeds. + // + uint8_t ui8NewAccelAfsSel; + + // + // The data buffers used for sending/receiving data to/from the LSM303DLHC. + // + uint8_t pui8Data[8]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tLSM303DLHCAccel; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t LSM303DLHCAccelInit(tLSM303DLHCAccel *psInst, + tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DLHCAccelRead(tLSM303DLHCAccel *psInst, + uint_fast8_t ui8Reg, + uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DLHCAccelWrite(tLSM303DLHCAccel *psInst, + uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DLHCAccelReadModifyWrite(tLSM303DLHCAccel *psInst, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallbak, + void *pvCallbackData); +extern uint_fast8_t LSM303DLHCAccelDataRead(tLSM303DLHCAccel *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void LSM303DLHCAccelDataAccelGetRaw(tLSM303DLHCAccel *psInst, + uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, + uint_fast16_t *pui16AccelZ); +extern void LSM303DLHCAccelDataAccelGetFloat(tLSM303DLHCAccel *psInst, + float *pfAccelX, float *pfAccelY, + float *pfAccelZ); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_LSM303DLHC_ACCEL_H__ diff --git a/sensorlib/lsm303dlhc_mag.c b/sensorlib/lsm303dlhc_mag.c new file mode 100644 index 0000000..d8abaa8 --- /dev/null +++ b/sensorlib/lsm303dlhc_mag.c @@ -0,0 +1,615 @@ +//***************************************************************************** +// +// lsm303dlhc.c - Driver for the ST LSM303DLHC magnetometer +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_lsm303dlhc.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/lsm303dlhc_mag.h" + +//***************************************************************************** +// +//! \addtogroup lsm303dlhc_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the LSM303DLHC state machine. +// +//***************************************************************************** +#define LSM303DLHC_STATE_IDLE 0 // State machine is idle +#define LSM303DLHC_STATE_READ 1 // Waiting for read +#define LSM303DLHC_STATE_WRITE 2 // Waiting for write +#define LSM303DLHC_STATE_RMW 3 // Waiting for read-modify-write + +//***************************************************************************** +// +// The factors used to convert the magnetometer readings from the LSM303 into +// floating point values in tesla +// +//***************************************************************************** +static const float g_pfLSM303DLHCMagnetoFactors[] = +{ + 0, + 9.09E-08f, + 1.17E-07f, + 1.49E-07f, + 2.22E-07f, + 2.50E-07f, + 3.03E-07f, + 4.35E-07f, +}; + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// LSM303DLHC have completed. +// +//***************************************************************************** +static void +LSM303DLHCCallback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tLSM303DLHCMag *psInst; + + // + // Convert the instance data into a pointer to a tLSM303DLHC structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = LSM303DLHC_STATE_IDLE; + } + + // + // Determine the current state of the LSM303DLHC state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case LSM303DLHC_STATE_READ: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A write just completed + // + case LSM303DLHC_STATE_WRITE: + { + // + // Set the magneto ranges to the new values. If the register was + // not modified, the values will be the same so this has no effect. + // + psInst->ui8MagnetoFsSel = psInst->ui8NewMagnetoFsSel; + + // + // The state machine is now idle. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read-modify-write just completed + // + case LSM303DLHC_STATE_RMW: + { + // + // See if the MAGNETO_CONFIG register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + LSM303DLHC_O_MAG_CRB) + { + // + // Extract the FS_SEL from the MAGNETO_CONFIG register value. + // + psInst->ui8MagnetoFsSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + LSM303DLHC_MAG_CRB_GAIN_M) >> LSM303DLHC_MAG_CRB_GAIN_S); + } + + // + // The state machine is now idle. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == LSM303DLHC_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the LSM303DLHC driver. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the LSM303DLHC device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the LSM303DLHC driver, preparing it for +//! operation. +//! +//! \return Returns 1 if the LSM303DLHC driver was successfully initialized and +//! 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCMagInit(tLSM303DLHCMag *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Initialize the LSM303DLHC instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Default range setting is +/- 1.3 + // TODO: double-check default + // + psInst->ui8MagnetoFsSel = (LSM303DLHC_MAG_CRB_GAIN_1_3GAUSS >> + LSM303DLHC_MAG_CRB_GAIN_S); + psInst->ui8NewMagnetoFsSel = (LSM303DLHC_MAG_CRB_GAIN_1_3GAUSS >> + LSM303DLHC_MAG_CRB_GAIN_S); + psInst->ui8State = LSM303DLHC_STATE_IDLE; + + if(pfnCallback) + { + pfnCallback(pvCallbackData, I2CM_STATUS_SUCCESS); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from LSM303DLHC registers. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the LSM303DLHC. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCMagRead(tLSM303DLHCMag *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the LSM303DLHC driver is not idle (in other words, + // there is already an outstanding request to the LSM303DLHC). + // + if(psInst->ui8State != LSM303DLHC_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = LSM303DLHC_STATE_READ; + + // + // Read the requested registers from the LSM303DLHC. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + LSM303DLHCCallback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to LSM303DLHC registers. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the LSM303DLHC. The first byte of the \e pui8Data buffer contains the +//! value to be written into the \e ui8Reg register, the second value contains +//! the data to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCMagWrite(tLSM303DLHCMag *psInst, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the LSM303DLHC driver is not idle (in other words, + // there is already an outstanding request to the LSM303DLHC). + // + if(psInst->ui8State != LSM303DLHC_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the MAGNETO_CONFIG register is being written. + // + if((ui8Reg <= LSM303DLHC_O_MAG_CRB) && + ((ui8Reg + ui16Count) > LSM303DLHC_O_MAG_CRB)) + { + // + // Extract the FS_SEL from the MAGNETO_CONFIG register value. + // + psInst->ui8NewMagnetoFsSel = ((pui8Data[ui8Reg - LSM303DLHC_O_MAG_CRB] & + LSM303DLHC_MAG_CRB_GAIN_M) >> + LSM303DLHC_MAG_CRB_GAIN_S); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = LSM303DLHC_STATE_WRITE; + + // + // Write the requested registers to the LSM303DLHC. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, + LSM303DLHCCallback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a LSM303DLHC register. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the LSM303DLHC via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! LSM303DLHC. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCMagReadModifyWrite(tLSM303DLHCMag *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the LSM303DLHC driver is not idle (in other words, + // there is already an outstanding request to the LSM303DLHC). + // + if(psInst->ui8State != LSM303DLHC_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = LSM303DLHC_STATE_RMW; + + // + // Submit the read-modify-write request to the LSM303DLHC. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, LSM303DLHCCallback, + psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the magneto data from the LSM303DLHC. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the LSM303DLHC data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - LSM303DLHCDataMagnetoGetRaw() +//! - LSM303DLHCDataMagnetoGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +LSM303DLHCMagDataRead(tLSM303DLHCMag *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the LSM303DLHC driver is not idle (in other words, + // there is already an outstanding request to the LSM303DLHC). + // + if(psInst->ui8State != LSM303DLHC_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = LSM303DLHC_STATE_READ; + + // + // Read the data registers from the LSM303DLHC. + // + psInst->pui8Data[0] = LSM303DLHC_O_MAG_OUT_X_MSB; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 1, + psInst->pui8Data, 7, LSM303DLHCCallback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = LSM303DLHC_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw magneto data from the most recent data read. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param pui16MagnetoX is a pointer to the value into which the raw X-axis +//! magnetometer data is stored. +//! \param pui16MagnetoY is a pointer to the value into which the raw Y-axis +//! magnetometer data is stored. +//! \param pui16MagnetoZ is a pointer to the value into which the raw Z-axis +//! magnetometer data is stored. +//! +//! This function returns the raw magnetometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +LSM303DLHCMagDataMagnetoGetRaw(tLSM303DLHCMag *psInst, + uint_fast16_t *pui16MagnetoX, + uint_fast16_t *pui16MagnetoY, + uint_fast16_t *pui16MagnetoZ) +{ + // + // Return the raw magnetometer values. + // + if(pui16MagnetoX) + { + *pui16MagnetoX = (psInst->pui8Data[0] << 8) | psInst->pui8Data[1]; + } + if(pui16MagnetoY) + { + *pui16MagnetoY = (psInst->pui8Data[2] << 8) | psInst->pui8Data[3]; + } + if(pui16MagnetoZ) + { + *pui16MagnetoZ = (psInst->pui8Data[4] << 8) | psInst->pui8Data[5]; + } +} + +//***************************************************************************** +// +//! Gets the magnetometer data from the most recent data read. +//! +//! \param psInst is a pointer to the LSM303DLHC instance data. +//! \param pfMagnetoX is a pointer to the value into which the X-axis +//! magnetometer data is stored. +//! \param pfMagnetoY is a pointer to the value into which the Y-axis +//! magnetometer data is stored. +//! \param pfMagnetoZ is a pointer to the value into which the Z-axis +//! magnetometer data is stored. +//! +//! This function returns the magnetometer data from the most recent data read, +//! converted into radians per second. If any of the output data pointers are +//! \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +LSM303DLHCMagDataMagnetoGetFloat(tLSM303DLHCMag *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ) +{ + float fFactor; + + // + // Get the conversion factor for the current data format. + // + fFactor = g_pfLSM303DLHCMagnetoFactors[psInst->ui8MagnetoFsSel]; + + // + // Convert the magnetometer values into rad/sec + // + if(pfMagnetoX) + { + *pfMagnetoX = (float)(((int16_t)((psInst->pui8Data[0] << 8) | + psInst->pui8Data[1])) * fFactor); + } + if(pfMagnetoY) + { + *pfMagnetoY = (float)(((int16_t)((psInst->pui8Data[2] << 8) | + psInst->pui8Data[3])) * fFactor); + } + if(pfMagnetoZ) + { + *pfMagnetoZ = (float)(((int16_t)((psInst->pui8Data[4] << 8) | + psInst->pui8Data[5])) * fFactor); + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/lsm303dlhc_mag.h b/sensorlib/lsm303dlhc_mag.h new file mode 100644 index 0000000..a7426c3 --- /dev/null +++ b/sensorlib/lsm303dlhc_mag.h @@ -0,0 +1,164 @@ +//***************************************************************************** +// +// lsm303dlhc.c - Driver for the ST L3GD20H gyrometer +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_LSM303DLHC_MAG_H__ +#define __SENSORLIB_LSM303DLHC_MAG_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the LSM303DLHC driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the LSM303DLHC. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the LSM303DLHC. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the LSM303DLHC. + // + uint8_t ui8State; + + // + // The current gyroscope fs_sel setting. + // + uint8_t ui8MagnetoFsSel; + + // + // The new gyroscope fs_sel setting, which is used when a register write + // succeeds. + // + uint8_t ui8NewMagnetoFsSel; + + // + // The data buffers used for sending/receiving data to/from the LSM303DLHC. + // + uint8_t pui8Data[8]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tLSM303DLHCMag; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t LSM303DLHCMagInit(tLSM303DLHCMag *psInst, + tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DLHCMagRead(tLSM303DLHCMag *psInst, + uint_fast8_t ui8Reg, + uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DLHCMagWrite(tLSM303DLHCMag *psInst, + uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DLHCMagReadModifyWrite(tLSM303DLHCMag *psInst, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t LSM303DLHCMagDataRead(tLSM303DLHCMag *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void LSM303DLHCMagDataMagnetoGetRaw(tLSM303DLHCMag *psInst, + uint_fast16_t *pui16MagnetoX, + uint_fast16_t *pui16MagnetoY, + uint_fast16_t *pui16MagnetoZ); +extern void LSM303DLHCMagDataMagnetoGetFloat(tLSM303DLHCMag *psInst, + float *pfMagnetoX, + float *pfMagnetoY, + float *pfMagnetoZ); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_LSM303DLHC_MAG_H__ diff --git a/sensorlib/magneto.c b/sensorlib/magneto.c new file mode 100644 index 0000000..b7f7595 --- /dev/null +++ b/sensorlib/magneto.c @@ -0,0 +1,248 @@ +//***************************************************************************** +// +// magneto.c - Functions for manipulating magnetometer readings. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/magneto.h" + +//***************************************************************************** +// +//! \addtogroup magneto_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +//! Initializes the magnetometer hard- and soft-iron compensation state. +//! +//! \param psInst is a pointer to the magnetometer compensation state +//! structure. +//! \param fXOffset is the hard-iron compensation for the X axis. +//! \param fYOffset is the hard-iron compensation for the Y axis. +//! \param fZOffset is the hard-iron compensation for the Z axis. +//! \param fXYAngle is the amount to rotate around the Z axis prior to scaling +//! the Y axis reading, in radians. +//! \param fYRatio is the amount to scale the Y axis reading. +//! \param fXZAngle is the amount to rotate around the Y axis prior to scaling +//! the Z axis reading, in radians. +//! \param fZRatio is the amount to scale the Z axis reading. +//! +//! This function initializes the magnetometer compensation state structure +//! with the values that are used to perform hard- and soft-iron compensation +//! of magnetometer readings. +//! +//! \return None. +// +//***************************************************************************** +void +MagnetoCompensateInit(tMagnetoCompensation *psInst, float fXOffset, + float fYOffset, float fZOffset, float fXYAngle, + float fYRatio, float fXZAngle, float fZRatio) +{ + // + // Save the hard- and soft-iron compensation values. + // + psInst->fXOffset = fXOffset; + psInst->fYOffset = fYOffset; + psInst->fZOffset = fZOffset; + psInst->fXYAngle = fXYAngle; + psInst->fYRatio = fYRatio; + psInst->fXZAngle = fXZAngle; + psInst->fZRatio = fZRatio; +} + +//***************************************************************************** +// +//! Performs hard- and soft-iron compensation on magnetometer readings. +//! +//! \param psInst is a pointer to the magnetometer compensation state +//! structure. +//! \param pfMagnetoX is a pointer to the magnetometer X-axis reading. +//! \param pfMagnetoY is a pointer to the magnetometer Y-axis reading. +//! \param pfMagnetoZ is a pointer to the magnetometer Z-axis reading. +//! +//! This function performs hard- and soft-iron compensation on the given +//! magnetometer reading. Hard-iron distortions cause a fixed offset in the +//! reading, regardless of orientation. Hard-iron compensation is performed by +//! negating this fixed offset. +//! +//! Soft-iron distortion is more complicated, causing an offset that varies as +//! the sensor rotates, which results in the sensor returning an ellipse as it +//! rotates instead of a circle. Performing soft-iron compensation requires +//! rotating the sensor reading such that the major axis of the ellipse is +//! aligned with one of the magnetometer axes, scaling one of the axes, then +//! rotating the scaled sensor reading back. This operation is performed two +//! times; once to scale the Y axis to the same scale as the X axis, and once +//! again to scale the Z axis to the same scale as the X axis. +//! +//! Hard-iron compensation is performed prior to soft-iron compensation. +//! +//! \return None. +// +//***************************************************************************** +void +MagnetoCompensate(tMagnetoCompensation *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ) +{ + float fSin, fCos, fX, fY, fZ, fTemp; + + // + // Get the magnetometer values. + // + fX = *pfMagnetoX; + fY = *pfMagnetoY; + fZ = *pfMagnetoZ; + + // + // Perform hard-iron distortion compensation. + // + fX += psInst->fXOffset; + fY += psInst->fYOffset; + fZ += psInst->fZOffset; + + // + // Perform soft-iron distortion compensation on the X-Y plane. Start by + // computing the sine and cosine of the rotation angle (which will be used + // multiple times below). + // + fSin = sinf(psInst->fXYAngle); + fCos = cosf(psInst->fXYAngle); + + // + // Rotate the magnetometer reading around the Z axis. + // + fTemp = (fCos * fX) - (fSin * fY); + fY = (fCos * fY) + (fSin * fX); + fX = fTemp; + + // + // Scale the Y-axis reading so that it has the same range as the X-axis + // reading. + // + fY *= psInst->fYRatio; + + // + // Rotate the magnetometer reading around the Z axis again, this time in + // the opposite direction. + // + fTemp = (fCos * fX) + (fSin * fY); + fY = (fCos * fY) - (fSin * fX); + fX = fTemp; + + // + // Perform soft-iron distortion compensation on the X-Z plane. Start by + // computing the sine and cosine of the rotation angle (which will be used + // multiple times below). + // + fSin = sinf(psInst->fXZAngle); + fCos = cosf(psInst->fXZAngle); + + // + // Rotate the magnetometer reading around the Y axis. + // + fTemp = (fCos * fZ) - (fSin * fX); + fX = (fCos * fX) + (fSin * fZ); + fZ = fTemp; + + // + // Scale the Z-axis reading so that it has the same range as the X-axis + // reading. + // + fZ *= psInst->fZRatio; + + // + // Rotate the magnetometer reading around the Y axis again, this time in + // the opposite direction. + // + fTemp = (fCos * fZ) + (fSin * fX); + fX = (fCos * fX) - (fSin * fZ); + fZ = fTemp; + + // + // Return the compensated magnetometer values. + // + *pfMagnetoX = fX; + *pfMagnetoY = fY; + *pfMagnetoZ = fZ; +} + +//***************************************************************************** +// +//! Computes the compass heading from magnetometer data and roll/pitch. +//! +//! \param fMagnetoX is the X component of the magnetometer reading. +//! \param fMagnetoY is the Y component of the magnetometer reading. +//! \param fMagnetoZ is the Z component of the magnetometer reading. +//! \param fRoll is the roll angle, in radians. +//! \param fPitch is the pitch angle, in radians. +//! +//! This function computes the compass heading by performing tilt compensation +//! on the magnetometer reading. +//! +//! \return Returns the compass heading, in radians. +// +//***************************************************************************** +float +MagnetoHeadingCompute(float fMagnetoX, float fMagnetoY, float fMagnetoZ, + float fRoll, float fPitch) +{ + float fSinRoll, fCosRoll, fSinPitch, fCosPitch, fX, fY, fHeading; + + // + // Compute the sine and cosine of the roll and pitch angles. + // + fSinRoll = sinf(fRoll); + fCosRoll = cosf(fRoll); + fSinPitch = sinf(fPitch); + fCosPitch = cosf(fPitch); + + // + // Rotate the magnetometer data such that it is level with the ground, + // based on the provided roll and pitch. + // + fX = ((fMagnetoX * fCosPitch) + (fMagnetoY * fSinRoll * fSinPitch) + + (fMagnetoZ * fCosRoll * fSinPitch)); + fY = (fMagnetoY * fCosRoll) - (fMagnetoZ * fSinRoll); + + // + // Compute the compass heading and make it positive. + // + fHeading = atan2f(-fY, fX); + if(fHeading < 0) + { + fHeading += 2 * 3.141592; + } + + // + // Return the computed compass heading. + // + return(fHeading); +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/magneto.h b/sensorlib/magneto.h new file mode 100644 index 0000000..811491e --- /dev/null +++ b/sensorlib/magneto.h @@ -0,0 +1,92 @@ +//***************************************************************************** +// +// magneto.h - Prototypes for the functions that manipulate magnetometer +// readings. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_MAGNETO_H__ +#define __SENSORLIB_MAGNETO_H__ + +//***************************************************************************** +// +// The structure that defines the internal state of the magnetometer hard and +// soft iron compensation. +// +//***************************************************************************** +typedef struct +{ + // + // The hard iron induced offset in the X axis of the magnetometer. + // + float fXOffset; + + // + // The hard iron induced offset in the Y axis of the magnetometer. + // + float fYOffset; + + // + // The hard iron induced offset in the Z axis of the magnetometer. + // + float fZOffset; + + // + // The Z axis rotation required to align the major/minor axes of the + // ellipse in the X-Y plane with the X-Y axes, specified in radians. + // + float fXYAngle; + + // + // The amount to scale the Y axis in order to turn the X-Y ellipse into a + // circle. + // + float fYRatio; + + // + // The Y axis rotation required to align the major/minor axes of the + // ellipse in the X-Z plane with X-Z axes, specified in radians. + // + float fXZAngle; + + // + // The amount to scale the Z axis in order to turn the X-Z ellipse into a + // circle. + // + float fZRatio; +} +tMagnetoCompensation; + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern void MagnetoCompensateInit(tMagnetoCompensation *psInst, float fXOffset, + float fYOffset, float fZOffset, + float fXYAngle, float fYRatio, + float fXZAngle, float fZRatio); +extern void MagnetoCompensate(tMagnetoCompensation *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ); +extern float MagnetoHeadingCompute(float fMagnetoX, float fMagnetoY, + float fMagnetoZ, float fRoll, float fPitch); + +#endif // __SENSORLIB_MAGNETO_H__ diff --git a/sensorlib/mpu6050.c b/sensorlib/mpu6050.c new file mode 100644 index 0000000..f095e40 --- /dev/null +++ b/sensorlib/mpu6050.c @@ -0,0 +1,879 @@ +//***************************************************************************** +// +// mpu6050.c - Driver for the MPU6050 accelerometer and gyroscope. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_mpu6050.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/mpu6050.h" + +//***************************************************************************** +// +//! \addtogroup mpu6050_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the MPU6050 state machine. +// +//***************************************************************************** +#define MPU6050_STATE_IDLE 0 // State machine is idle +#define MPU6050_STATE_INIT_RES 1 // Waiting for initialization +#define MPU6050_STATE_INIT_WAIT 2 // Waiting for reset to complete +#define MPU6050_STATE_READ 3 // Waiting for read +#define MPU6050_STATE_WRITE 4 // Waiting for write +#define MPU6050_STATE_RMW 5 // Waiting for read-modify-write + +//***************************************************************************** +// +// The factors used to convert the acceleration readings from the MPU6050 into +// floating point values in meters per second squared. +// +// Values are obtained by taking the g conversion factors from the data sheet +// and multiplying by 9.81 (1 g = 9.81 m/s^2). +// +//***************************************************************************** +static const float g_fMPU6050AccelFactors[] = +{ + 0.00059875, // Range = +/- 2 g (16384 lsb/g) + 0.00119751, // Range = +/- 4 g (8192 lsb/g) + 0.00239502, // Range = +/- 8 g (4096 lsb/g) + 0.00479004 // Range = +/- 16 g (2048 lsb/g) +}; + +//***************************************************************************** +// +// The factors used to convert the acceleration readings from the MPU6050 into +// floating point values in radians per second. +// +// Values are obtained by taking the degree per second conversion factors +// from the data sheet and then converting to radians per sec (1 degree = +// 0.0174532925 radians). +// +//***************************************************************************** +static const float g_fMPU6050GyroFactors[] = +{ + 1.3323124e-4f, // Range = +/- 250 dps (131.0 LSBs/DPS) + 2.6646248e-4f, // Range = +/- 500 dps (65.5 LSBs/DPS) + 5.3211258e-4f, // Range = +/- 1000 dps (32.8 LSBs/DPS) + 0.0010642252f // Range = +/- 2000 dps (16.4 LSBs/DPS) +}; +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// MPU6050 have completed. +// +//***************************************************************************** +static void +MPU6050Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tMPU6050 *psInst; + + // + // Convert the instance data into a pointer to a tMPU6050 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). Except in the case that we are in the reset wait state and the + // error is an address NACK. This error is handled by the reset wait + // state. + // + if((ui8Status != I2CM_STATUS_SUCCESS) && + !((ui8Status == I2CM_STATUS_ADDR_NACK) && + (psInst->ui8State == MPU6050_STATE_INIT_WAIT))) + { + psInst->ui8State = MPU6050_STATE_IDLE; + } + + // + // Determine the current state of the MPU6050 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case MPU6050_STATE_READ: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = MPU6050_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // MPU6050 Device reset was issued + // + case MPU6050_STATE_INIT_RES: + { + // + // Issue a read of the status register to confirm reset is done. + // + psInst->uCommand.pui8Buffer[0] = MPU6050_O_PWR_MGMT_1; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, + MPU6050Callback, psInst); + + psInst->ui8State = MPU6050_STATE_INIT_WAIT; + break; + } + + // + // Status register was read, check if reset is done before proceeding. + // + case MPU6050_STATE_INIT_WAIT: + { + // + // Check the value read back from status to determine if device + // is still in reset or if it is ready. Reset state for this + // register is 0x40, which has sleep bit set. Device may also + // respond with an address NACK during very early stages of the its + // internal reset. Keep polling until we verify device is ready. + // + // + if((psInst->pui8Data[0] != MPU6050_PWR_MGMT_1_SLEEP) || + (ui8Status == I2CM_STATUS_ADDR_NACK)) + { + // + // Device still in reset so begin polling this register. + // + psInst->uCommand.pui8Buffer[0] = MPU6050_O_PWR_MGMT_1; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, + MPU6050Callback, psInst); + + // + // Intentionally stay in this state to create polling effect. + // + } + else + { + // + // Device is out of reset, move to the idle state. + // + psInst->ui8State = MPU6050_STATE_IDLE; + } + break; + } + + // + // A write just completed + // + case MPU6050_STATE_WRITE: + { + // + // Set the accelerometer and gyroscope ranges to the new values. + // If the register was not modified, the values will be the same so + // this has no effect. + // + psInst->ui8AccelAfsSel = psInst->ui8NewAccelAfsSel; + psInst->ui8GyroFsSel = psInst->ui8NewGyroFsSel; + + // + // The state machine is now idle. + // + psInst->ui8State = MPU6050_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read-modify-write just completed + // + case MPU6050_STATE_RMW: + { + // + // See if the PWR_MGMT_1 register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + MPU6050_O_PWR_MGMT_1) + { + // + // See if a soft reset has been issued. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + MPU6050_PWR_MGMT_1_DEVICE_RESET) + { + // + // Default range setting is +/- 2 g + // + psInst->ui8AccelAfsSel = 0; + psInst->ui8NewAccelAfsSel = 0; + + // + // Default range setting is +/- 250 degrees/s + // + psInst->ui8GyroFsSel = 0; + psInst->ui8NewGyroFsSel = 0; + } + } + + // + // See if the GYRO_CONFIG register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + MPU6050_O_GYRO_CONFIG) + { + // + // Extract the FS_SEL from the GYRO_CONFIG register value. + // + psInst->ui8GyroFsSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + MPU6050_GYRO_CONFIG_FS_SEL_M) >> + MPU6050_GYRO_CONFIG_FS_SEL_S); + } + + // + // See if the ACCEL_CONFIG register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + MPU6050_O_ACCEL_CONFIG) + { + // + // Extract the FS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8AccelAfsSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + MPU6050_ACCEL_CONFIG_AFS_SEL_M) >> + MPU6050_ACCEL_CONFIG_AFS_SEL_S); + } + + // + // The state machine is now idle. + // + psInst->ui8State = MPU6050_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == MPU6050_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the MPU6050 driver. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the MPU6050 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the MPU6050 driver, preparing it for operation. +//! +//! \return Returns 1 if the MPU6050 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +MPU6050Init(tMPU6050 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Initialize the MPU6050 instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Default range setting is +/- 2 g + // + psInst->ui8AccelAfsSel = (MPU6050_ACCEL_CONFIG_AFS_SEL_2G >> + MPU6050_ACCEL_CONFIG_AFS_SEL_S); + psInst->ui8NewAccelAfsSel = (MPU6050_ACCEL_CONFIG_AFS_SEL_2G >> + MPU6050_ACCEL_CONFIG_AFS_SEL_S); + + // + // Default range setting is +/- 250 degrees/s + // + psInst->ui8GyroFsSel = (MPU6050_GYRO_CONFIG_FS_SEL_250 >> + MPU6050_GYRO_CONFIG_FS_SEL_S); + psInst->ui8NewGyroFsSel = (MPU6050_GYRO_CONFIG_FS_SEL_250 >> + MPU6050_GYRO_CONFIG_FS_SEL_S); + + // + // Set the state to show we are initiating a reset. + // + psInst->ui8State = MPU6050_STATE_INIT_RES; + + // + // Load the buffer with command to perform device reset + // + psInst->uCommand.pui8Buffer[0] = MPU6050_O_PWR_MGMT_1; + psInst->uCommand.pui8Buffer[1] = MPU6050_PWR_MGMT_1_DEVICE_RESET; + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, MPU6050Callback, psInst) == 0) + { + psInst->ui8State = MPU6050_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from MPU6050 registers. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the MPU6050. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +MPU6050Read(tMPU6050 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the MPU6050 driver is not idle (in other words, + // there is already an outstanding request to the MPU6050). + // + if(psInst->ui8State != MPU6050_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = MPU6050_STATE_READ; + + // + // Read the requested registers from the MPU6050. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + MPU6050Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = MPU6050_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to MPU6050 registers. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the MPU6050. The first byte of the \e pui8Data buffer contains the value +//! to be written into the \e ui8Reg register, the second value contains the +//! data to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +MPU6050Write(tMPU6050 *psInst, uint_fast8_t ui8Reg, const uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the MPU6050 driver is not idle (in other words, + // there is already an outstanding request to the MPU6050). + // + if(psInst->ui8State != MPU6050_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the PWR_MGMT_1 register is being written. + // + if((ui8Reg <= MPU6050_O_PWR_MGMT_1) && + ((ui8Reg + ui16Count) > MPU6050_O_PWR_MGMT_1)) + { + // + // See if a soft reset is being requested. + // + if(pui8Data[ui8Reg - MPU6050_O_PWR_MGMT_1] & + MPU6050_PWR_MGMT_1_DEVICE_RESET) + { + // + // Default range setting is +/- 2 g. + // + psInst->ui8NewAccelAfsSel = 0; + + // + // Default range setting is +/- 250 degrees/s. + // + psInst->ui8NewGyroFsSel = 0; + } + } + + // + // See if the GYRO_CONFIG register is being written. + // + if((ui8Reg <= MPU6050_O_GYRO_CONFIG) && + ((ui8Reg + ui16Count) > MPU6050_O_GYRO_CONFIG)) + { + // + // Extract the FS_SEL from the GYRO_CONFIG register value. + // + psInst->ui8NewGyroFsSel = ((pui8Data[ui8Reg - MPU6050_O_GYRO_CONFIG] & + MPU6050_GYRO_CONFIG_FS_SEL_M) >> + MPU6050_GYRO_CONFIG_FS_SEL_S); + } + + // + // See if the ACCEL_CONFIG register is being written. + // + if((ui8Reg <= MPU6050_O_ACCEL_CONFIG) && + ((ui8Reg + ui16Count) > MPU6050_O_ACCEL_CONFIG)) + { + // + // Extract the AFS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8NewAccelAfsSel = + ((pui8Data[ui8Reg - MPU6050_O_ACCEL_CONFIG] & + MPU6050_ACCEL_CONFIG_AFS_SEL_M) >> + MPU6050_ACCEL_CONFIG_AFS_SEL_S); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = MPU6050_STATE_WRITE; + + // + // Write the requested registers to the MPU6050. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, + MPU6050Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = MPU6050_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a MPU6050 register. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the MPU6050 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! MPU6050. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +MPU6050ReadModifyWrite(tMPU6050 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the MPU6050 driver is not idle (in other words, + // there is already an outstanding request to the MPU6050). + // + if(psInst->ui8State != MPU6050_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = MPU6050_STATE_RMW; + + // + // Submit the read-modify-write request to the MPU6050. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, MPU6050Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = MPU6050_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the accelerometer and gyroscope data from the MPU6050. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the MPU6050 data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - MPU6050DataAccelGetRaw() +//! - MPU6050DataAccelGetFloat() +//! - MPU6050DataGyroGetRaw() +//! - MPU6050DataGyroGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +MPU6050DataRead(tMPU6050 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the MPU6050 driver is not idle (in other words, + // there is already an outstanding request to the MPU6050). + // + if(psInst->ui8State != MPU6050_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = MPU6050_STATE_READ; + + // + // Read the data registers from the MPU6050. + // + psInst->pui8Data[0] = MPU6050_O_ACCEL_XOUT_H; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8Data, 1, + psInst->pui8Data, 14, MPU6050Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = MPU6050_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param pui16AccelX is a pointer to the value into which the raw X-axis +//! accelerometer data is stored. +//! \param pui16AccelY is a pointer to the value into which the raw Y-axis +//! accelerometer data is stored. +//! \param pui16AccelZ is a pointer to the value into which the raw Z-axis +//! accelerometer data is stored. +//! +//! This function returns the raw accelerometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU6050DataAccelGetRaw(tMPU6050 *psInst, uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, uint_fast16_t *pui16AccelZ) +{ + // + // Return the raw accelerometer values. + // + if(pui16AccelX) + { + *pui16AccelX = (psInst->pui8Data[0] << 8) | psInst->pui8Data[1]; + } + if(pui16AccelY) + { + *pui16AccelY = (psInst->pui8Data[2] << 8) | psInst->pui8Data[3]; + } + if(pui16AccelZ) + { + *pui16AccelZ = (psInst->pui8Data[4] << 8) | psInst->pui8Data[5]; + } +} + +//***************************************************************************** +// +//! Gets the accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param pfAccelX is a pointer to the value into which the X-axis +//! accelerometer data is stored. +//! \param pfAccelY is a pointer to the value into which the Y-axis +//! accelerometer data is stored. +//! \param pfAccelZ is a pointer to the value into which the Z-axis +//! accelerometer data is stored. +//! +//! This function returns the accelerometer data from the most recent data +//! read, converted into meters per second squared (m/s^2). If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU6050DataAccelGetFloat(tMPU6050 *psInst, float *pfAccelX, float *pfAccelY, + float *pfAccelZ) +{ + float fFactor; + + // + // Get the acceleration conversion factor for the current data format. + // + fFactor = g_fMPU6050AccelFactors[psInst->ui8AccelAfsSel]; + + // + // Convert the Accelerometer values into floating-point gravity values. + // + if(pfAccelX) + { + *pfAccelX = (float)((int16_t)((psInst->pui8Data[0] << 8) | + psInst->pui8Data[1]) * fFactor); + } + if(pfAccelY) + { + *pfAccelY = (float)((int16_t)((psInst->pui8Data[2] << 8) | + psInst->pui8Data[3]) * fFactor); + } + if(pfAccelZ) + { + *pfAccelZ = (float)((int16_t)((psInst->pui8Data[4] << 8) | + psInst->pui8Data[5]) * fFactor); + } +} +//***************************************************************************** +// +//! Gets the raw gyroscope data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param pui16GyroX is a pointer to the value into which the raw X-axis +//! gyroscope data is stored. +//! \param pui16GyroY is a pointer to the value into which the raw Y-axis +//! gyroscope data is stored. +//! \param pui16GyroZ is a pointer to the value into which the raw Z-axis +//! gyroscope data is stored. +//! +//! This function returns the raw gyroscope data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU6050DataGyroGetRaw(tMPU6050 *psInst, uint_fast16_t *pui16GyroX, + uint_fast16_t *pui16GyroY, uint_fast16_t *pui16GyroZ) +{ + // + // Return the raw gyroscope values. + // + if(pui16GyroX) + { + *pui16GyroX = (psInst->pui8Data[8] << 8) | psInst->pui8Data[9]; + } + if(pui16GyroY) + { + *pui16GyroY = (psInst->pui8Data[10] << 8) | psInst->pui8Data[11]; + } + if(pui16GyroZ) + { + *pui16GyroZ = (psInst->pui8Data[12] << 8) | psInst->pui8Data[13]; + } +} + +//***************************************************************************** +// +//! Gets the gyroscope data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU6050 instance data. +//! \param pfGyroX is a pointer to the value into which the X-axis +//! gyroscope data is stored. +//! \param pfGyroY is a pointer to the value into which the Y-axis +//! gyroscope data is stored. +//! \param pfGyroZ is a pointer to the value into which the Z-axis +//! gyroscope data is stored. +//! +//! This function returns the gyroscope data from the most recent data read, +//! converted into radians per second. If any of the output data pointers are +//! \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU6050DataGyroGetFloat(tMPU6050 *psInst, float *pfGyroX, float *pfGyroY, + float *pfGyroZ) +{ + float fFactor; + + // + // Get the conversion factor for the current data format. + // + fFactor = g_fMPU6050GyroFactors[psInst->ui8GyroFsSel]; + + // + // Convert the gyroscope values into rad/sec + // + if(pfGyroX) + { + *pfGyroX = ((float)(int16_t)((psInst->pui8Data[8] << 8) | + psInst->pui8Data[9]) * fFactor); + } + if(pfGyroY) + { + *pfGyroY = ((float)(int16_t)((psInst->pui8Data[10] << 8) | + psInst->pui8Data[11]) * fFactor); + } + if(pfGyroZ) + { + *pfGyroZ = ((float)(int16_t)((psInst->pui8Data[12] << 8) | + psInst->pui8Data[13]) * fFactor); + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/mpu6050.h b/sensorlib/mpu6050.h new file mode 100644 index 0000000..ec11ab8 --- /dev/null +++ b/sensorlib/mpu6050.h @@ -0,0 +1,174 @@ +//***************************************************************************** +// +// mpu6050.h - Prototypes for the MPU6050 accelerometer and gyroscope driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_MPU6050_H__ +#define __SENSORLIB_MPU6050_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the MPU6050 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the MPU6050. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the MPU6050. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the MPU6050. + // + uint8_t ui8State; + + // + // The current accelerometer afs_sel setting. + // + uint8_t ui8AccelAfsSel; + + // + // The new accelerometer afs_sel setting, which is used when a register + // write succeeds. + // + uint8_t ui8NewAccelAfsSel; + + // + // The current gyroscope fs_sel setting. + // + uint8_t ui8GyroFsSel; + + // + // The new gyroscope fs_sel setting, which is used when a register write + // succeeds. + // + uint8_t ui8NewGyroFsSel; + + // + // The data buffer used for sending/receiving data to/from the MPU6050. + // + uint8_t pui8Data[16]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tMPU6050; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t MPU6050Init(tMPU6050 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t MPU6050Read(tMPU6050 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t MPU6050Write(tMPU6050 *psInst, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t MPU6050ReadModifyWrite(tMPU6050 *psInst, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t MPU6050DataRead(tMPU6050 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void MPU6050DataAccelGetRaw(tMPU6050 *psInst, + uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, + uint_fast16_t *pui16AccelZ); +extern void MPU6050DataAccelGetFloat(tMPU6050 *psInst, float *pfAccelX, + float *pfAccelY, float *pfAccelZ); +extern void MPU6050DataGyroGetRaw(tMPU6050 *psInst, uint_fast16_t *pui16GyroX, + uint_fast16_t *pui16GyroY, + uint_fast16_t *pui16GyroZ); +extern void MPU6050DataGyroGetFloat(tMPU6050 *psInst, float *pfGyroX, + float *pfGyroY, float *pfGyroZ); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_MPU6050_H__ diff --git a/sensorlib/mpu9150.c b/sensorlib/mpu9150.c new file mode 100644 index 0000000..a1515e2 --- /dev/null +++ b/sensorlib/mpu9150.c @@ -0,0 +1,1180 @@ +//***************************************************************************** +// +// mpu9150.c - Driver for the MPU9150 accelerometer, gyroscope, and +// magnetometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_ak8975.h" +#include "sensorlib/hw_mpu9150.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/ak8975.h" +#include "sensorlib/mpu9150.h" + +//***************************************************************************** +// +//! \addtogroup mpu9150_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the MPU9150 state machine. +// +//***************************************************************************** +#define MPU9150_STATE_IDLE 0 // State machine is idle +#define MPU9150_STATE_LAST 1 // Last step in a sequence +#define MPU9150_STATE_READ 2 // Waiting for read +#define MPU9150_STATE_WRITE 3 // Waiting for write +#define MPU9150_STATE_RMW 4 // Waiting for read modify write +#define MPU9150_STATE_INIT_RESET \ + 5 // reset request issued. +#define MPU9150_STATE_INIT_RESET_WAIT \ + 6 // polling wait for reset complete +#define MPU9150_STATE_INIT_PWR_MGMT \ + 7 // wake up the device. +#define MPU9150_STATE_INIT_USER_CTRL \ + 8 // init user control +#define MPU9150_STATE_INIT_SAMPLE_RATE_CFG \ + 9 // init the sensors and filters +#define MPU9150_STATE_INIT_I2C_SLAVE_DLY \ + 10 // set the ak8975 polling delay +#define MPU9150_STATE_INIT_I2C_SLAVE_0 \ + 11 // config ak8975 automatic read +#define MPU9150_STATE_RD_DATA 12 // Waiting for data read + +//***************************************************************************** +// +// The factors used to convert the acceleration readings from the MPU9150 into +// floating point values in meters per second squared. +// +// Values are obtained by taking the g conversion factors from the data sheet +// and multiplying by 9.81 (1 g = 9.81 m/s^2). +// +//***************************************************************************** +static const float g_fMPU9150AccelFactors[] = +{ + 0.0005985482, // Range = +/- 2 g (16384 lsb/g) + 0.0011970964, // Range = +/- 4 g (8192 lsb/g) + 0.0023941928, // Range = +/- 8 g (4096 lsb/g) + 0.0047883855 // Range = +/- 16 g (2048 lsb/g) +}; + +//***************************************************************************** +// +// The factors used to convert the acceleration readings from the MPU9150 into +// floating point values in radians per second. +// +// Values are obtained by taking the degree per second conversion factors +// from the data sheet and then converting to radians per sec (1 degree = +// 0.0174532925 radians). +// +//***************************************************************************** +static const float g_fMPU9150GyroFactors[] = +{ + 1.3323124e-4, // Range = +/- 250 dps (131.0) + 2.6646248e-4, // Range = +/- 500 dps (65.5) + 5.3211258e-4, // Range = +/- 1000 dps (32.8) + 0.0010642252 // Range = +/- 2000 dps (16.4) +}; + +//***************************************************************************** +// +// Converting sensor data to tesla (0.3 uT per LSB) +// +//***************************************************************************** +#define CONVERT_TO_TESLA 0.0000003 + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the +// MPU9150 have completed. +// +//***************************************************************************** +static void +MPU9150Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tMPU9150 *psInst; + + // + // Convert the instance data into a pointer to a tMPU9150 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). Except in the case that we are in the reset wait state and the + // error is an address NACK. This error is handled by the reset wait + // state. + // + if((ui8Status != I2CM_STATUS_SUCCESS) && + !((ui8Status == I2CM_STATUS_ADDR_NACK) && + (psInst->ui8State == MPU9150_STATE_INIT_RESET_WAIT))) + { + psInst->ui8State = MPU9150_STATE_IDLE; + } + + // + // Determine the current state of the MPU9150 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case MPU9150_STATE_READ: + case MPU9150_STATE_LAST: + case MPU9150_STATE_RD_DATA: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = MPU9150_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // MPU9150 Device reset was issued + // + case MPU9150_STATE_INIT_RESET: + { + // + // Issue a read of the status register to confirm reset is done. + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_PWR_MGMT_1; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, + MPU9150Callback, psInst); + + psInst->ui8State = MPU9150_STATE_INIT_RESET_WAIT; + break; + } + + // + // Status register was read, check if reset is done before proceeding. + // + case MPU9150_STATE_INIT_RESET_WAIT: + { + // + // Check the value read back from status to determine if device + // is still in reset or if it is ready. Reset state for this + // register is 0x40, which has sleep bit set. Device may also + // respond with an address NACK during very early stages of the + // its internal reset. Keep polling until we verify device is + // ready. + // + if((psInst->pui8Data[0] != MPU9150_PWR_MGMT_1_SLEEP) || + (ui8Status == I2CM_STATUS_ADDR_NACK)) + { + // + // Device still in reset so begin polling this register. + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_PWR_MGMT_1; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, + MPU9150Callback, psInst); + + // + // Intentionally stay in this state to create polling effect. + // + } + else + { + // + // Device is out of reset, bring it out of sleep mode. + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_PWR_MGMT_1; + psInst->uCommand.pui8Buffer[1] = MPU9150_PWR_MGMT_1_CLKSEL_XG; + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, MPU9150Callback, + psInst); + + // + // Update state to show we are modifing user control and + // power management 1 regs. + // + psInst->ui8State = MPU9150_STATE_INIT_PWR_MGMT; + } + break; + } + + // + // Reset complete now take device out of sleep mode. + // + case MPU9150_STATE_INIT_PWR_MGMT: + { + psInst->uCommand.pui8Buffer[0] = MPU9150_O_USER_CTRL; + psInst->uCommand.pui8Buffer[1] = MPU9150_USER_CTRL_I2C_MST_EN; + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, MPU9150Callback, + psInst); + + // + // Update state to show we are modifing user control and + // power management 1 regs. + // + psInst->ui8State = MPU9150_STATE_INIT_USER_CTRL; + + break; + } + + // + // Change to power mode complete, device is ready for configuration. + // + case MPU9150_STATE_INIT_USER_CTRL: + { + // + // Load index 0 with the sample rate register number. + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_SMPLRT_DIV; + + // + // Set sample rate to 50 hertz. 1000 hz / (1 + 19) + // + psInst->uCommand.pui8Buffer[1] = 19; + + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, MPU9150Callback, psInst); + + // + // update state to show are in process of configuring sensors. + // + psInst->ui8State = MPU9150_STATE_INIT_SAMPLE_RATE_CFG; + break; + } + + // + // Sensor configuration is complete. + // + case MPU9150_STATE_INIT_SAMPLE_RATE_CFG: + { + // + // Write the I2C Master delay control so we only sample the AK + // every 5th time that we sample accel/gyro. Delay Count itself + // handled in next state. + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_I2C_MST_DELAY_CTRL; + psInst->uCommand.pui8Buffer[1] = + (MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV0_DLY_EN | + MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV4_DLY_EN); + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, MPU9150Callback, psInst); + + // + // Update state to show we are configuring i2c slave delay between + // slave events. Slave 0 and Slave 4 transaction only occur every + // 5th sample cycle. + // + psInst->ui8State = MPU9150_STATE_INIT_I2C_SLAVE_DLY; + break; + } + + // + // Master slave delay configuration complete. + // + case MPU9150_STATE_INIT_I2C_SLAVE_DLY: + { + // + // Write the configuration for I2C master control clock 400khz + // and wait for external sensor before asserting data ready + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_I2C_MST_CTRL; + psInst->uCommand.pui8Buffer[1] = + (MPU9150_I2C_MST_CTRL_I2C_MST_CLK_400 | + MPU9150_I2C_MST_CTRL_WAIT_FOR_ES); + + // + // Configure I2C Slave 0 for read of AK8975 (I2C Address 0x0C) + // Start at AK8975 register status 1 + // Read 8 bytes and enable this slave transaction + // + psInst->uCommand.pui8Buffer[2] = MPU9150_I2C_SLV0_ADDR_RW | 0x0C; + psInst->uCommand.pui8Buffer[3] = AK8975_O_ST1; + psInst->uCommand.pui8Buffer[4] = MPU9150_I2C_SLV0_CTRL_EN | 0x08; + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 5, MPU9150Callback, psInst); + + // + // Update state. Now in process of configuring slave 0. + // + psInst->ui8State = MPU9150_STATE_INIT_I2C_SLAVE_0; + break; + } + + // + // I2C slave 0 init complete. + // + case MPU9150_STATE_INIT_I2C_SLAVE_0: + { + // + // Write the configuration for I2C Slave 4 transaction to AK8975 + // 0x0c is the AK8975 address on i2c bus. + // we want to write the control register with the value for a + // starting a single measurement. + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_I2C_SLV4_ADDR; + psInst->uCommand.pui8Buffer[1] = 0x0C; + psInst->uCommand.pui8Buffer[2] = AK8975_O_CNTL; + psInst->uCommand.pui8Buffer[3] = AK8975_CNTL_MODE_SINGLE; + + // + // Enable the SLV4 transaction and set the master delay to + // 0x04 + 1. This means the slave transactions with delay enabled + // will run every fifth accel/gyro sample. + // + psInst->uCommand.pui8Buffer[4] = MPU9150_I2C_SLV4_CTRL_EN | 0x04; + I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 5, MPU9150Callback, psInst); + + // + // Update state. Now in the final init state. + // + psInst->ui8State = MPU9150_STATE_LAST; + break; + } + + // + // A write just completed + // + case MPU9150_STATE_WRITE: + { + // + // Set the accelerometer and gyroscope ranges to the new values. + // If the register was not modified, the values will be the same so + // this has no effect. + // + psInst->ui8AccelAfsSel = psInst->ui8NewAccelAfsSel; + psInst->ui8GyroFsSel = psInst->ui8NewGyroFsSel; + + // + // The state machine is now idle. + // + psInst->ui8State = MPU9150_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // A read-modify-write just completed + // + case MPU9150_STATE_RMW: + { + // + // See if the PWR_MGMT_1 register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + MPU9150_O_PWR_MGMT_1) + { + // + // See if a soft reset has been issued. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + MPU9150_PWR_MGMT_1_DEVICE_RESET) + { + // + // Default range setting is +/- 2 g + // + psInst->ui8AccelAfsSel = 0; + psInst->ui8NewAccelAfsSel = 0; + + // + // Default range setting is +/- 250 degrees/s + // + psInst->ui8GyroFsSel = 0; + psInst->ui8NewGyroFsSel = 0; + } + } + + // + // See if the GYRO_CONFIG register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + MPU9150_O_GYRO_CONFIG) + { + // + // Extract the FS_SEL from the GYRO_CONFIG register value. + // + psInst->ui8GyroFsSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + MPU9150_GYRO_CONFIG_FS_SEL_M) >> + MPU9150_GYRO_CONFIG_FS_SEL_S); + } + + // + // See if the ACCEL_CONFIG register was just modified. + // + if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == + MPU9150_O_ACCEL_CONFIG) + { + // + // Extract the FS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8AccelAfsSel = + ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & + MPU9150_ACCEL_CONFIG_AFS_SEL_M) >> + MPU9150_ACCEL_CONFIG_AFS_SEL_S); + } + + // + // The state machine is now idle. + // + psInst->ui8State = MPU9150_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == MPU9150_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the MPU9150 driver. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param psI2CInst is a pointer to the I2C master driver instance data. +//! \param ui8I2CAddr is the I2C address of the MPU9150 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the MPU9150 driver, preparing it for operation. +//! +//! \return Returns 1 if the MPU9150 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +MPU9150Init(tMPU9150 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Initialize the MPU9150 instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Default range setting is +/- 2 g + // + psInst->ui8AccelAfsSel = (MPU9150_ACCEL_CONFIG_AFS_SEL_2G >> + MPU9150_ACCEL_CONFIG_AFS_SEL_S); + psInst->ui8NewAccelAfsSel = (MPU9150_ACCEL_CONFIG_AFS_SEL_2G >> + MPU9150_ACCEL_CONFIG_AFS_SEL_S); + + // + // Default range setting is +/- 250 degrees/s + // + psInst->ui8GyroFsSel = (MPU9150_GYRO_CONFIG_FS_SEL_250 >> + MPU9150_GYRO_CONFIG_FS_SEL_S); + psInst->ui8NewGyroFsSel = (MPU9150_GYRO_CONFIG_FS_SEL_250 >> + MPU9150_GYRO_CONFIG_FS_SEL_S); + + // + // Set the state to show we are initiating a reset. + // + psInst->ui8State = MPU9150_STATE_INIT_RESET; + + // + // Load the buffer with command to perform device reset + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_PWR_MGMT_1; + psInst->uCommand.pui8Buffer[1] = MPU9150_PWR_MGMT_1_DEVICE_RESET; + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, MPU9150Callback, psInst) == 0) + { + psInst->ui8State = MPU9150_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Returns the pointer to the tAK8975 object +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! +//! The MPU9150 contains in internal AK8975 magnetometer. To access data from +//! that sensor, application should use this function to get a pointer to the +//! tAK8975 object, and then use the AK8975 APIs. +//! +//! \return Returns the pointer to the tAK8975 object +// +//***************************************************************************** +tAK8975 * +MPU9150MagnetoInstGet(tMPU9150 *psInst) +{ + return(&(psInst->sAK8975Inst)); +} + +//***************************************************************************** +// +//! Reads data from MPU9150 registers. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count is the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the MPU9150. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +MPU9150Read(tMPU9150 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the MPU9150 driver is not idle (in other words, + // there is already an outstanding request to the MPU9150). + // + if(psInst->ui8State != MPU9150_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = MPU9150_STATE_READ; + + // + // Read the requested registers from the MPU9150. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + MPU9150Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = MPU9150_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to MPU9150 registers. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui8Data is a pointer to the data to write. +//! \param ui16Count is the number of data bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the MPU9150. The first byte of the \e pui8Data buffer contains the value +//! to be written into the \e ui8Reg register, the second value contains the +//! data to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +MPU9150Write(tMPU9150 *psInst, uint_fast8_t ui8Reg, const uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the MPU9150 driver is not idle (in other words, + // there is already an outstanding request to the MPU9150). + // + if(psInst->ui8State != MPU9150_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // See if the PWR_MGMT_1 register is being written. + // + if((ui8Reg <= MPU9150_O_PWR_MGMT_1) && + ((ui8Reg + ui16Count) > MPU9150_O_PWR_MGMT_1)) + { + // + // See if a soft reset is being requested. + // + if(pui8Data[ui8Reg - MPU9150_O_PWR_MGMT_1] & + MPU9150_PWR_MGMT_1_DEVICE_RESET) + { + // + // Default range setting is +/- 2 g. + // + psInst->ui8NewAccelAfsSel = 0; + + // + // Default range setting is +/- 250 degrees/s. + // + psInst->ui8NewGyroFsSel = 0; + } + } + + // + // See if the GYRO_CONFIG register is being written. + // + if((ui8Reg <= MPU9150_O_GYRO_CONFIG) && + ((ui8Reg + ui16Count) > MPU9150_O_GYRO_CONFIG)) + { + // + // Extract the FS_SEL from the GYRO_CONFIG register value. + // + psInst->ui8NewGyroFsSel = ((pui8Data[ui8Reg - MPU9150_O_GYRO_CONFIG] & + MPU9150_GYRO_CONFIG_FS_SEL_M) >> + MPU9150_GYRO_CONFIG_FS_SEL_S); + } + + // + // See if the ACCEL_CONFIG register is being written. + // + if((ui8Reg <= MPU9150_O_ACCEL_CONFIG) && + ((ui8Reg + ui16Count) > MPU9150_O_ACCEL_CONFIG)) + { + // + // Extract the AFS_SEL from the ACCEL_CONFIG register value. + // + psInst->ui8NewAccelAfsSel = + ((pui8Data[ui8Reg - MPU9150_O_ACCEL_CONFIG] & + MPU9150_ACCEL_CONFIG_AFS_SEL_M) >> + MPU9150_ACCEL_CONFIG_AFS_SEL_S); + } + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = MPU9150_STATE_WRITE; + + // + // Write the requested registers to the MPU9150. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, + MPU9150Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = MPU9150_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a MPU9150 register. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the MPU9150 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the +//! MPU9150. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +MPU9150ReadModifyWrite(tMPU9150 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the MPU9150 driver is not idle (in other words, + // there is already an outstanding request to the MPU9150). + // + if(psInst->ui8State != MPU9150_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = MPU9150_STATE_RMW; + + // + // Submit the read-modify-write request to the MPU9150. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, MPU9150Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = MPU9150_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the accelerometer and gyroscope data from the MPU9150 and the +//! magnetometer data from the on-chip aK8975. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the MPU9150 data registers. When the +//! read has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - MPU9150DataAccelGetRaw() +//! - MPU9150DataAccelGetFloat() +//! - MPU9150DataGyroGetRaw() +//! - MPU9150DataGyroGetFloat() +//! - MPU9150DataMagnetoGetRaw() +//! - MPU9150DataMagnetoGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +MPU9150DataRead(tMPU9150 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the MPU9150 driver is not idle (in other words, + // there is already an outstanding request to the MPU9150). + // + if(psInst->ui8State != MPU9150_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = MPU9150_STATE_RD_DATA; + + // + // Read the data registers from the MPU9150. + // + // (ACCEL_XOUT_H(0x3B) -> GYRO_ZOUT_L(0x48) = 14 bytes + // Grab Ext Sens Data as well for another 8 bytes. ST1 + Mag Data + ST2 + // + psInst->uCommand.pui8Buffer[0] = MPU9150_O_ACCEL_XOUT_H; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 22, + MPU9150Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = MPU9150_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param pui16AccelX is a pointer to the value into which the raw X-axis +//! accelerometer data is stored. +//! \param pui16AccelY is a pointer to the value into which the raw Y-axis +//! accelerometer data is stored. +//! \param pui16AccelZ is a pointer to the value into which the raw Z-axis +//! accelerometer data is stored. +//! +//! This function returns the raw accelerometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU9150DataAccelGetRaw(tMPU9150 *psInst, uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, uint_fast16_t *pui16AccelZ) +{ + // + // Return the raw accelerometer values. + // + if(pui16AccelX) + { + *pui16AccelX = (psInst->pui8Data[0] << 8) | psInst->pui8Data[1]; + } + if(pui16AccelY) + { + *pui16AccelY = (psInst->pui8Data[2] << 8) | psInst->pui8Data[3]; + } + if(pui16AccelZ) + { + *pui16AccelZ = (psInst->pui8Data[4] << 8) | psInst->pui8Data[5]; + } +} + +//***************************************************************************** +// +//! Gets the accelerometer data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param pfAccelX is a pointer to the value into which the X-axis +//! accelerometer data is stored. +//! \param pfAccelY is a pointer to the value into which the Y-axis +//! accelerometer data is stored. +//! \param pfAccelZ is a pointer to the value into which the Z-axis +//! accelerometer data is stored. +//! +//! This function returns the accelerometer data from the most recent data +//! read, converted into meters per second squared (m/s^2). If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU9150DataAccelGetFloat(tMPU9150 *psInst, float *pfAccelX, float *pfAccelY, + float *pfAccelZ) +{ + float fFactor; + + // + // Get the acceleration conversion factor for the current data format. + // + fFactor = g_fMPU9150AccelFactors[psInst->ui8AccelAfsSel]; + + // + // Convert the accelerometer values into m/sec^2 + // + if(pfAccelX) + { + *pfAccelX = ((float)(int16_t)((psInst->pui8Data[0] << 8) | + psInst->pui8Data[1]) * fFactor); + } + if(pfAccelY) + { + *pfAccelY = ((float)(int16_t)((psInst->pui8Data[2] << 8) | + psInst->pui8Data[3]) * fFactor); + } + if(pfAccelZ) + { + *pfAccelZ = ((float)(int16_t)((psInst->pui8Data[4] << 8) | + psInst->pui8Data[5]) * fFactor); + } +} + +//***************************************************************************** +// +//! Gets the raw gyroscope data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param pui16GyroX is a pointer to the value into which the raw X-axis +//! gyroscope data is stored. +//! \param pui16GyroY is a pointer to the value into which the raw Y-axis +//! gyroscope data is stored. +//! \param pui16GyroZ is a pointer to the value into which the raw Z-axis +//! gyroscope data is stored. +//! +//! This function returns the raw gyroscope data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU9150DataGyroGetRaw(tMPU9150 *psInst, uint_fast16_t *pui16GyroX, + uint_fast16_t *pui16GyroY, uint_fast16_t *pui16GyroZ) +{ + // + // Return the raw gyroscope values. + // + if(pui16GyroX) + { + *pui16GyroX = (psInst->pui8Data[8] << 8) | psInst->pui8Data[9]; + } + if(pui16GyroY) + { + *pui16GyroY = (psInst->pui8Data[10] << 8) | psInst->pui8Data[11]; + } + if(pui16GyroZ) + { + *pui16GyroZ = (psInst->pui8Data[12] << 8) | psInst->pui8Data[13]; + } +} + +//***************************************************************************** +// +//! Gets the gyroscope data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param pfGyroX is a pointer to the value into which the X-axis +//! gyroscope data is stored. +//! \param pfGyroY is a pointer to the value into which the Y-axis +//! gyroscope data is stored. +//! \param pfGyroZ is a pointer to the value into which the Z-axis +//! gyroscope data is stored. +//! +//! This function returns the gyroscope data from the most recent data read, +//! converted into radians per second. If any of the output data pointers are +//! \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU9150DataGyroGetFloat(tMPU9150 *psInst, float *pfGyroX, float *pfGyroY, + float *pfGyroZ) +{ + float fFactor; + int16_t i16Temp; + + // + // Get the gyroscope conversion factor for the current data format. + // + fFactor = g_fMPU9150GyroFactors[psInst->ui8GyroFsSel]; + + // + // Convert the gyroscope values into rad/sec + // + if(pfGyroX) + { + i16Temp = (int16_t)psInst->pui8Data[8]; + i16Temp <<= 8; + i16Temp += psInst->pui8Data[9]; + *pfGyroX = (float)i16Temp; + *pfGyroX *= fFactor; + } + if(pfGyroY) + { + i16Temp = (int16_t)psInst->pui8Data[10]; + i16Temp <<= 8; + i16Temp += psInst->pui8Data[11]; + *pfGyroY = (float)i16Temp; + *pfGyroY *= fFactor; + } + if(pfGyroZ) + { + i16Temp = (int16_t)psInst->pui8Data[12]; + i16Temp <<= 8; + i16Temp += psInst->pui8Data[13]; + *pfGyroZ = (float)i16Temp; + *pfGyroZ *= fFactor; + } +} + +//***************************************************************************** +// +//! Gets the raw magnetometer data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param pui16MagnetoX is a pointer to the value into which the raw X-axis +//! magnetometer data is stored. +//! \param pui16MagnetoY is a pointer to the value into which the raw Y-axis +//! magnetometer data is stored. +//! \param pui16MagnetoZ is a pointer to the value into which the raw Z-axis +//! magnetometer data is stored. +//! +//! This function returns the raw magnetometer data from the most recent data +//! read. The data is not manipulated in any way by the driver. If any of the +//! output data pointers are \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU9150DataMagnetoGetRaw(tMPU9150 *psInst, uint_fast16_t *pui16MagnetoX, + uint_fast16_t *pui16MagnetoY, + uint_fast16_t *pui16MagnetoZ) +{ + uint8_t *pui8ExtSensData; + + pui8ExtSensData = &(psInst->pui8Data[14]); + + // + // Return the raw magnetometer values. + // + if(pui16MagnetoX) + { + *pui16MagnetoX = (pui8ExtSensData[2] << 8) | pui8ExtSensData[1]; + } + if(pui16MagnetoY) + { + *pui16MagnetoY = (pui8ExtSensData[4] << 8) | pui8ExtSensData[3]; + } + if(pui16MagnetoZ) + { + *pui16MagnetoZ = (pui8ExtSensData[6] << 8) | pui8ExtSensData[5]; + } +} + +//***************************************************************************** +// +//! Gets the magnetometer data from the most recent data read. +//! +//! \param psInst is a pointer to the MPU9150 instance data. +//! \param pfMagnetoX is a pointer to the value into which the X-axis +//! magnetometer data is stored. +//! \param pfMagnetoY is a pointer to the value into which the Y-axis +//! magnetometer data is stored. +//! \param pfMagnetoZ is a pointer to the value into which the Z-axis +//! magnetometer data is stored. +//! +//! This function returns the magnetometer data from the most recent data read, +//! converted into tesla. If any of the output data pointers are +//! \b NULL, the corresponding data is not provided. +//! +//! \return None. +// +//***************************************************************************** +void +MPU9150DataMagnetoGetFloat(tMPU9150 *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ) +{ + int16_t *pi16Data; + + pi16Data = (int16_t *)(psInst->pui8Data + 15); + + // + // Convert the magnetometer values into floating-point tesla values. + // + if(pfMagnetoX) + { + *pfMagnetoX = (float)pi16Data[0]; + *pfMagnetoX *= CONVERT_TO_TESLA; + } + if(pfMagnetoY) + { + *pfMagnetoY = (float)pi16Data[1]; + *pfMagnetoY *= CONVERT_TO_TESLA; + } + if(pfMagnetoZ) + { + *pfMagnetoZ = (float)pi16Data[2]; + *pfMagnetoZ *= CONVERT_TO_TESLA; + } +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/mpu9150.h b/sensorlib/mpu9150.h new file mode 100644 index 0000000..459d6ca --- /dev/null +++ b/sensorlib/mpu9150.h @@ -0,0 +1,187 @@ +//***************************************************************************** +// +// mpu9150.h - Prototypes for the MPU9150 accelerometer, gyroscope, and +// magnetometer driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_MPU9150_H__ +#define __SENSORLIB_MPU9150_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the MPU9150 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the MPU9150. + // + tI2CMInstance *psI2CInst; + + // + // The AK8975 inst that used to access the on-chip AK8975 magnetometer + // + tAK8975 sAK8975Inst; + + // + // The I2C address of the MPU9150. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the MPU9150. + // + uint8_t ui8State; + + // + // The current accelerometer afs_sel setting + // + uint8_t ui8AccelAfsSel; + + // + // The new accelerometer afs_sel setting, which is used when a register + // write succeeds. + // + uint8_t ui8NewAccelAfsSel; + + // + // The current gyroscope fs_sel setting + // + uint8_t ui8GyroFsSel; + + // + // The new gyroscope fs_sel setting, which is used when a register write + // succeeds. + // + uint8_t ui8NewGyroFsSel; + + // + // The data buffer used for sending/receiving data to/from the MPU9150. + // + uint8_t pui8Data[24]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[6]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tMPU9150; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t MPU9150Init(tMPU9150 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern tAK8975 *MPU9150InstAK8975Get(tMPU9150 *psInst); +extern uint_fast8_t MPU9150Read(tMPU9150 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t MPU9150Write(tMPU9150 *psInst, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t MPU9150ReadModifyWrite(tMPU9150 *psInst, + uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t MPU9150DataRead(tMPU9150 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void MPU9150DataAccelGetRaw(tMPU9150 *psInst, + uint_fast16_t *pui16AccelX, + uint_fast16_t *pui16AccelY, + uint_fast16_t *pui16AccelZ); +extern void MPU9150DataAccelGetFloat(tMPU9150 *psInst, float *pfAccelX, + float *pfAccelY, float *pfAccelZ); +extern void MPU9150DataGyroGetRaw(tMPU9150 *psInst, uint_fast16_t *pui16GyroX, + uint_fast16_t *pui16GyroY, + uint_fast16_t *pui16GyroZ); +extern void MPU9150DataGyroGetFloat(tMPU9150 *psInst, float *pfGyroX, + float *pfGyroY, float *pfGyroZ); +extern void MPU9150DataMagnetoGetRaw(tMPU9150 *psInst, + uint_fast16_t *pui16MagnetoX, + uint_fast16_t *pui16MagnetoY, + uint_fast16_t *pui16MagnetoZ); +extern void MPU9150DataMagnetoGetFloat(tMPU9150 *psInst, float *pfMagnetoX, + float *pfMagnetoY, float *pfMagnetoZ); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_MPU9150_H__ diff --git a/sensorlib/quaternion.c b/sensorlib/quaternion.c new file mode 100644 index 0000000..78296aa --- /dev/null +++ b/sensorlib/quaternion.c @@ -0,0 +1,286 @@ +//***************************************************************************** +// +// quaternion.c - Functions for performing quaternion operations. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/quaternion.h" + +//***************************************************************************** +// +//! \addtogroup quaternion_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// If M_PI has not been defined by the system headers, define it here. +// +//***************************************************************************** +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//***************************************************************************** +// +//! Computes a quaternion from a set of eueler angles specified in degrees +//! +//! \param pfQOut is the inverted quaternion in W,X,Y,Z form +//! \param fRollDeg is roll in degrees +//! \param fPitchDeg is pitch in degrees +//! \param fYawDeg is yaw in degrees +//! +//! This function computes a quaternion from a set of euler angles specified +//! in degrees +//! +//! \return Returns a quaternion representing the provided eulers +// +//***************************************************************************** +void +QuaternionFromEuler(float pfQOut[4], float fRollDeg, float fPitchDeg, + float fYawDeg) +{ + float fRoll, fPitch, fYaw; + float fCOSY, fCOSP, fCOSR; + float fSINY, fSINP, fSINR; + + // + // Convert roll, pitch, and yaw from degrees into radians + // + fRoll = fRollDeg * M_PI / 180.0; + fPitch = fPitchDeg * M_PI / 180.0; + fYaw = fYawDeg * M_PI / 180.0; + + // + // Pre-calculate the cosine of (yaw, pitch, roll divided by 2) + // + fCOSY = cosf(fYaw / 2.0); + fCOSP = cosf(fPitch / 2.0); + fCOSR = cosf(fRoll / 2.0); + + // + // Pre-calculate the sine of (yaw, pitch, roll divided by 2) + // + fSINY = sinf(fYaw / 2.0); + fSINP = sinf(fPitch / 2.0); + fSINR = sinf(fRoll / 2.0); + + // + // The W component + // + pfQOut[Q_W] = fCOSY * fCOSP * fCOSR - fSINY * fSINP * fSINR; + + // + // The X component + // + pfQOut[Q_X] = fSINY * fSINP * fCOSR + fCOSY * fCOSP * fSINR; + + // + // The Y component + // + pfQOut[Q_Y] = fCOSY * fSINP * fCOSR - fSINY * fCOSP * fSINR; + + // + // The Z component + // + pfQOut[Q_Z] = fSINY * fCOSP * fCOSR + fCOSY * fSINP * fSINR; +} + +//***************************************************************************** +// +//! Computes the magnitude of a quaternion. +//! +//! \param pfQIn is the source quaternion in W,X,Y,Z form +//! +//! This function computes the magnitude of a quaternion by summing the square +//! of each of the quatnerion components. +//! +//! \return Returns the scalar magnitude of the quaternion +// +//***************************************************************************** +float +QuaternionMagnitude(float pfQIn[4]) +{ + float fSumSq; + + // + // Calculate the magnitude of the quaternion by finding the sum of the + // squares of each component. + // + fSumSq = ((pfQIn[Q_W] * pfQIn[Q_W]) + (pfQIn[Q_X] * pfQIn[Q_X]) + + (pfQIn[Q_Y] * pfQIn[Q_Y]) + (pfQIn[Q_Z] * pfQIn[Q_Z])); + + return(fSumSq); +} + +//***************************************************************************** +// +//! Computes the inverse of a quaternion. +//! +//! \param pfQOut is the inverted quaternion in W,X,Y,Z form +//! \param pfQIn is the source quaternion in W,X,Y,Z form +//! +//! This function computes the inverse of a quaternion. The inverse of a +//! quaternion produces a rotation opposite to the source quaternion. This +//! can be achieved by simply changing the signs of the imaginary components +//! of a quaternion when the quatnerion is a unit quaternion. +//! +//! \return Returns the inverse of a quaternion. +// +//***************************************************************************** +void +QuaternionInverse(float pfQOut[4], float pfQIn[4]) +{ + float fMag; + + // + // Find magnitude of the quaternion. This will be used to normalize the + // source quaternion if it's not already. If it is a unit quaternion then + // the magnitude should be nearly equal to 1.0 and dividing by the + // magnitude has no mathemtical effect. + // + fMag = QuaternionMagnitude(pfQIn); + + // + // Normalize the W component + // + pfQOut[Q_W] = pfQIn[Q_W] / fMag; + + // + // Invert and normalize the X component + // + pfQOut[Q_X] = -pfQIn[Q_X] / fMag; + + // + // Invert and normalize the Y component + // + pfQOut[Q_Y] = -pfQIn[Q_Y] / fMag; + + // + // Invert and normalize the Z component + // + pfQOut[Q_Z] = -pfQIn[Q_Z] / fMag; +} + +//***************************************************************************** +// +//! Computes the product of two quaternions. +//! +//! \param pfQOut is the product of In1 X In2 +//! \param pfQIn1 is the source quaternion in W,X,Y,Z form +//! \param pfQIn2 is the source quaternion in W,X,Y,Z form +//! +//! This function computes the cross product of two quaternions. +//! +//! \return Returns the cross product of the two quaternions. +// +//***************************************************************************** +void +QuaternionMult(float pfQOut[4], float pfQIn1[4], float pfQIn2[4]) +{ + // + // Let Q1 and Q2 be two quaternions with components w,x,y,z + // Let Qp be the cross product Q1 x Q2. The components of Qp can be + // calculated as follows: + // + // Qp.w = (Q1w Q2w) - (Q1x Q2x) - (Q1y Q2y) - (Q1z Q2z) + // Qp.x = (Q1w Q2x) + (Q1x Q2w) - (Q1z Q2y) + (Q1y Q2z) + // Qp.y = (Q1y Q2w) + (Q1z Q2x) + (Q1w Q2y) - (Q1x Q2z) + // Qp.z = (Q1z Q2w) - (Q1y Q2x) + (Q1x Q2y) + (Q1w Q2z) + // + + // + // Calculate the W term + // + pfQOut[Q_W] = ((pfQIn2[Q_W] * pfQIn1[Q_W]) - (pfQIn2[Q_X] * pfQIn1[Q_X]) - + (pfQIn2[Q_Y] * pfQIn1[Q_Y]) - (pfQIn2[Q_Z] * pfQIn1[Q_Z])); + + // + // Calculate the X term + // + pfQOut[Q_X]= ((pfQIn2[Q_X] * pfQIn1[Q_W]) + (pfQIn2[Q_W] * pfQIn1[Q_X]) - + (pfQIn2[Q_Y] * pfQIn1[Q_Z]) + (pfQIn2[Q_Z] * pfQIn1[Q_Y])); + + // + // Calculate the Y term + // + pfQOut[Q_Y]= ((pfQIn2[Q_W] * pfQIn1[Q_Y]) + (pfQIn2[Q_X] * pfQIn1[Q_Z]) - + (pfQIn2[Q_Y] * pfQIn1[Q_W]) - (pfQIn2[Q_Z] * pfQIn1[Q_X])); + + // + // Calculate the Z term + // + pfQOut[Q_Z] = ((pfQIn2[Q_W] * pfQIn1[Q_Z]) - (pfQIn2[Q_X] * pfQIn1[Q_Y]) - + (pfQIn2[Q_Y] * pfQIn1[Q_X]) + (pfQIn2[Q_Z] * pfQIn1[Q_W])); +} + +//***************************************************************************** +// +//! Computes the angle between two quaternions +//! +//! \param pfQIn1 is a source quaternion in W,X,Y,Z form +//! \param pfQIn2 is a source quaternion in W,X,Y,Z form +//! +//! This function computes the angle between two quaternions. +//! +//! \return Returns the angle, in radians, between the two quaternions. +// +//***************************************************************************** +float +QuaternionAngle(float pfQIn1[4], float pfQIn2[4]) +{ + float pfQInv[4]; + float pfQProd[4]; + + // + // Let Q1 and Q2 be two quaternions having components w,x,y,z. The angle + // between the orientations represented by Q1 and Q2 can be calculated + // with: + // + // angle = arccos( (Q2 * Q1').w ) * 2.0; + // + // where Q1' is the inverse of Q1 + // + + // + // Calculate the inverse of Q1 + // + QuaternionInverse(pfQInv, pfQIn1); + + // + // Find the product of Q2 x Q1` + // + QuaternionMult(pfQProd, pfQIn2, pfQInv); + + // + // calculate the arccos of the w component of the previous product. + // + return(acosf(pfQProd[Q_W]) * 2.0); +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/quaternion.h b/sensorlib/quaternion.h new file mode 100644 index 0000000..79f9270 --- /dev/null +++ b/sensorlib/quaternion.h @@ -0,0 +1,70 @@ +//***************************************************************************** +// +// quaternion.h - Prototypes for the quaternion functions. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_QUATERNION_H__ +#define __SENSORLIB_QUATERNION_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The index of the components in a quaternion vector. +// +//***************************************************************************** +#define Q_W 0 +#define Q_X 1 +#define Q_Y 2 +#define Q_Z 3 + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern void QuaternionFromEuler(float pfQOut[4], float fRollDeg, + float fPitchDeg, float fYawDeg); +extern float QuaternionMagnitude(float pfQIn[4]); +extern void QuaternionInverse(float pfQOut[4], float pfQIn[4]); +extern void QuaternionMult(float pfQOut[4], float pfQIn1[4], float pfQIn2[4]); +extern float QuaternionAngle(float pfQIn1[4], float pfQIn2[4]); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_QUATERNION_H__ diff --git a/sensorlib/readme.txt b/sensorlib/readme.txt new file mode 100644 index 0000000..209ec0c --- /dev/null +++ b/sensorlib/readme.txt @@ -0,0 +1,21 @@ +This project will build the Texas Instruments Sensor Library. + +------------------------------------------------------------------------------- + +Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +Software License Agreement + +Texas Instruments (TI) is supplying this software for use solely and +exclusively on TI's microcontroller products. The software is owned by +TI and/or its suppliers, and is protected under applicable copyright +laws. You may not combine this software with "viral" open-source +software in order to form a larger program. + +THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, FOR ANY REASON WHATSOEVER. + +This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. diff --git a/sensorlib/rvmdk/sensorlib.lib b/sensorlib/rvmdk/sensorlib.lib new file mode 100644 index 0000000..582e01b Binary files /dev/null and b/sensorlib/rvmdk/sensorlib.lib differ diff --git a/sensorlib/sensorlib.ewp b/sensorlib/sensorlib.ewp new file mode 100644 index 0000000..9504f35 --- /dev/null +++ b/sensorlib/sensorlib.ewp @@ -0,0 +1,833 @@ + + + + 1 + + Debug + + ARM + + 1 + + General + 3 + + 14 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCARM + 2 + + 19 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AARM + 2 + + 7 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + OBJCOPY + 0 + + 1 + 1 + 1 + + + + + + + + + CUSTOM + 3 + + + + + + + BICOMP + 0 + + + + BUILDACTION + 1 + + + + + + + ILINK + 0 + + 5 + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IARCHIVE + 0 + + 0 + 1 + 1 + + + + + + + BILINK + 0 + + + + + Source + + $PROJ_DIR$\ak8963.c + + + $PROJ_DIR$\ak8975.c + + + $PROJ_DIR$\bmp180.c + + + $PROJ_DIR$\bq27510g3.c + + + $PROJ_DIR$\cm3218.c + + + $PROJ_DIR$\comp_dcm.c + + + $PROJ_DIR$\i2cm_drv.c + + + $PROJ_DIR$\isl29023.c + + + $PROJ_DIR$\kxti9.c + + + $PROJ_DIR$\l3gd20h.c + + + $PROJ_DIR$\lsm303d.c + + + $PROJ_DIR$\lsm303dlhc_accel.c + + + $PROJ_DIR$\lsm303dlhc_mag.c + + + $PROJ_DIR$\magneto.c + + + $PROJ_DIR$\mpu6050.c + + + $PROJ_DIR$\mpu9150.c + + + $PROJ_DIR$\quaternion.c + + + $PROJ_DIR$\sht21.c + + + $PROJ_DIR$\tmp006.c + + + $PROJ_DIR$\tmp100.c + + + $PROJ_DIR$\vector.c + + + diff --git a/sensorlib/sensorlib.uvopt b/sensorlib/sensorlib.uvopt new file mode 100644 index 0000000..2d5838b --- /dev/null +++ b/sensorlib/sensorlib.uvopt @@ -0,0 +1,524 @@ + + + + 1.0 + +
### uVision Project, (C) Keil Software
+ + + *.c + *.s*; *.src; *.a* + *.obj + *.lib + *.txt; *.h; *.inc + *.plm + *.cpp + + + + 0 + 0 + + + + sensorlib + 0x4 + ARM-ADS + + 8000000 + + 1 + 1 + 1 + 0 + + + 1 + 65535 + 0 + 0 + 0 + + + 79 + 66 + 8 + .\rvmdk\ + + + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 0 + + + 1 + 0 + 1 + + 255 + + + 0 + Data Sheet + DATASHTS\Luminary\TM4C1230C3PM.PDF + + + + SARMCM3.DLL + -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + 1 + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 1 + 0 + 1 + 0 + 0 + 3 + + + + + + + + + + + BIN\lmidk-agdi.dll + + + + 0 + lmidk-agdi + -O4622 -S3 -FO29 + + + + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + Source + 1 + 0 + 0 + + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\ak8963.c + ak8963.c + + + 1 + 2 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\ak8975.c + ak8975.c + + + 1 + 3 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\bmp180.c + bmp180.c + + + 1 + 4 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\bq27510g3.c + bq27510g3.c + + + 1 + 5 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\cm3218.c + cm3218.c + + + 1 + 6 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\comp_dcm.c + comp_dcm.c + + + 1 + 7 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\i2cm_drv.c + i2cm_drv.c + + + 1 + 8 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\isl29023.c + isl29023.c + + + 1 + 9 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\kxti9.c + kxti9.c + + + 1 + 10 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\l3gd20h.c + l3gd20h.c + + + 1 + 11 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\lsm303d.c + lsm303d.c + + + 1 + 12 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\lsm303dlhc_accel.c + lsm303dlhc_accel.c + + + 1 + 13 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\lsm303dlhc_mag.c + lsm303dlhc_mag.c + + + 1 + 14 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\magneto.c + magneto.c + + + 1 + 15 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\mpu6050.c + mpu6050.c + + + 1 + 16 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\mpu9150.c + mpu9150.c + + + 1 + 17 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\quaternion.c + quaternion.c + + + 1 + 18 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\sht21.c + sht21.c + + + 1 + 19 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\tmp006.c + tmp006.c + + + 1 + 20 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\tmp100.c + tmp100.c + + + 1 + 21 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + .\vector.c + vector.c + + + + + Documentation + 1 + 0 + 0 + + 2 + 22 + 5 + 0 + 1 + 0 + 0 + 1 + 1 + 0 + .\readme.txt + readme.txt + + 44 + 0 + 1 + + -1 + -1 + + + -1 + -1 + + + 0 + 0 + 729 + 300 + + + + + + + 1 + 0 + + 100 + 0 + + + .\readme.txt + 0 + 1 + 1 + + + + + +
diff --git a/sensorlib/sensorlib.uvproj b/sensorlib/sensorlib.uvproj new file mode 100644 index 0000000..7d88e4c --- /dev/null +++ b/sensorlib/sensorlib.uvproj @@ -0,0 +1,510 @@ + + + + 1.1 + +
### uVision Project, (C) Keil Software
+ + + + sensorlib + 0x4 + ARM-ADS + + + TM4C1230C3PM + Texas Instruments + IRAM(0x20000000-0x20002FFF) IROM(0-0x7FFF) CLOCK(8000000) CPUTYPE("Cortex-M4") FPU2 + + "STARTUP\Luminary\Startup.s" ("Luminary Startup Code") + UL2CM3(-O207 -S0 -C0 -FO7 -FD20000000 -FC800 -FN1 -FF0LM4F_32 -FS00 -FL08000) + 5919 + LM4Fxxxx.H + + + + + + + + + + SFD\Luminary\TM4C1230C3PM.SFR + 0 + + + + Luminary\ + Luminary\ + + 0 + 0 + 0 + 0 + 1 + + .\rvmdk\ + sensorlib + 0 + 1 + 0 + 1 + 1 + .\rvmdk\ + 1 + 0 + 0 + + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + + 0 + 0 + + 0 + + + + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 3 + + + + + SARMCM3.DLL + -MPU + DCM.DLL + -pCM4 + SARMCM3.DLL + -MPU + TCM.DLL + -pCM4 + + + + 1 + 0 + 0 + 0 + 16 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + + + 0 + 1 + 0 + 1 + 1 + 1 + 0 + 1 + + 0 + 3 + + + + + + + + + + + + + + BIN\lmidk-agdi.dll + + + + + 1 + 0 + 0 + 0 + 1 + 4097 + + BIN\lmidk-agdi.dll + + + + + + 0 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 0 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + "Cortex-M4" + + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 2 + 0 + 0 + 8 + 1 + 0 + 0 + 3 + 3 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 1 + 0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x3000 + + + 1 + 0x0 + 0x8000 + + + 0 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x0 + + + 1 + 0x0 + 0x8000 + + + 1 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x0 + 0x0 + + + 0 + 0x20000000 + 0x3000 + + + 0 + 0x0 + 0x0 + + + + + + 0 + 3 + 1 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + + --c99 + rvmdk + + ..; + + + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + 0 + 1 + 0 + 0x00000000 + 0x20000000 + + + + + + + + + + + + Source + + + ak8963.c + 1 + .\ak8963.c + + + ak8975.c + 1 + .\ak8975.c + + + bmp180.c + 1 + .\bmp180.c + + + bq27510g3.c + 1 + .\bq27510g3.c + + + cm3218.c + 1 + .\cm3218.c + + + comp_dcm.c + 1 + .\comp_dcm.c + + + i2cm_drv.c + 1 + .\i2cm_drv.c + + + isl29023.c + 1 + .\isl29023.c + + + kxti9.c + 1 + .\kxti9.c + + + l3gd20h.c + 1 + .\l3gd20h.c + + + lsm303d.c + 1 + .\lsm303d.c + + + lsm303dlhc_accel.c + 1 + .\lsm303dlhc_accel.c + + + lsm303dlhc_mag.c + 1 + .\lsm303dlhc_mag.c + + + magneto.c + 1 + .\magneto.c + + + mpu6050.c + 1 + .\mpu6050.c + + + mpu9150.c + 1 + .\mpu9150.c + + + quaternion.c + 1 + .\quaternion.c + + + sht21.c + 1 + .\sht21.c + + + tmp006.c + 1 + .\tmp006.c + + + tmp100.c + 1 + .\tmp100.c + + + vector.c + 1 + .\vector.c + + + + + Documentation + + + readme.txt + 5 + .\readme.txt + + + + + + + +
diff --git a/sensorlib/sht21.c b/sensorlib/sht21.c new file mode 100644 index 0000000..0698593 --- /dev/null +++ b/sensorlib/sht21.c @@ -0,0 +1,564 @@ +//***************************************************************************** +// +// sht21.c - Driver for the SHT21 accelerometer. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include "sensorlib/hw_sht21.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/sht21.h" + +//***************************************************************************** +// +//! \addtogroup sht21_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the SHT21 state machine. +// +//***************************************************************************** +#define SHT21_STATE_IDLE 0 // State machine is idle +#define SHT21_STATE_INIT 1 // Waiting for initialization +#define SHT21_STATE_READ 2 // Waiting for register read +#define SHT21_STATE_WRITE 3 // Waiting for register write +#define SHT21_STATE_RMW 4 +#define SHT21_STATE_READ_DATA 5 // Waiting for temperature or + // humidity data + +//***************************************************************************** +// +// The callback function that is called when I2C transactions to/from the +// SHT21 have completed. +// +//***************************************************************************** +static void +SHT21Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tSHT21 *psInst; + + // + // Convert the instance data into a pointer to a tSHT221 structure. + // + psInst = (tSHT21 *)pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = SHT21_STATE_IDLE; + } + + // + // Determine the current state of the SHT21 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case SHT21_STATE_INIT: + case SHT21_STATE_READ: + case SHT21_STATE_WRITE: + case SHT21_STATE_READ_DATA: + case SHT21_STATE_RMW: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = SHT21_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == SHT21_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the SHT21 driver. +//! +//! \param psInst is a pointer to the SHT21 instance data. +//! \param psI2CInst is a pointer to the I2C driver instance data. +//! \param ui8I2CAddr is the I2C address of the SHT21 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the SHT21 driver, preparing it for operation, and +//! initiates a reset of the SHT21 device, clearing any previous configuration +//! data. +//! +//! \return Returns 1 if the SHT21 driver was successfully initialized and 0 if +//! it was not. +// +//***************************************************************************** +uint_fast8_t +SHT21Init(tSHT21 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Initialize the SHT21 instance structure. + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = SHT21_STATE_INIT; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Perform a soft reset of the SHT21. + // + psInst->pui8Data[0] = SHT21_CMD_SOFT_RESET; + if(I2CMWrite(psInst->psI2CInst, ui8I2CAddr, psInst->pui8Data, 1, + SHT21Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = SHT21_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from SHT21 registers. +//! +//! \param psInst is a pointer to the SHT21 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui8Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count the number of data bytes to read. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the SHT21. +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +SHT21Read(tSHT21 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the SHT21 driver is not idle (in other words, there + // is already an outstanding request to the SHT21). + // + if(psInst->ui8State != SHT21_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = SHT21_STATE_READ; + + // + // Read the requested registers from the SHT21. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, + SHT21Callback, (void *)psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = SHT21_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to SHT21 registers. +//! +//! \param psInst is a pointer to the SHT21 instance data. +//! \param ui8Reg is the register offset to be written. +//! \param pui8Data is the data buffer bytes to write. +//! \param ui16Count is the number of bytes to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the SHT21. The first byte of the \e pui8Data buffer contains the value to +//! be written into the \e ui8Reg register, the second value contains the data +//! to be written into the next register, and so on. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +SHT21Write(tSHT21 *psInst, uint_fast8_t ui8Reg, const uint8_t *pui8Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the SHT21 driver is not idle (in other words, there + // is already an outstanding request to the SHT21). + // + if(psInst->ui8State != SHT21_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = SHT21_STATE_WRITE; + + // + // Write the requested registers to the SHT21. + // + if(I2CMWrite8(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui8Data, ui16Count, SHT21Callback, + psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = SHT21_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a SHT21 register. +//! +//! \param psInst is a pointer to the SHT21 instance data. +//! \param ui8Reg is the register to modify. +//! \param ui8Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui8Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the SHT21 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui8Mask, ORed with \e ui8Value, and then written back to the SHT21. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +SHT21ReadModifyWrite(tSHT21 *psInst, uint_fast8_t ui8Reg, uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the SHT21 driver is not idle (in other words, there + // is already an outstanding request to the SHT21). + // + if(psInst->ui8State != SHT21_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = SHT21_STATE_RMW; + + // + // Submit the read-modify-write request to the TMP006. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui8Mask, ui8Value, SHT21Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = SHT21_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the temperature and humidity data from the SHT21. +//! +//! \param psInst is a pointer to the SHT21 instance data +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the SHT21 data registers. The user must +//! first initiate a measurement by using the SHT21Write() function configured +//! to write the command for a humidity or temperature measurement. In the +//! case of a measurement with I2C bus hold, this function is not needed. When +//! the read has completed (as indicated by callback function), the new +//! readings can be obtained via: +//! +//! - SHT21DataTemperatureGetRaw() +//! - SHT21DataTemperatureGetFloat() +//! - SHT21DataHumidityGetRaw() +//! - SHT21DataHumidityGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +SHT21DataRead(tSHT21 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the SHT21 driver is not idle (in other words, there + // is already an outstanding request to the SHT21). + // + if(psInst->ui8State != SHT21_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = SHT21_STATE_READ_DATA; + + // + // Read the data registers from the SHT21. + // + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, 0, 0, psInst->pui8Data, 2, + SHT21Callback, psInst) == 0) + { + psInst->ui8State = SHT21_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Returns the raw temperature measurement as received from the SHT21. +//! +//! \param psInst is a pointer to the SHT21 instance data. +//! \param pui16Temperature is a pointer to the value into which the raw +//! temperature data is stored. +//! +//! This function returns the raw temperature data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +SHT21DataTemperatureGetRaw(tSHT21 *psInst, uint16_t *pui16Temperature) +{ + // + // Return the raw temperature value. + // + *pui16Temperature = ((((uint16_t)psInst->pui8Data[0]) << 8) | + (uint16_t)psInst->pui8Data[1]); +} + +//***************************************************************************** +// +//! Returns the most recent temperature measurement in floating point degrees +//! Celsius. +//! +//! \param psInst is a pointer to the SHT21 instance data. +//! \param pfTemperature is a pointer to the value into which the temperature +//! data is stored. +//! +//! This function converts the raw temperature measurement data into floating +//! point degrees Celsius and returns the result. See the SHT21 datasheet +//! section 6.2 for more information about the conversion formula used. +//! +//! \return None. +// +//***************************************************************************** +void +SHT21DataTemperatureGetFloat(tSHT21 *psInst, float *pfTemperature) +{ + uint16_t ui16TemperatureRaw; + + // + // Get the raw temperature into a floating point variable + // + SHT21DataTemperatureGetRaw(psInst, &ui16TemperatureRaw); + *pfTemperature = (float)(ui16TemperatureRaw & 0xFFFC); + + // + // Equation from SHT21 datasheet for raw to Celsius conversion. + // + *pfTemperature = -46.85 + 175.72 * (*pfTemperature / 65536.0); +} + +//***************************************************************************** +// +//! Returns the raw humidity measurement from the SHT21. +//! +//! \param psInst is a pointer to the SHT21 instance data. +//! \param pui16Humidity is a pointer to the value into which the raw humidity +//! data is stored. +//! +//! This function returns the raw humidity data from the most recent data read. +//! The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +SHT21DataHumidityGetRaw(tSHT21 *psInst, uint16_t *pui16Humidity) +{ + // + // Return the raw humidity value. + // + *pui16Humidity = ((((uint16_t)psInst->pui8Data[0]) << 8) | + (uint16_t)psInst->pui8Data[1]); +} + +//***************************************************************************** +// +//! Returns the relative humidity measurement as a floating point percentage. +//! +//! \param psInst pointer to the SHT21 instance data. +//! \param pfHumidity is a pointer to the value into which the humidity data +//! is stored. +//! +//! This function converts the raw humidity measurement to +//! floating-point-percentage relative humidity over water. For more +//! information on the conversion algorithm see the SHT21 datasheet section +//! 6.1. +//! +//! \return None. +// +//***************************************************************************** +void +SHT21DataHumidityGetFloat(tSHT21 *psInst, float *pfHumidity) +{ + uint16_t ui16HumidityRaw; + + // + // Convert the raw measure to float for later math. + // + SHT21DataHumidityGetRaw(psInst, &ui16HumidityRaw); + *pfHumidity = (float)(ui16HumidityRaw & 0xFFFC); + + // + // Convert from raw measurement to percent relative humidity over water + // per the datasheet formula. + // + *pfHumidity = -6.0 + 125.0 * (*pfHumidity / 65536.0); + + // + // Convert to a number from 0 to 1.0 instead of 0 to 100%. + // + *pfHumidity /= 100.0; +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/sht21.h b/sensorlib/sht21.h new file mode 100644 index 0000000..7956b0e --- /dev/null +++ b/sensorlib/sht21.h @@ -0,0 +1,156 @@ +//***************************************************************************** +// +// sht21.h - Prototypes for the SHT21 accelerometer driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_SHT21_H__ +#define __SENSORLIB_SHT21_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the SHT21 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the SHT21. + // + tI2CMInstance *psI2CInst; + + // + // the I2C address of the SHT21. + // + uint8_t ui8Addr; + + // + // the state of the state machine used while accessing the + // SHT21. + // + uint8_t ui8State; + + // + // the data buffer used for sending/receiving data to/from the + // SHT21. + // + uint8_t pui8Data[5]; + + // + // the 16 bit raw temperature reading + // + uint16_t ui16Temperature; + + // + // the 16 bit raw humidity reading + // + uint16_t ui16Humidity; + + // + // the function that is called when the current request has + // completed processing. + // + tSensorCallback *pfnCallback; + + // + // the callback data provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The write state used to write register values. + // + tI2CMWrite8 sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState; + } + uCommand; +} +tSHT21; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t SHT21Init(tSHT21 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t SHT21Read(tSHT21 *psInst, uint_fast8_t ui8Reg, + uint8_t *pui8Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t SHT21Write(tSHT21 *psInst, uint_fast8_t ui8Reg, + const uint8_t *pui8Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t SHT21ReadModifyWrite(tSHT21 *psInst, uint_fast8_t ui8Reg, + uint_fast8_t ui8Mask, + uint_fast8_t ui8Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t SHT21DataRead(tSHT21 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void SHT21DataTemperatureGetRaw(tSHT21 *psInst, + uint16_t *pui16Temperature); +extern void SHT21DataTemperatureGetFloat(tSHT21 *psInst, float *pfTemperature); +extern void SHT21DataHumidityGetRaw(tSHT21 *psInst, uint16_t *pui16Humidity); +extern void SHT21DataHumidityGetFloat(tSHT21 *psInst, float *pfHumidity); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_SHT21_H__ diff --git a/sensorlib/tmp006.c b/sensorlib/tmp006.c new file mode 100644 index 0000000..e29900a --- /dev/null +++ b/sensorlib/tmp006.c @@ -0,0 +1,606 @@ +//***************************************************************************** +// +// tmp006.c - Driver for the TI TMP006 Temperature Sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include +#include "sensorlib/hw_tmp006.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/tmp006.h" + +//***************************************************************************** +// +//! \addtogroup tmp006_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the TMP006 state machine. +// +//***************************************************************************** +#define TMP006_STATE_IDLE 0 +#define TMP006_STATE_INIT 1 +#define TMP006_STATE_READ 2 +#define TMP006_STATE_WRITE 3 +#define TMP006_STATE_RMW 4 +#define TMP006_STATE_READ_AMB 5 +#define TMP006_STATE_READ_OBJ 6 + +//***************************************************************************** +// +// The constants used to calculate object temperature. +// +//***************************************************************************** +#define T_REF 298.15 +#define A1 1.75e-03 +#define A2 -1.678e-05 +#define B0 -2.94e-05 +#define B1 -5.70e-07 +#define B2 4.63e-09 +#define C2 13.4 + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the TMP006 +// have completed. +// +//***************************************************************************** +static void +TMP006Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tTMP006 *psInst; + + // + // Convert the instance data into a pointer to a tTMP006 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = TMP006_STATE_IDLE; + } + + // + // Determine the current state of the TMP006 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case TMP006_STATE_INIT: + case TMP006_STATE_READ: + case TMP006_STATE_WRITE: + case TMP006_STATE_RMW: + case TMP006_STATE_READ_OBJ: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = TMP006_STATE_IDLE; + + // + // Done. + // + break; + } + + // + // The ambient temperature was just read. + // + case TMP006_STATE_READ_AMB: + { + // + // Move to the read object temperature state. + // + psInst->ui8State = TMP006_STATE_READ_OBJ; + + // + // Start a read of the object temperature now that this read is + // complete. + // + psInst->uCommand.pui8Buffer[0] = TMP006_O_VOBJECT; + I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data + 2, 2, + TMP006Callback, psInst); + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == TMP006_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the TMP006 driver. +//! +//! \param psInst is a pointer to the TMP006 instance data. +//! \param psI2CInst is a pointer to the I2C driver instance data. +//! \param ui8I2CAddr is the I2C address of the TMP006 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the TMP006 driver, preparing it for operation, +//! and initiates a reset of the TMP006 device, clearing any previous +//! configuration data. +//! +//! \return Returns 1 if the TMP006 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +TMP006Init(tTMP006 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Initialize the TMP006 instance structure + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = TMP006_STATE_INIT; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Set the calibration factor to a reasonable estimate, applications + // should perform a calibration in their environment and directly overwrite + // this value after calling TMP006Init with the system specific value. + // + psInst->fCalibrationFactor = 6.40e-14; + + // + // Load the data buffer to write the reset sequence + // + psInst->pui8Data[0] = TMP006_O_CONFIG; + psInst->pui8Data[1] = (uint8_t)(TMP006_CONFIG_RESET_ASSERT >> 8); + psInst->pui8Data[2] = (uint8_t)(TMP006_CONFIG_RESET_ASSERT & 0x00FF); + + // + // Write the reset bit and issue a callback when finished. + // + if(I2CMWrite(psInst->psI2CInst, ui8I2CAddr, psInst->pui8Data, 3, + TMP006Callback, psInst) == 0) + { + // + // I2CMWrite failed so reset TMP006 state and return zero to indicate + // failure. + // + psInst->ui8State = TMP006_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from TMP006 registers. +//! +//! \param psInst is a pointer to the TMP006 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui16Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count the number of register values to read. +//! \param pfnCallback is the function to be called when data read is complete +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the TMP006. +//! +//! \note The TMP006 does not auto-increment the register pointer, so reads of +//! more than one value returns garbage for the subsequent values. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +TMP006Read(tTMP006 *psInst, uint_fast8_t ui8Reg, uint16_t *pui16Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the TMP006 driver is not idle (in other words, there + // is already an outstanding request to the TMP006). + // + if(psInst->ui8State != TMP006_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = TMP006_STATE_READ; + + // + // Read the requested registers from the TMP006. + // + if(I2CMRead16BE(&(psInst->uCommand.sReadState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, + TMP006Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = TMP006_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to TMP006 registers. +//! +//! \param psInst is a pointer to the TMP006 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui16Data is a pointer to the 16-bit register data to write. +//! \param ui16Count is the number of 16-bit registers to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the TMP006. The first value in the \e pui16Data buffer contains the data +//! to be written into the \e ui8Reg register, the second value contains the +//! data to be written into the next register, and so on. +//! +//! \note The TMP006 does not auto-increment the register pointer, so writes of +//! more than one register are rejected by the TMP006. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +TMP006Write(tTMP006 *psInst, uint_fast8_t ui8Reg, const uint16_t *pui16Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the TMP006 driver is not idle (in other words, there + // is already an outstanding request to the TMP006). + // + if(psInst->ui8State != TMP006_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = TMP006_STATE_WRITE; + + // + // Write the requested registers to the TMP006. + // + if(I2CMWrite16BE(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, + TMP006Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = TMP006_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a TMP006 register. +//! +//! \param psInst is a pointer to the TMP006 instance data. +//! \param ui8Reg is the register offset to read modify and write +//! \param ui16Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui16Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the TMP006 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui16Mask, ORed with \e ui16Value, and then written back to the +//! TMP006. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +TMP006ReadModifyWrite(tTMP006 *psInst, uint_fast8_t ui8Reg, + uint_fast16_t ui16Mask, uint_fast16_t ui16Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the TMP006 driver is not idle (in other words, there + // is already an outstanding request to the TMP006). + // + if(psInst->ui8State != TMP006_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = TMP006_STATE_RMW; + + // + // Submit the read-modify-write request to the TMP006. + // + if(I2CMReadModifyWrite16BE(&(psInst->uCommand.sReadModifyWriteState), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui16Mask, ui16Value, TMP006Callback, + psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = TMP006_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the temperature data from the TMP006. +//! +//! \param psInst is a pointer to the TMP006 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the TMP006 data registers. When the read +//! has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - TMP006DataTemperatureGetRaw() +//! - TMP006DataTemperatureGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +TMP006DataRead(tTMP006 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the TMP006 driver is not idle (in other words, there + // is already an outstanding request to the TMP006). + // + if(psInst->ui8State != TMP006_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for ambient data read state. + // + psInst->ui8State = TMP006_STATE_READ_AMB; + + // + // Read the ambient temperature data from the TMP006. + // + psInst->uCommand.pui8Buffer[0] = TMP006_O_TAMBIENT; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 2, + TMP006Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = TMP006_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the TMP006 instance data. +//! \param pi16Ambient is a pointer to the value into which the raw ambient +//! temperature data is stored. +//! \param pi16Object is a pointer to the value into which the raw object +//! temperature data is stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +TMP006DataTemperatureGetRaw(tTMP006 *psInst, int16_t *pi16Ambient, + int16_t *pi16Object) +{ + // + // Return the raw temperature value. + // + *pi16Ambient = ((int16_t)psInst->pui8Data[0] << 8) | psInst->pui8Data[1]; + *pi16Object = ((int16_t)psInst->pui8Data[2] << 8) | psInst->pui8Data[3]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the TMP006 instance data. +//! \param pfAmbient is a pointer to the value into which the ambient +//! temperature data is stored as floating point degrees Celsius. +//! \param pfObject is a pointer to the value into which the object temperature +//! data is stored as floating point degrees Celsius. +//! +//! This function returns the temperature data from the most recent data read, +//! converted into Celsius. +//! +//! \return None. +// +//***************************************************************************** +void +TMP006DataTemperatureGetFloat(tTMP006 *psInst, float *pfAmbient, + float *pfObject) +{ + float fTdie2, fS, fVo, fVx, fObj; + int16_t i16Ambient; + int16_t i16Object; + + // + // Get the raw readings. + // + TMP006DataTemperatureGetRaw(psInst, &i16Ambient, &i16Object); + + // + // The bottom two bits are not temperature data, so discard them but keep + // the sign information. + // + *pfAmbient = (float)(i16Ambient / 4); + + // + // Divide by 32 to get unit scaling correct. + // + *pfAmbient = *pfAmbient / 32.0; + + // + // fTdie2 is measured ambient temperature in degrees Kelvin. + // + fTdie2 = *pfAmbient + T_REF; + + // + // S is the sensitivity. + // + fS = psInst->fCalibrationFactor * (1.0f + (A1 * (*pfAmbient)) + + (A2 * ((*pfAmbient) * (*pfAmbient)))); + + // + // Vos is the offset voltage. + // + fVo = B0 + (B1 * (*pfAmbient)) + (B2 * ((*pfAmbient) * (*pfAmbient))); + + // + // Vx is the difference between raw object voltage and Vos + // 156.25e-9 is nanovolts per least significant bit from the voltage + // register. + // + fVx = (((float) i16Object) * 156.25e-9) - fVo; + + // + // fObj is the feedback coefficient. + // + fObj = fVx + C2 * (fVx * fVx); + + // + // Finally calculate the object temperature. + // + *pfObject = (sqrtf(sqrtf((fTdie2 * fTdie2 * fTdie2 * fTdie2) + + (fObj / fS))) - T_REF); +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/tmp006.h b/sensorlib/tmp006.h new file mode 100644 index 0000000..e22e410 --- /dev/null +++ b/sensorlib/tmp006.h @@ -0,0 +1,157 @@ +//***************************************************************************** +// +// tmp006.h - Prototypes for the Texas Instruments TMP006 temperature sensor +// driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_TMP006_H__ +#define __SENSORLIB_TMP006_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the TMP006 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the TMP006. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the TMP006. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the TMP006. + // + uint8_t ui8State; + + // + // The data buffer used for sending/receiving data to/from the TMP006. + // + uint8_t pui8Data[4]; + + // + // Calibration factor. Left to application to implement calibration + // See term S0 in http://www.ti.com/lit/ug/sbou107/sbou107.pdf + // + float fCalibrationFactor; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The read state used to read register values. + // + tI2CMRead16BE sReadState; + + // + // The write state used to write register values. + // + tI2CMWrite16BE sWriteState; + + // + // The read-modify-write state used to modify register values. + // + tI2CMReadModifyWrite16 sReadModifyWriteState; + } + uCommand; +} +tTMP006; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t TMP006Init(tTMP006 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t TMP006Read(tTMP006 *psInst, uint_fast8_t ui8Reg, + uint16_t *pui16Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t TMP006Write(tTMP006 *psInst, uint_fast8_t ui8Reg, + const uint16_t *pui16Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t TMP006ReadModifyWrite(tTMP006 *psInst, uint_fast8_t ui8Reg, + uint_fast16_t ui16Mask, + uint_fast16_t ui16Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t TMP006DataRead(tTMP006 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void TMP006DataTemperatureGetRaw(tTMP006 *psInst, int16_t *pui16Ambient, + int16_t *pui16Object); +extern void TMP006DataTemperatureGetFloat(tTMP006 *psInst, float *pfAmbient, + float *pfObject); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_TMP006_H__ + diff --git a/sensorlib/tmp100.c b/sensorlib/tmp100.c new file mode 100644 index 0000000..d4cc3a8 --- /dev/null +++ b/sensorlib/tmp100.c @@ -0,0 +1,582 @@ +//***************************************************************************** +// +// tmp100.c - Driver for the TI TMP100 Temperature Sensor +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include +#include +#include "sensorlib/hw_tmp100.h" +#include "sensorlib/i2cm_drv.h" +#include "sensorlib/tmp100.h" + +//***************************************************************************** +// +//! \addtogroup tmp100_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +// The states of the TMP100 state machine. +// +//***************************************************************************** +#define TMP100_STATE_IDLE 0 +#define TMP100_STATE_INIT 1 +#define TMP100_STATE_READ 2 +#define TMP100_STATE_WRITE 3 +#define TMP100_STATE_RMW 4 + +//***************************************************************************** +// +// The callback function that is called when I2C transations to/from the TMP100 +// have completed. +// +//***************************************************************************** +static void +TMP100Callback(void *pvCallbackData, uint_fast8_t ui8Status) +{ + tTMP100 *psInst; + + // + // Convert the instance data into a pointer to a tTMP100 structure. + // + psInst = pvCallbackData; + + // + // If the I2C master driver encountered a failure, force the state machine + // to the idle state (which will also result in a callback to propagate the + // error). + // + if(ui8Status != I2CM_STATUS_SUCCESS) + { + psInst->ui8State = TMP100_STATE_IDLE; + } + + // + // Determine the current state of the TMP100 state machine. + // + switch(psInst->ui8State) + { + // + // All states that trivially transition to IDLE, and all unknown + // states. + // + case TMP100_STATE_INIT: + case TMP100_STATE_READ: + case TMP100_STATE_WRITE: + case TMP100_STATE_RMW: + default: + { + // + // The state machine is now idle. + // + psInst->ui8State = TMP100_STATE_IDLE; + + // + // Done. + // + break; + } + } + + // + // See if the state machine is now idle and there is a callback function. + // + if((psInst->ui8State == TMP100_STATE_IDLE) && psInst->pfnCallback) + { + // + // Call the application-supplied callback function. + // + psInst->pfnCallback(psInst->pvCallbackData, ui8Status); + } +} + +//***************************************************************************** +// +//! Initializes the TMP100 driver. +//! +//! \param psInst is a pointer to the TMP100 instance data. +//! \param psI2CInst is a pointer to the I2C driver instance data. +//! \param ui8I2CAddr is the I2C address of the TMP100 device. +//! \param pfnCallback is the function to be called when the initialization has +//! completed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initializes the TMP100 driver, preparing it for operation, +//! and initiates a reset of the TMP100 device, clearing any previous +//! configuration data. +//! +//! \return Returns 1 if the TMP100 driver was successfully initialized and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +TMP100Init(tTMP100 *psInst, tI2CMInstance *psI2CInst, uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Initialize the TMP100 instance structure + // + psInst->psI2CInst = psI2CInst; + psInst->ui8Addr = ui8I2CAddr; + psInst->ui8State = TMP100_STATE_INIT; + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Write the configuration register to its default value. + // + psInst->pui8Data[0] = TMP100_O_CONFIG; + psInst->pui8Data[1] = 0x00; + + // + // Write the reset bit and issue a callback when finished. + // + if(I2CMWrite(psInst->psI2CInst, ui8I2CAddr, psInst->pui8Data, 2, + TMP100Callback, psInst) == 0) + { + // + // I2CMWrite failed so reset TMP100 state and return zero to indicate + // failure. + // + psInst->ui8State = TMP100_STATE_IDLE; + return(0); + } + + // + // Success + // + return(1); +} + +//***************************************************************************** +// +//! Reads data from TMP100 registers. +//! +//! \param psInst is a pointer to the TMP100 instance data. +//! \param ui8Reg is the first register to read. +//! \param pui16Data is a pointer to the location to store the data that is +//! read. +//! \param ui16Count the number of register values to read. +//! \param pfnCallback is the function to be called when data read is complete +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function reads a sequence of data values from consecutive registers in +//! the TMP100. +//! +//! \note The TMP100 does not auto-increment the register pointer, so reads of +//! more than one value returns garbage for the subsequent values. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +TMP100Read(tTMP100 *psInst, uint_fast8_t ui8Reg, uint16_t *pui16Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the TMP100 driver is not idle (in other words, there + // is already an outstanding request to the TMP100). + // + if(psInst->ui8State != TMP100_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read state. + // + psInst->ui8State = TMP100_STATE_READ; + + // + // Read the requested registers from the TMP100. + // + if(ui8Reg == TMP100_O_CONFIG) + { + // + // The configuration register is only one byte, so only a single byte + // read is necessary and no endian swapping is required. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, (uint8_t *)pui16Data, 1, + TMP100Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = TMP100_STATE_IDLE; + return(0); + } + } + else + { + // + // This is one of the temperature registers, which are 16-bit + // big-endian registers. + // + if(I2CMRead16BE(&(psInst->uCommand.sReadState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, + TMP100Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = TMP100_STATE_IDLE; + return(0); + } + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Writes data to TMP100 registers. +//! +//! \param psInst is a pointer to the TMP100 instance data. +//! \param ui8Reg is the first register to write. +//! \param pui16Data is a pointer to the 16-bit register data to write. +//! \param ui16Count is the number of 16-bit registers to write. +//! \param pfnCallback is the function to be called when the data has been +//! written (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function writes a sequence of data values to consecutive registers in +//! the TMP100. The first value in the \e pui16Data buffer contains the data +//! to be written into the \e ui8Reg register, the second value contains the +//! data to be written into the next register, and so on. +//! +//! \note The TMP100 does not auto-increment the register pointer, so writes of +//! more than one register are rejected by the TMP100. +//! +//! \return Returns 1 if the write was successfully started and 0 if it was +//! not. +// +//***************************************************************************** +uint_fast8_t +TMP100Write(tTMP100 *psInst, uint_fast8_t ui8Reg, const uint16_t *pui16Data, + uint_fast16_t ui16Count, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the TMP100 driver is not idle (in other words, there + // is already an outstanding request to the TMP100). + // + if(psInst->ui8State != TMP100_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for write state. + // + psInst->ui8State = TMP100_STATE_WRITE; + + // + // Write the requested registers to the TMP100. + // + if(ui8Reg == TMP100_O_CONFIG) + { + // + // The configuration register is only one byte, so only a single byte + // write is necessary and no endian swapping is required. + // + psInst->uCommand.pui8Buffer[0] = ui8Reg; + psInst->uCommand.pui8Buffer[1] = *pui16Data & 0xff; + if(I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 2, TMP100Callback, + psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = TMP100_STATE_IDLE; + return(0); + } + } + else + { + // + // This is one of the temperature registers, which are 16-bit + // big-endian registers. + // + if(I2CMWrite16BE(&(psInst->uCommand.sWriteState), psInst->psI2CInst, + psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, + TMP100Callback, psInst) == 0) + { + // + // The I2C write failed, so move to the idle state and return a + // failure. + // + psInst->ui8State = TMP100_STATE_IDLE; + return(0); + } + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Performs a read-modify-write of a TMP100 register. +//! +//! \param psInst is a pointer to the TMP100 instance data. +//! \param ui8Reg is the register offset to read modify and write +//! \param ui16Mask is the bit mask that is ANDed with the current register +//! value. +//! \param ui16Value is the bit mask that is ORed with the result of the AND +//! operation. +//! \param pfnCallback is the function to be called when the data has been +//! changed (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function changes the value of a register in the TMP100 via a +//! read-modify-write operation, allowing one of the fields to be changed +//! without disturbing the other fields. The \e ui8Reg register is read, ANDed +//! with \e ui16Mask, ORed with \e ui16Value, and then written back to the +//! TMP100. +//! +//! \return Returns 1 if the read-modify-write was successfully started and 0 +//! if it was not. +// +//***************************************************************************** +uint_fast8_t +TMP100ReadModifyWrite(tTMP100 *psInst, uint_fast8_t ui8Reg, + uint_fast16_t ui16Mask, uint_fast16_t ui16Value, + tSensorCallback *pfnCallback, void *pvCallbackData) +{ + // + // Return a failure if the TMP100 driver is not idle (in other words, there + // is already an outstanding request to the TMP100). + // + if(psInst->ui8State != TMP100_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for read-modify-write state. + // + psInst->ui8State = TMP100_STATE_RMW; + + // + // Submit the read-modify-write request to the TMP100. + // + if(ui8Reg == TMP100_O_CONFIG) + { + // + // The configuration register is only one byte, so only a single byte + // read-modify-write is necessary and no endian swapping is required. + // + if(I2CMReadModifyWrite8(&(psInst->uCommand.sReadModifyWriteState8), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui16Mask & 0xff, ui16Value & 0xff, + TMP100Callback, psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = TMP100_STATE_IDLE; + return(0); + } + } + else + { + // + // This is one of the temperature registers, which are 16-bit + // big-endian registers. + // + if(I2CMReadModifyWrite16BE(&(psInst->uCommand.sReadModifyWriteState16), + psInst->psI2CInst, psInst->ui8Addr, ui8Reg, + ui16Mask, ui16Value, TMP100Callback, + psInst) == 0) + { + // + // The I2C read-modify-write failed, so move to the idle state and + // return a failure. + // + psInst->ui8State = TMP100_STATE_IDLE; + return(0); + } + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Reads the temperature data from the TMP100. +//! +//! \param psInst is a pointer to the TMP100 instance data. +//! \param pfnCallback is the function to be called when the data has been read +//! (can be \b NULL if a callback is not required). +//! \param pvCallbackData is a pointer that is passed to the callback function. +//! +//! This function initiates a read of the TMP100 data registers. When the read +//! has completed (as indicated by calling the callback function), the new +//! readings can be obtained via: +//! +//! - TMP100DataTemperatureGetRaw() +//! - TMP100DataTemperatureGetFloat() +//! +//! \return Returns 1 if the read was successfully started and 0 if it was not. +// +//***************************************************************************** +uint_fast8_t +TMP100DataRead(tTMP100 *psInst, tSensorCallback *pfnCallback, + void *pvCallbackData) +{ + // + // Return a failure if the TMP100 driver is not idle (in other words, there + // is already an outstanding request to the TMP100). + // + if(psInst->ui8State != TMP100_STATE_IDLE) + { + return(0); + } + + // + // Save the callback information. + // + psInst->pfnCallback = pfnCallback; + psInst->pvCallbackData = pvCallbackData; + + // + // Move the state machine to the wait for data read state. + // + psInst->ui8State = TMP100_STATE_READ; + + // + // Read the temperature data from the TMP100. + // + psInst->uCommand.pui8Buffer[0] = TMP100_O_TEMP; + if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, + psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 2, + TMP100Callback, psInst) == 0) + { + // + // The I2C read failed, so move to the idle state and return a failure. + // + psInst->ui8State = TMP100_STATE_IDLE; + return(0); + } + + // + // Success. + // + return(1); +} + +//***************************************************************************** +// +//! Gets the raw measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the TMP100 instance data. +//! \param pi16Temperature is a pointer to the value into which the raw +//! temperature data is stored. +//! +//! This function returns the raw measurement data from the most recent data +//! read. The data is not manipulated in any way by the driver. +//! +//! \return None. +// +//***************************************************************************** +void +TMP100DataTemperatureGetRaw(tTMP100 *psInst, int16_t *pi16Temperature) +{ + // + // Return the raw temperature value. + // + *pi16Temperature = + ((int16_t)psInst->pui8Data[0] << 8) | psInst->pui8Data[1]; +} + +//***************************************************************************** +// +//! Gets the measurement data from the most recent data read. +//! +//! \param psInst is a pointer to the TMP100 instance data. +//! \param pfTemperature is a pointer to the value into which the temperature +//! data is stored as floating point degrees Celsius. +//! +//! This function returns the temperature data from the most recent data read, +//! converted into Celsius. +//! +//! \return None. +// +//***************************************************************************** +void +TMP100DataTemperatureGetFloat(tTMP100 *psInst, float *pfTemperature) +{ + // + // Convert the temperature reading into Celcius. + // + *pfTemperature = ((float)(((int16_t)psInst->pui8Data[0] << 8) | + psInst->pui8Data[1]) / 256.0); +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/tmp100.h b/sensorlib/tmp100.h new file mode 100644 index 0000000..bbb923c --- /dev/null +++ b/sensorlib/tmp100.h @@ -0,0 +1,156 @@ +//***************************************************************************** +// +// tmp100.h - Prototypes for the Texas Instruments TMP100 temperature sensor +// driver. +// +// Copyright (c) 2013-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_TMP100_H__ +#define __SENSORLIB_TMP100_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// The structure that defines the internal state of the TMP100 driver. +// +//***************************************************************************** +typedef struct +{ + // + // The pointer to the I2C master interface instance used to communicate + // with the TMP100. + // + tI2CMInstance *psI2CInst; + + // + // The I2C address of the TMP100. + // + uint8_t ui8Addr; + + // + // The state of the state machine used while accessing the TMP100. + // + uint8_t ui8State; + + // + // The data buffer used for sending/receiving data to/from the TMP100. + // + uint8_t pui8Data[4]; + + // + // The function that is called when the current request has completed + // processing. + // + tSensorCallback *pfnCallback; + + // + // The pointer provided to the callback function. + // + void *pvCallbackData; + + // + // A union of structures that are used for read, write and + // read-modify-write operations. Since only one operation can be active at + // a time, it is safe to re-use the memory in this manner. + // + union + { + // + // A buffer used to store the write portion of a register read. + // + uint8_t pui8Buffer[2]; + + // + // The read state used to read register values. + // + tI2CMRead16BE sReadState; + + // + // The write state used to write register values. + // + tI2CMWrite16BE sWriteState; + + // + // The read-modify-write state used to modify 8-bit register values. + // + tI2CMReadModifyWrite8 sReadModifyWriteState8; + + // + // The read-modify-write state used to modify 16-bit register values. + // + tI2CMReadModifyWrite16 sReadModifyWriteState16; + } + uCommand; +} +tTMP100; + +//***************************************************************************** +// +// Function prototypes. +// +//***************************************************************************** +extern uint_fast8_t TMP100Init(tTMP100 *psInst, tI2CMInstance *psI2CInst, + uint_fast8_t ui8I2CAddr, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t TMP100Read(tTMP100 *psInst, uint_fast8_t ui8Reg, + uint16_t *pui16Data, uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t TMP100Write(tTMP100 *psInst, uint_fast8_t ui8Reg, + const uint16_t *pui16Data, + uint_fast16_t ui16Count, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t TMP100ReadModifyWrite(tTMP100 *psInst, uint_fast8_t ui8Reg, + uint_fast16_t ui16Mask, + uint_fast16_t ui16Value, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern uint_fast8_t TMP100DataRead(tTMP100 *psInst, + tSensorCallback *pfnCallback, + void *pvCallbackData); +extern void TMP100DataTemperatureGetRaw(tTMP100 *psInst, + int16_t *pui16Temperature); +extern void TMP100DataTemperatureGetFloat(tTMP100 *psInst, + float *pfTemperature); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_TMP100_H__ + diff --git a/sensorlib/vector.c b/sensorlib/vector.c new file mode 100644 index 0000000..208b671 --- /dev/null +++ b/sensorlib/vector.c @@ -0,0 +1,139 @@ +//***************************************************************************** +// +// vector.c - Functions for performing vector operations. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#include "sensorlib/vector.h" + +//***************************************************************************** +// +//! \addtogroup vector_api +//! @{ +// +//***************************************************************************** + +//***************************************************************************** +// +//! Computes the dot product of two vectors. +//! +//! \param pfVectorIn1 is the first vector. +//! \param pfVectorIn2 is the second vector. +//! +//! This function computes the dot product of two 3-dimensional vector. +//! +//! \return Returns the dot product of the two vectors. +// +//***************************************************************************** +float +VectorDotProduct(float pfVectorIn1[3], float pfVectorIn2[3]) +{ + // + // Compute and return the vector dot product. + // + return((pfVectorIn1[0] * pfVectorIn2[0]) + + (pfVectorIn1[1] * pfVectorIn2[1]) + + (pfVectorIn1[2] * pfVectorIn2[2])); +} + +//***************************************************************************** +// +//! Computes the cross product of two vectors. +//! +//! \param pfVectorOut is the output vector. +//! \param pfVectorIn1 is the first vector. +//! \param pfVectorIn2 is the second vector. +//! +//! This function computes the cross product of two 3-dimensional vectors. +//! +//! \return None. +// +//***************************************************************************** +void +VectorCrossProduct(float pfVectorOut[3], float pfVectorIn1[3], + float pfVectorIn2[3]) +{ + // + // Compute the cross product of the input vectors. + // + pfVectorOut[0] = ((pfVectorIn1[1] * pfVectorIn2[2]) - + (pfVectorIn1[2] * pfVectorIn2[1])); + pfVectorOut[1] = ((pfVectorIn1[2] * pfVectorIn2[0]) - + (pfVectorIn1[0] * pfVectorIn2[2])); + pfVectorOut[2] = ((pfVectorIn1[0] * pfVectorIn2[1]) - + (pfVectorIn1[1] * pfVectorIn2[0])); +} + +//***************************************************************************** +// +//! Scales a vector. +//! +//! \param pfVectorOut is the output vector. +//! \param pfVectorIn is the input vector. +//! \param fScale is the scale factor. +//! +//! This function scales a 3-dimensional vector by multiplying each of its +//! components by the scale factor. +//! +//! \return None. +// +//***************************************************************************** +void +VectorScale(float pfVectorOut[3], float pfVectorIn[3], float fScale) +{ + // + // Scale each component of the vector by the scale factor. + // + pfVectorOut[0] = pfVectorIn[0] * fScale; + pfVectorOut[1] = pfVectorIn[1] * fScale; + pfVectorOut[2] = pfVectorIn[2] * fScale; +} + +//***************************************************************************** +// +//! Adds two vectors. +//! +//! \param pfVectorOut is the output vector. +//! \param pfVectorIn1 is the first vector. +//! \param pfVectorIn2 is the second vector. +//! +//! This function adds two 3-dimensional vectors. +//! +//! \return None. +// +//***************************************************************************** +void +VectorAdd(float pfVectorOut[3], float pfVectorIn1[3], float pfVectorIn2[3]) +{ + // + // Add the components of the two vectors. + // + pfVectorOut[0] = pfVectorIn1[0] + pfVectorIn2[0]; + pfVectorOut[1] = pfVectorIn1[1] + pfVectorIn2[1]; + pfVectorOut[2] = pfVectorIn1[2] + pfVectorIn2[2]; +} + +//***************************************************************************** +// +// Close the Doxygen group. +//! @} +// +//***************************************************************************** diff --git a/sensorlib/vector.h b/sensorlib/vector.h new file mode 100644 index 0000000..d18b1e2 --- /dev/null +++ b/sensorlib/vector.h @@ -0,0 +1,61 @@ +//***************************************************************************** +// +// vector.h - Prototypes for the vector functions. +// +// Copyright (c) 2012-2014 Texas Instruments Incorporated. All rights reserved. +// Software License Agreement +// +// Texas Instruments (TI) is supplying this software for use solely and +// exclusively on TI's microcontroller products. The software is owned by +// TI and/or its suppliers, and is protected under applicable copyright +// laws. You may not combine this software with "viral" open-source +// software in order to form a larger program. +// +// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. +// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT +// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY +// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL +// DAMAGES, FOR ANY REASON WHATSOEVER. +// +// This is part of revision 2.1.0.12573 of the Tiva Firmware Development Package. +// +//***************************************************************************** + +#ifndef __SENSORLIB_VECTOR_H__ +#define __SENSORLIB_VECTOR_H__ + +//***************************************************************************** +// +// If building with a C++ compiler, make all of the definitions in this header +// have a C binding. +// +//***************************************************************************** +#ifdef __cplusplus +extern "C" +{ +#endif + +//***************************************************************************** +// +// Prototypes. +// +//***************************************************************************** +extern float VectorDotProduct(float pfVectorIn1[3], float pfVectorIn2[3]); +extern void VectorCrossProduct(float pfVectorOut[3], float pfVectorIn1[3], + float pfVectorIn2[3]); +extern void VectorScale(float pfVectorOut[3], float pfVectorIn[3], + float fScale); +extern void VectorAdd(float pfVectorOut[3], float pfVectorIn1[3], + float pfVectorIn2[3]); + +//***************************************************************************** +// +// Mark the end of the C bindings section for C++ compilers. +// +//***************************************************************************** +#ifdef __cplusplus +} +#endif + +#endif // __SENSORLIB_VECTOR_H__ -- cgit v1.3.1