Device driver for the Freescale MMA845x family of accelerometers.

Fork of MMA845x by Sam Grove

Revision:
2:555f8ba0c959
Parent:
1:37ddb4739f02
diff -r 37ddb4739f02 -r 555f8ba0c959 MMA845x.cpp
--- a/MMA845x.cpp	Thu Jan 05 06:41:39 2017 +0000
+++ b/MMA845x.cpp	Wed Jan 11 04:12:05 2017 +0000
@@ -1,13 +1,13 @@
 /**
  * @file    MMA845x.cpp
- * @brief   Device driver - MMA845X 3-axis accelerometer IC
- * @author  sam grove
+ * @brief   Device driver - MMA845X 3-axis accelerometer IC W/RTOS support
+ * @author  Tim Barr
  * @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
+ * Copyright (c) 2015
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,153 +20,304 @@
  * 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.
+ *
+ * 5/5/2015 Forked from https://developer.mbed.org/users/sam_grove/code/MMA845x/
+ *
+ * 6/20/2015 TAB Added setup functions and polling data capability. Also added RTOS calls
+ * TODO Still need to add interrupt support for other Accelerometer mode support
  */
- 
-#include "MMA845x.h"
- 
-MMA845x::MMA845x(I2C &i2c, InterruptIn &int1, InterruptIn &int2) {
-    _i2c =  &i2c;
-    _int1 = &int1;
-    _int2 = &int2;
-    
-    _i2c_addr = (0x1c << 2) | (0 << 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;
-}
+#include "MMA845x.h"
+#include "mbed_debug.h"
+#include "rtos.h"
+#include "MTSLog.h"
 
-void MMA845x::enableDataReadyMode(void) const
+MMA845x::MMA845x(I2C &i2c, SA0 const i2c_addr, InterruptIn* int1, InterruptIn* int2)
 {
-    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
-    
-}
+    _i2c =  &i2c;
+    _int1 = int1;
+    _int2 = int2;
 
-void MMA845x::enableMotionMode(void) const{}
-void MMA845x::enablePulseMode(void) const{}
+    _i2c_addr = (0x1c | i2c_addr) << 1;
 
-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__);
-    }
-    
+    MMA845x::init();
+
     return;
 }
 
-void MMA845x::enableTransitMode(void) const{}
-void MMA845x::enableAutoSleepMode(void) const{}
-
-void MMA845x::enableFIFOMode(void) const
+uint8_t MMA845x::init(void)
 {
-    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__);
+    uint8_t result = 0;
+    uint8_t i = 0;
+    char reg_val[1];
+
+    _i2c->frequency(100000);
+    _who_am_i = 0x00;
+
+    // Reset all registers to POR values
+    result = MMA845x::writeRegister(CTRL_REG2, 0xFF);        //REG 0x2B
+    if (result == 0) {
+
+        do {
+            // wait for the reset bit to clear. readRegister may error out so we re-try 10 times
+            osDelay(200);
+            reg_val[0] = 0x40;
+            result = MMA845x::readRegister(CTRL_REG2,1,reg_val);
+            reg_val[0] = reg_val[0] & 0x40;
+            i++;
+        } while(((reg_val[0] != 0)||( result != 0)) && (i<=10));
+    }
+
+    if (result == 0) {
+        result = MMA845x::readRegister(WHO_AM_I,1,reg_val);
+    }
+
+    switch (reg_val[0]) {
+        case MMA8451:
+        case MMA8452:
+        case MMA8453:
+            _who_am_i= reg_val[0];
+            if ((_int1 == NULL) && (_int2 == NULL))
+                _polling_mode = true;
+            else _polling_mode = false;
+            break;
+        default:
+            debug ("Device not supported by this library!\n\r");
+            result = 1;
+    }
+
+    if(result != 0) {
+        debug("MMA845x:init failed\n\r");
     }
