Class Module for MMA845x I2C Accelerometer.

Dependents:   mDotEVBM2X MTDOT-EVBDemo-DRH MTDOT-BOX-EVB-Factory-Firmware-LIB-108 MTDOT-UDKDemo_Senet ... more

Fork of MMA845x by Sam Grove

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MMA845x.cpp Source File

MMA845x.cpp

Go to the documentation of this file.
00001 /**
00002  * @file    MMA845x.cpp
00003  * @brief   Device driver - MMA845X 3-axis accelerometer IC W/RTOS support
00004  * @author  Tim Barr
00005  * @version 1.0
00006  * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf
00007  * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8452Q.pdf
00008  * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8453Q.pdf
00009  *
00010  * Copyright (c) 2015
00011  *
00012  * Licensed under the Apache License, Version 2.0 (the "License");
00013  * you may not use this file except in compliance with the License.
00014  * You may obtain a copy of the License at
00015  *
00016  *     http://www.apache.org/licenses/LICENSE-2.0
00017  *
00018  * Unless required by applicable law or agreed to in writing, software
00019  * distributed under the License is distributed on an "AS IS" BASIS,
00020  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00021  * See the License for the specific language governing permissions and
00022  * limitations under the License.
00023  *
00024  * 5/5/2015 Forked from https://developer.mbed.org/users/sam_grove/code/MMA845x/
00025  *
00026  * 6/20/2015 TAB Added setup functions and polling data capability. Also added RTOS calls
00027  * TODO Still need to add interrupt support for other Accelerometer mode support
00028  */
00029 
00030 #include "MMA845x.h"
00031 #include "mbed_debug.h"
00032 #include "rtos.h"
00033 
00034 MMA845x::MMA845x(I2C &i2c, SA0 const i2c_addr, InterruptIn* int1, InterruptIn* int2)
00035 {
00036     _i2c =  &i2c;
00037     _int1 = int1;
00038     _int2 = int2;
00039 
00040     _i2c_addr = (0x1c | i2c_addr) << 1;
00041 
00042     MMA845x::init();
00043 
00044     return;
00045 }
00046 
00047 uint8_t MMA845x::init(void)
00048 {
00049     uint8_t result = 0;
00050     uint8_t i = 0;
00051     char reg_val[1];
00052 
00053     _who_am_i = 0x00;
00054 
00055     // Reset all registers to POR values
00056     result = MMA845x::writeRegister(CTRL_REG2, 0xFF);        //REG 0x2B
00057     if (result == 0) {
00058 
00059         do {
00060             // wait for the reset bit to clear. readRegister may error out so we re-try 10 times
00061             osDelay(200);
00062             reg_val[0] = 0x40;
00063             result = MMA845x::readRegister(CTRL_REG2,1,reg_val);
00064             reg_val[0] = reg_val[0] & 0x40;
00065             i++;
00066         } while(((reg_val[0] != 0)||( result != 0)) && (i<=10));
00067     }
00068 
00069     if (result == 0) {
00070         result = MMA845x::readRegister(WHO_AM_I,1,reg_val);
00071     }
00072 
00073     switch (reg_val[0]) {
00074         case MMA8451 :
00075         case MMA8452 :
00076         case MMA8453 :
00077             _who_am_i= reg_val[0];
00078             if ((_int1 == NULL) && (_int2 == NULL))
00079                 _polling_mode = true;
00080             else _polling_mode = false;
00081             break;
00082         default:
00083             debug ("Device not supported by this library!\n\r");
00084             result = 1;
00085     }
00086 
00087     if(result != 0) {
00088         debug("MMA845x:init failed\n\r");
00089     }
00090 
00091 
00092     return result;
00093 }
00094 
00095 uint8_t MMA845x::setCommonParameters(RANGE range, RESOLUTION resolution, LOW_NOISE lo_noise,
00096                                      DATA_RATE data_rate, OVERSAMPLE_MODE os_mode, HPF_MODE hpf_mode) const
00097 {
00098     uint8_t result = 0;
00099     char datain[1];
00100     uint8_t dataout = 0;
00101 
00102     result |= MMA845x::readRegister(SYSMOD,1,datain); // Make sure MMA845x is in Stand-By mode
00103     if ((datain[0] & 0x03) != 0 ) {
00104         debug ("MMA845x not in STAND BY mode\n\f");
00105         debug("MMA845x:setCommonParameters failed\n\r");
00106         result = 1;
00107         return result;
00108     }
00109 
00110     result |= MMA845x::readRegister(CTRL_REG1, 1, datain);
00111     dataout = (datain[0] & 0xB1) | resolution | lo_noise | data_rate;
00112     result |= MMA845x::writeRegister(CTRL_REG1, dataout);        // Set resolution, Low Noise mode, and data rate
00113 
00114     result |= MMA845x::readRegister(CTRL_REG2,1, datain);
00115     dataout = (datain[0] & 0xFB) | os_mode;
00116     result |= MMA845x::writeRegister(CTRL_REG2, dataout);        // Set Oversample mode
00117 
00118     result |= MMA845x::readRegister(XYZ_DATA_CFG,1, datain);
00119     dataout = range | hpf_mode;
00120     result |= MMA845x::writeRegister(XYZ_DATA_CFG, dataout);     //Set HPF mode and range
00121 
00122 //    result |= MMA845x::readRegister(HP_FILTER_CUTOFF,1, datain);
00123 //    result |= MMA845x::writeRegister(HP_FILTER_CUTOFF, dataout); //REG 0xF HPF settings
00124 
00125     if(result != 0) {
00126         debug("MMA845x:setParameters failed\n\r");
00127     }
00128 
00129     return result;
00130 
00131 }
00132 
00133 uint8_t MMA845x::enableMotionDetect(void) const
00134 {
00135     uint8_t result = 0;
00136     return result;
00137 }
00138 
00139 uint8_t MMA845x::enablePulseDetect(void) const
00140 {
00141     uint8_t result = 0;
00142     return result;
00143 }
00144 
00145 uint8_t MMA845x::enableOrientationDetect(void) const
00146 {
00147     uint8_t result = 0;
00148 
00149     if(_who_am_i != MMA8451 ) {
00150         debug("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
00151         result = 1;
00152     }
00153 
00154     return result;
00155 }
00156 
00157 uint8_t MMA845x::enableTransientDetect(void) const
00158 {
00159     uint8_t result = 0;
00160     return result;
00161 }
00162 
00163 uint8_t MMA845x::enableAutoSleep(void) const
00164 {
00165     uint8_t result = 0;
00166     return result;
00167 }
00168 
00169 uint8_t MMA845x::enableFIFO(void) const
00170 {
00171     uint8_t result = 0;
00172 
00173     if(_who_am_i != MMA8451 ) {
00174         debug("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
00175         result = 1;
00176     }
00177 
00178     return result;
00179 }
00180 
00181 uint8_t MMA845x::activeMode(void) const
00182 {
00183     uint8_t result = 0;
00184     char datain[1];
00185     uint8_t dataout;
00186 
00187     result |= MMA845x::readRegister(CTRL_REG1,1, datain);
00188     dataout = (datain[0] & 0xFE) | 0x01 ;
00189     result |= MMA845x::writeRegister(CTRL_REG1, dataout);        // Set to active mode
00190 
00191     return result;
00192 }
00193 uint8_t MMA845x::standbyMode(void) const
00194 {
00195     uint8_t result = 0;
00196     char datain[1];
00197     uint8_t dataout;
00198 
00199     result |= MMA845x::readRegister(CTRL_REG1,1, datain);
00200     dataout = (datain[0] & 0xFE);
00201     result |= MMA845x::writeRegister(CTRL_REG1, dataout);        // Set to standby mode
00202 
00203     return result;
00204 }
00205 
00206 uint8_t MMA845x::getStatus(void) const
00207 {
00208     uint8_t result = 0;
00209     char datain[1];
00210     uint8_t dataout;
00211 
00212     result = MMA845x::readRegister(STATUS,1, datain);
00213 
00214     if (result != 0)
00215         dataout = result;
00216     else
00217         dataout = datain[0];
00218 
00219     return dataout;
00220 }
00221 
00222 int16_t MMA845x::getX(void)
00223 {
00224     char datain[2];
00225 
00226     if (_polling_mode) {
00227         MMA845x::readRegister(OUT_X_MSB,2, datain);
00228         _data._x  = ((datain[0] << 8) | datain[1]);  /* data is 14 bit signed with 2 LSB = 0 */
00229         _data._x  /= 4;        /* need to shift first to preserve sign then /4 to remove LSBs */
00230     }
00231     return _data._x ;
00232 
00233 }
00234 
00235 int16_t MMA845x::getY(void)
00236 {
00237     char datain[2];
00238 
00239     if (_polling_mode) {
00240         MMA845x::readRegister(OUT_Y_MSB,2, datain);
00241         _data._y  = ((datain[0] << 8) | datain[1]);   /* data is 14 bit signed with 2 LSB = 0 */
00242         _data._y  /= 4;        /* need to shift first to preserve sign then /4 to remove LSBs */
00243     }
00244     return _data._y ;
00245 }
00246 
00247 int16_t MMA845x::getZ(void)
00248 {
00249     char datain[2];
00250 
00251     if (_polling_mode) {
00252         MMA845x::readRegister(OUT_Z_MSB,2, datain);
00253         _data._z  = ((datain[0] << 8) | datain[1]);   /* data is 14 bit signed with 2 LSB = 0 */
00254         _data._z  /= 4;        /* need to shift first to preserve sign then /4 to remove LSBs */
00255     }
00256 
00257     return _data._z ;
00258 }
00259 
00260 MMA845x_DATA MMA845x::getXYZ(void)
00261 {
00262     char datain[6];
00263 
00264     if (_polling_mode) {
00265         MMA845x::readRegister(OUT_X_MSB,6, datain);   /* data is 14 bit signed with 2 LSB = 0 */
00266         _data._x  = ((datain[0] << 8) | datain[1]);    /* need to shift first to preserve sign */
00267         _data._x  /= 4;                                /* then /4 to remove LSBs */
00268         _data._y  = ((datain[2] << 8) | datain[3]);
00269         _data._y  /= 4;
00270         _data._z  = ((datain[4] << 8) | datain[5]);
00271         _data._z  /= 4;
00272     }
00273 
00274     return _data;
00275 }
00276 
00277 char MMA845x::getWhoAmI(void) const
00278 {
00279     return _who_am_i;
00280 }
00281 
00282 uint8_t MMA845x::writeRegister(uint8_t const reg, uint8_t const data) const
00283 {
00284     char buf[2] = {reg, data};
00285     uint8_t result = 0;
00286 
00287     buf[0] = reg;
00288     buf[1] = data;
00289 
00290     result |= _i2c->write(_i2c_addr, buf, 2);
00291 
00292     if (result != 0) {
00293         debug("MMA845x::writeRegister failed r-%d\n\r",result);
00294     }
00295 
00296     return result;
00297 }
00298 
00299 uint8_t MMA845x::readRegister(uint8_t const reg, uint8_t count, char* data) const
00300 {
00301     uint8_t result = 0;
00302     char reg_out[1];
00303 
00304     reg_out[0] = reg;
00305     _i2c->lock();
00306 
00307     // MMA8451Q expects a repeated start from the master
00308     result |= _i2c->write(_i2c_addr,reg_out,1,true);
00309 
00310     if (result != 0) {
00311         debug("MMA845x::readRegister failed write r- %d\n\r", result);
00312         goto exit;
00313     }
00314 
00315     result |= _i2c->read(_i2c_addr,data,count,false);
00316 
00317     if (result != 0) {
00318         debug("MMA845x::readRegister failed read r-%d\n\r",result);
00319     }
00320 
00321 exit:
00322     _i2c->unlock();
00323     return result;
00324 }