Device driver for the Freescale MMA845x family of accelerometers.

Dependents:   MMA845x_test KL05_accel-test

Work in Progress

Files at this revision

API Documentation at this revision

Comitter:
sam_grove
Date:
Fri Mar 29 21:51:11 2013 +0000
Commit message:
Work in progress

Changed in this revision

MMA845x.cpp Show annotated file Show diff for this revision Revisions of this file
MMA845x.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 9d1e3a344e4f MMA845x.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMA845x.cpp	Fri Mar 29 21:51:11 2013 +0000
@@ -0,0 +1,174 @@
+/**
+ * @file    MMA845x.cpp
+ * @brief   Device driver - MMA845X 3-axis accelerometer IC
+ * @author  sam grove
+ * @version 1.0
+ * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf
+ * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8452Q.pdf
+ * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8453Q.pdf
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#include "MMA845x.h"
+ 
+MMA845x::MMA845x(I2C &i2c, InterruptIn &int1, InterruptIn &int2, MMA845x_SA0 const i2c_addr)
+{
+    _i2c =  &i2c;
+    _int1 = &int1;
+    _int2 = &int2;
+    
+    _i2c_addr = (0x1c << 2) | (i2c_addr << 0x1);
+ 
+    return;
+}
+
+void MMA845x::init(void) const
+{
+    uint8_t reg_val = 0;
+    
+    _i2c->frequency(400000);
+    
+    // Reset all registers to POR values
+    MMA845x::writeRegister(CTRL_REG2, 0xFF);        //REG 0x2B
+    do{
+        // wait for the reset bit to clear
+        reg_val = MMA845x::readRegister(CTRL_REG2) & 0x40;
+    }while(reg_val);
+    
+    // setup the registers that are common among modes
+    MMA845x::writeRegister(CTRL_REG1, 0xd8);        //REG 0x2A
+    MMA845x::writeRegister(CTRL_REG2, 0x00);        //REG 0x2B
+    MMA845x::writeRegister(CTRL_REG3, 0x00);        //REG 0x2C
+    
+    MMA845x::writeRegister(XYZ_DATA_CFG, 0x0);      //REG 0xE HPF / scale +/-2,4,8g
+    MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x0);  //REG 0xF HPF settings
+    
+    return;
+}
+
+void MMA845x::enableDataReadyMode(void) const
+{
+    MMA845x::init();
+    MMA845x::writeRegister(SYSMOD, 0x1);        //REG 0x0B
+    MMA845x::writeRegister(INT_SOURCE, 0x1);    //REG 0x0C
+    // need to finish up these config registers..... 3/8/13
+    
+}
+
+void MMA845x::enableMotionMode(void) const{}
+void MMA845x::enablePulseMode(void) const{}
+
+void MMA845x::enableOrientationMode(void) const
+{
+    uint16_t who_am_i = MMA845x::readRegister(WHO_AM_I);
+    if(who_am_i != MMA8451)
+    {
+        error("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
+    }
+    
+    return;
+}
+
+void MMA845x::enableTransitMode(void) const{}
+void MMA845x::enableAutoSleepMode(void) const{}
+
+void MMA845x::enableFIFOMode(void) const
+{
+    uint16_t who_am_i = MMA845x::readRegister(WHO_AM_I);
+    if(who_am_i != MMA8451)
+    {
+        error("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
+    }
+    
+    //MMA845x::writeRegister(
+    
+    return;
+}
+
+uint16_t MMA845x::getX(void) const
+{
+    return _data._x;
+}
+    
+uint16_t MMA845x::getY(void) const
+{
+    return _data._y;
+}
+
+uint16_t MMA845x::getZ(void) const
+{
+    return _data._z;
+}
+    
+MMA845x_DATA MMA845x::getXYZ(void) const
+{
+    return _data;
+}
+
+void MMA845x::writeRegister(uint8_t const reg, uint8_t const data) const
+{
+    char buf[2] = {reg, data};
+    uint8_t result = 0;
+    
+    __disable_irq(); // Tickers and other timebase events can jack up the I2C bus for some deicse
+    result = _i2c->write(_i2c_addr, buf, 2);
+    __enable_irq();  // Just need to block during the transaction
+    
+    if(0 != result)
+    {
+        error("%s %d: I2c write failed\n", __FILE__, __LINE__);
+    }
+    
+    return;
+}
+
+uint8_t MMA845x::readRegister(uint8_t const reg) const
+{
+    uint8_t result = 1, data = 0;
+    
+    __disable_irq(); // Tickers and other timebase events can jack up the I2C bus
+    _i2c->start();
+    result &= _i2c->write(_i2c_addr);
+    result &= _i2c->write(reg);
+    // issue a repeated start...
+    _i2c->start();
+    result &= _i2c->write(_i2c_addr | 0x01);
+    // read with nak
+    data = _i2c->read(0);
+    _i2c->stop();
+    __enable_irq();  // Just need to block during the transaction
+    
+    if(1 != result)
+    {
+        error("%s %d: I2C read failed\n", __FILE__, __LINE__);
+    }
+    
+    return data;
+}
+
+void MMA845x::registerDump(void) const
+{
+    uint8_t reg_val = 0;
+    
+    for(int i=0; i<0x80; i++)
+    {
+        reg_val = MMA845x::readRegister(i);
+        printf("Reg 0x%02x: 0x%02x \n", i, reg_val);
+    }
+    
+    return;
+}
+
diff -r 000000000000 -r 9d1e3a344e4f MMA845x.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MMA845x.h	Fri Mar 29 21:51:11 2013 +0000
@@ -0,0 +1,221 @@
+/**
+ * @file    MMA845x.h
+ * @brief   Device driver - MMA845x 3-axis accelerometer IC
+ * @author  sam grove
+ * @version 1.0
+ * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf
+ * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8452Q.pdf
+ * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8453Q.pdf
+ *
+ * Copyright (c) 2013
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+#ifndef MMA845X_H
+#define MMA845X_H
+
+#include "mbed.h"
+
+/** Using the Sparkfun SEN-10955
+ *
+ * Example:
+ * @code
+ *  #include "mbed.h"
+ *  #include "MMA845x.h"
+ *
+
+ * 
+ *  int main() 
+ *  {
+
+ *  }
+ * @endcode
+ */
+
+
+/**
+ *  @class MMA845x_DATA
+ *  @brief API abstraction for the MMA845x 3-axis accelerometer IC data
+ */  
+class MMA845x_DATA
+{      
+public:
+    
+    volatile uint16_t _x;   /*!< volatile data variable */
+    volatile uint16_t _y;   /*!< volatile data variable */
+    volatile uint16_t _z;   /*!< volatile data variable */
+   
+    /** Create the MMA845x_DATA object initialized to the parameter (or 0 if none)
+     *  @param x - the init value of _x
+     *  @param y - the init value of _y
+     *  @param x - the init value of _z
+     */
+    MMA845x_DATA(uint16_t x = 0, uint16_t y = 0, uint16_t z = 0) : _x(x), _y(y), _z(z) {}
+    
+    /** Overloaded '=' operator to allow shorthand coding, assigning objects to one another
+     *  @param rhs - an object of the same type to assign ourself the same values of
+     *  @return this
+     */
+    MMA845x_DATA &operator= (MMA845x_DATA const &rhs)
+    {
+        _x = rhs._x;
+        _y = rhs._y;
+        _z = rhs._z;
+        
+        return *this;
+    }
+    
+    /** Overloaded '=' operator to allow shorthand coding, assigning objects to one another
+     *  @param val - Assign each data member (_x, _y, _z) this value
+     *  @return this
+     */
+    MMA845x_DATA &operator= (uint16_t const val)
+    {
+        _x = _y = _z = val;
+        
+        return *this;
+    }
+    
+    /** Overloaded '==' operator to allow shorthand coding, test objects to one another
+     *  @param rhs - the object to compare against
+     *  @return 1 if the data members are the same and 0 otherwise
+     */
+    bool operator== (MMA845x_DATA const &rhs) const
+    {
+        return ((_x == rhs._x)&&(_y == rhs._y)&&(_z == rhs._z)) ? 1 : 0;
+    }
+    
+};
+
+/**
+ *  @class MMA845x
+ *  @brief API abstraction for the MMA845x 3-axis accelerometer IC
+ */ 
+class MMA845x
+{  
+public:
+    
+    /**
+     *  @enum MMA845x_SA0
+     *  @brief Possible terminations for the ADDR pin
+     */ 
+    enum MMA845x_SA0
+    { 
+        SA0_VSS = 0, /*!< SA0 connected to VSS */
+        SA0_VDD      /*!< SA0 connected to VDD */
+    };
+    
+    /**
+     *  @enum MMA845x_WHO_AM_I
+     *  @brief Device ID's that this class is compatible with
+     */ 
+    enum MMA845x_WHO_AM_I
+    { 
+        MMA8451 = 0x1a, /*!< MMA8451 WHO_AM_I register content */
+        MMA8452 = 0x2a, /*!< MMA8452 WHO_AM_I register content */
+        MMA8453 = 0x3a, /*!< MMA8453 WHO_AM_I register content */
+    };
+    
+    /**
+     *  @enum MMA845x_REGISTER
+     *  @brief The device register map
+     */
+    enum MMA845x_REGISTER
+    {
+        STATUS = 0x0,
+        OUT_X_MSB, OUT_X_LSB, OUT_Y_MSB, OUT_Y_LSB, OUT_Z_MSB, OUT_Z_LSB,
+        
+        F_SETUP = 0x9, TRIG_CFG, // only available on the MMA8451 variant
+        
+        SYSMOD = 0xb,
+        INT_SOURCE, WHO_AM_I, XYZ_DATA_CFG, HP_FILTER_CUTOFF, PL_STATUS,
+        PL_CFG, PL_COUNT, PL_BF_ZCOMP, P_L_THS_REG, FF_MT_CFG, FF_MT_SRC,
+        FF_MT_THS, FF_MT_COUNT,
+        
+        TRANSIENT_CFG = 0x1d,
+        TRANSIENT_SRC, TRANSIENT_THS, TRANSIENT_COUNT, PULSE_CFG, PULSE_SRC,
+        PULSE_THSX, PULSE_THSY, PULSE_THSZ, PULSE_TMLT, PULSE_LTCY, PULSE_WIND,
+        ASLP_COUNT, CTRL_REG1, CTRL_REG2, CTRL_REG3, CTRL_REG4, CTRL_REG5,
+        OFF_X, OFF_Y, OFF_Z
+    };
+        
+    /** Create the MMA845x object
+     *  @param i2c - A defined I2C object
+     *  @param int1 - A defined InterruptIn object
+     *  @param int2 - A defined InterruptIn object
+     *  @param i2c_addr - Connection of the address line
+     */ 
+    MMA845x(I2C &i2c, InterruptIn &int1, InterruptIn &int2, MMA845x_SA0 const i2c_addr);
+    
+    /** Get the X data
+     *  @return The last valid reading from the accelerometer
+     */
+    uint16_t getX(void) const;
+    
+    /** Get the Y data
+     *  @return The last valid reading from the accelerometer
+     */
+    uint16_t getY(void) const;
+    
+    /** Get the Z data
+     *  @return The last valid reading from the accelerometer
+     */
+    uint16_t getZ(void) const;
+    
+    /** Get the XYZ data structure
+     *  @return The last valid reading from the accelerometer
+     */
+    MMA845x_DATA getXYZ(void) const;
+    
+    void enableDataReadyMode(void) const;
+    void enableMotionMode(void) const;
+    void enablePulseMode(void) const;
+    void enableOrientationMode(void) const;
+    void enableTransitMode(void) const;
+    void enableAutoSleepMode(void) const;
+    void enableFIFOMode(void) const;
+    
+    /** Put the MMA845x in the lowest possible power mode and suspend operation
+     */
+    void disable(void);
+    
+    /** Write to a register (exposed for debugging reasons)
+     *  Note: most writes are only valid in stop mode
+     *  @param reg - The register to be written
+     *  @param data - The data to be written
+     */
+    void writeRegister(uint8_t const reg, uint8_t const data) const;
+    
+    /** Read from a register (exposed for debugging reasons)
+     *  @param reg - The register to read from
+     *  @return The register contents
+     */
+    uint8_t readRegister(uint8_t const reg) const;
+    
+    /** print the register map and values to the console
+     */
+    void registerDump(void) const;
+    
+private:
+    
+    I2C         *_i2c;
+    InterruptIn *_int1;
+    InterruptIn *_int2;
+    uint8_t      _i2c_addr;
+    MMA845x_DATA _data;
+    
+    void init(void) const;
+};
+
+#endif