-    
-    //MMA845x::writeRegister(
-    
-    return;
+
+
+    return result;
+}
+
+uint8_t MMA845x::setCommonParameters(RANGE range, RESOLUTION resolution, LOW_NOISE lo_noise,
+                                     DATA_RATE data_rate, OVERSAMPLE_MODE os_mode, HPF_MODE hpf_mode) const
+{
+    uint8_t result = 0;
+    char datain[1];
+    uint8_t dataout = 0;
+
+    result |= MMA845x::readRegister(SYSMOD,1,datain); // Make sure MMA845x is in Stand-By mode
+    if ((datain[0] & 0x03) != 0 ) {
+        debug ("MMA845x not in STAND BY mode\n\f");
+        debug("MMA845x:setCommonParameters failed\n\r");
+        result = 1;
+        return result;
+    }
+
+    result |= MMA845x::readRegister(CTRL_REG1, 1, datain);
+    dataout = (datain[0] & 0xB1) | resolution | lo_noise | data_rate;
+    result |= MMA845x::writeRegister(CTRL_REG1, dataout);        // Set resolution, Low Noise mode, and data rate
+
+    result |= MMA845x::readRegister(CTRL_REG2,1, datain);
+    dataout = (datain[0] & 0xFB) | os_mode;
+    result |= MMA845x::writeRegister(CTRL_REG2, dataout);        // Set Oversample mode
+
+    result |= MMA845x::readRegister(XYZ_DATA_CFG,1, datain);
+    dataout = range | hpf_mode;
+    result |= MMA845x::writeRegister(XYZ_DATA_CFG, dataout);     //Set HPF mode and range
+
+//    result |= MMA845x::readRegister(HP_FILTER_CUTOFF,1, datain);
+//    result |= MMA845x::writeRegister(HP_FILTER_CUTOFF, dataout); //REG 0xF HPF settings
+
+    if(result != 0) {
+        debug("MMA845x:setParameters failed\n\r");
+    }
+
+    return result;
+
+}
+
+uint8_t MMA845x::enableMotionDetect(void) const
+{
+    uint8_t result = 0;
+    return result;
+}
+
+uint8_t MMA845x::enablePulseDetect(void) const
+{
+    uint8_t result = 0;
+    return result;
 }
 
-uint16_t MMA845x::getX(void) const
+uint8_t MMA845x::enableOrientationDetect(void) const
+{
+    uint8_t result = 0;
+
+    if(_who_am_i != MMA8451) {
+        debug("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
+        result = 1;
+    }
+
+    return result;
+}
+
+uint8_t MMA845x::enableTransientDetect(void) const
+{
+    uint8_t result = 0;
+    return result;
+}
+
+uint8_t MMA845x::enableAutoSleep(void) const
 {
-    return _data._x;
+    uint8_t result = 0;
+    return result;
+}
+
+uint8_t MMA845x::enableFIFO(void) const
+{
+    uint8_t result = 0;
+
+    if(_who_am_i != MMA8451) {
+        debug("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
+        result = 1;
+    }
+
+    return result;
+}
+
+uint8_t MMA845x::activeMode(void) const
+{
+    uint8_t result = 0;
+    char datain[1];
+    uint8_t dataout;
+
+    result |= MMA845x::readRegister(CTRL_REG1,1, datain);
+    dataout = (datain[0] & 0xFE) | 0x01 ;
+    result |= MMA845x::writeRegister(CTRL_REG1, dataout);        // Set to active mode
+
+    return result;
 }
-    
-uint16_t MMA845x::getY(void) const
+uint8_t MMA845x::standbyMode(void) const
+{
+    uint8_t result = 0;
+    char datain[1];
+    uint8_t dataout;
+
+    result |= MMA845x::readRegister(CTRL_REG1,1, datain);
+    dataout = (datain[0] & 0xFE);
+    result |= MMA845x::writeRegister(CTRL_REG1, dataout);        // Set to standby mode
+
+    return result;
+}
+
+uint8_t MMA845x::getStatus(void) const
 {
+    uint8_t result = 0;
+    char datain[1];
+    uint8_t dataout;
+
+    result = MMA845x::readRegister(STATUS,1, datain);
+
+    if (result != 0)
+        dataout = result;
+    else
+        dataout = datain[0];
+
+    return dataout;
+}
+
+int16_t MMA845x::getX(void)
+{
+    char datain[2];
+
+    if (_polling_mode) {
+        MMA845x::readRegister(OUT_X_MSB,2, datain);
+        _data._x = ((datain[0] << 8) | datain[1]);  /* data is 14 bit signed with 2 LSB = 0 */
+        _data._x /= 4;        /* need to shift first to preserve sign then /4 to remove LSBs */
+    }
+    return _data._x;
+
+}
+
+int16_t MMA845x::getY(void)
+{
+    char datain[2];
+
+    if (_polling_mode) {
+        MMA845x::readRegister(OUT_Y_MSB,2, datain);
+        _data._y = ((datain[0] << 8) | datain[1]);   /* data is 14 bit signed with 2 LSB = 0 */
+        _data._y /= 4;        /* need to shift first to preserve sign then /4 to remove LSBs */
+    }
     return _data._y;
 }
 
-uint16_t MMA845x::getZ(void) const
+int16_t MMA845x::getZ(void)
 {
+    char datain[2];
+
+    if (_polling_mode) {
+        MMA845x::readRegister(OUT_Z_MSB,2, datain);
+        _data._z = ((datain[0] << 8) | datain[1]);   /* data is 14 bit signed with 2 LSB = 0 */
+        _data._z /= 4;        /* need to shift first to preserve sign then /4 to remove LSBs */
+    }
+
     return _data._z;
 }
-    
-MMA845x_DATA MMA845x::getXYZ(void) const
+
+MMA845x_DATA MMA845x::getXYZ(void)
 {
+    char datain[6];
+
+    if (_polling_mode) {
+        MMA845x::readRegister(OUT_X_MSB,6, datain);   /* data is 14 bit signed with 2 LSB = 0 */
+        _data._x = ((datain[0] << 8) | datain[1]);    /* need to shift first to preserve sign */
+        _data._x /= 4;                                /* then /4 to remove LSBs */
+        _data._y = ((datain[2] << 8) | datain[3]);
+        _data._y /= 4;
+        _data._z = ((datain[4] << 8) | datain[5]);
+        _data._z /= 4;
+    } else {
+        logInfo("NOT POLLING MODE\n\r");
+    }
+
     return _data;
 }
 
-void MMA845x::writeRegister(uint8_t const reg, uint8_t const data) const
+char MMA845x::getWhoAmI(void) const
+{
+    return _who_am_i;
+}
+
+uint8_t 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__);
+
+    buf[0] = reg;
+    buf[1] = data;
+
+    result |= _i2c->write(_i2c_addr, buf, 2);
+
+    if(result != 0) {
+        debug("MMA845x:writeRegister failed r-%d\n\r",result);
     }
-    
-    return;
+
+    return result;
 }
 
-uint8_t MMA845x::readRegister(uint8_t const reg) const
+uint8_t MMA845x::readRegister(uint8_t const reg, uint8_t count, char* data) 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__);
+    uint8_t result = 0;
+    char reg_out[1];
+
+    reg_out[0] = reg;
+    result |= _i2c->write(_i2c_addr,reg_out,1,true);
+
+    if(result != 0) {
+        debug("MMA845x::readRegister failed write r- %d\n\r", result);
+        return result;
     }
-    
-    return data;
-}
+
+    result |= _i2c->read(_i2c_addr,data,count,false);
 
-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);
+    if(result != 0) {
+        debug("MMA845x::readRegister failed read r-%d\n\r",result);
     }
-    
-    return;
+
+    return result;
 }
-