Library for driving the MMA8452 accelerometer over I2C

Dependents:   MMA8452_Test MMA8452_Demo Dualing_Tanks IMU-Controlled_MP3_Player ... more

Here is a simple example:

#include "mbed.h"
#include "MMA8452.h"

int main() {
   Serial pc(USBTX,USBRX);
   pc.baud(115200);
   double x = 0, y = 0, z = 0;

   MMA8452 acc(p28, p27, 40000);
   acc.setBitDepth(MMA8452::BIT_DEPTH_12);
   acc.setDynamicRange(MMA8452::DYNAMIC_RANGE_4G);
   acc.setDataRate(MMA8452::RATE_100);
   
   while(1) {
      if(!acc.isXYZReady()) {
         wait(0.01);
         continue;
      }
      acc.readXYZGravity(&x,&y,&z);
      pc.printf("Gravities: %lf %lf %lf\r\n",x,y,z);
   }
}

An easy way to test that this actually works is to run the loop above and hold the MMA8452 parallel to the ground along the respective axis (and upsidedown in each axis). You will see 1G on the respective axis and 0G on the others.

Committer:
ashleymills
Date:
Thu Mar 06 18:07:43 2014 +0000
Revision:
19:4d6cd7140a71
Parent:
17:6e4232c421c0
Child:
20:d55e9d7eb17e
Adding independent query methods;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 14:0602b45ca70f 1 // Authors: Ashley Mills, Nicholas Herriot
nherriot 0:bcf2aa85d7f9 2 /* Copyright (c) 2013 Vodafone, MIT License
nherriot 0:bcf2aa85d7f9 3 *
nherriot 0:bcf2aa85d7f9 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
nherriot 0:bcf2aa85d7f9 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
nherriot 0:bcf2aa85d7f9 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
nherriot 0:bcf2aa85d7f9 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
nherriot 0:bcf2aa85d7f9 8 * furnished to do so, subject to the following conditions:
nherriot 0:bcf2aa85d7f9 9 *
nherriot 0:bcf2aa85d7f9 10 * The above copyright notice and this permission notice shall be included in all copies or
nherriot 0:bcf2aa85d7f9 11 * substantial portions of the Software.
nherriot 0:bcf2aa85d7f9 12 *
nherriot 0:bcf2aa85d7f9 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
nherriot 0:bcf2aa85d7f9 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
nherriot 0:bcf2aa85d7f9 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
nherriot 0:bcf2aa85d7f9 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
nherriot 0:bcf2aa85d7f9 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
nherriot 0:bcf2aa85d7f9 18 */
nherriot 0:bcf2aa85d7f9 19
ashleymills 11:dfd1e0afcb7b 20 #include "MMA8452.h"
ashleymills 11:dfd1e0afcb7b 21 #include "mbed.h"
ashleymills 11:dfd1e0afcb7b 22
ashleymills 17:6e4232c421c0 23 #ifdef MMA8452_DEBUG
ashleymills 19:4d6cd7140a71 24 // you need to define Serial pc(USBTX,USBRX) somewhere for the below line to make sense
ashleymills 11:dfd1e0afcb7b 25 extern Serial pc;
ashleymills 17:6e4232c421c0 26 #define MMA8452_DBG(...) pc.printf(__VA_ARGS__); pc.printf("\r\n");
ashleymills 17:6e4232c421c0 27 #else
ashleymills 17:6e4232c421c0 28 #define MMA8452_DBG(...)
ashleymills 17:6e4232c421c0 29 #endif
nherriot 0:bcf2aa85d7f9 30
nherriot 0:bcf2aa85d7f9 31 // Connect module at I2C address using I2C port pins sda and scl
ashleymills 11:dfd1e0afcb7b 32 MMA8452::MMA8452(PinName sda, PinName scl, int frequency) : _i2c(sda, scl) , _frequency(frequency) {
ashleymills 17:6e4232c421c0 33 MMA8452_DBG("Creating MMA8452");
ashleymills 12:172540ff6b8b 34
ashleymills 12:172540ff6b8b 35 // set I2C frequency
ashleymills 11:dfd1e0afcb7b 36 _i2c.frequency(_frequency);
ashleymills 11:dfd1e0afcb7b 37
ashleymills 12:172540ff6b8b 38 // setup read and write addresses for convenience
ashleymills 11:dfd1e0afcb7b 39 _readAddress = MMA8452_ADDRESS | 0x01;
ashleymills 11:dfd1e0afcb7b 40 _writeAddress = MMA8452_ADDRESS & 0xFE;
ashleymills 12:172540ff6b8b 41
ashleymills 12:172540ff6b8b 42 // set some defaults
ashleymills 12:172540ff6b8b 43 _bitDepth = BIT_DEPTH_UNKNOWN;
ashleymills 12:172540ff6b8b 44 setBitDepth(BIT_DEPTH_12);
ashleymills 13:4bd8b4cd479d 45 _dynamicRange = DYNAMIC_RANGE_UNKNOWN;
ashleymills 13:4bd8b4cd479d 46 setDynamicRange(DYNAMIC_RANGE_2G);
ashleymills 13:4bd8b4cd479d 47
ashleymills 17:6e4232c421c0 48 MMA8452_DBG("Done");
nherriot 0:bcf2aa85d7f9 49 }
nherriot 0:bcf2aa85d7f9 50
nherriot 0:bcf2aa85d7f9 51
nherriot 0:bcf2aa85d7f9 52 // Destroys instance
ashleymills 10:ca9ba7ad4e94 53 MMA8452::~MMA8452() {}
nherriot 0:bcf2aa85d7f9 54
nherriot 0:bcf2aa85d7f9 55 // Setting the control register bit 1 to true to activate the MMA8452
ashleymills 10:ca9ba7ad4e94 56 int MMA8452::activate() {
ashleymills 6:f6bde04bf8be 57 // perform write and return error code
ashleymills 12:172540ff6b8b 58 return logicalORRegister(MMA8452_CTRL_REG_1,MMA8452_ACTIVE_MASK);
nherriot 3:ffb0b1650ca2 59 }
nherriot 3:ffb0b1650ca2 60
ashleymills 11:dfd1e0afcb7b 61 // Setting the control register bit 1 to 0 to standby the MMA8452
ashleymills 11:dfd1e0afcb7b 62 int MMA8452::standby() {
ashleymills 11:dfd1e0afcb7b 63 // perform write and return error code
ashleymills 12:172540ff6b8b 64 return logicalANDRegister(MMA8452_CTRL_REG_1,MMA8452_STANDBY_MASK);
nherriot 5:b3d0abd97e55 65 }
nherriot 5:b3d0abd97e55 66
ashleymills 11:dfd1e0afcb7b 67 // this reads a register, applies a bitmask with logical AND, sets a value with logical OR,
ashleymills 11:dfd1e0afcb7b 68 // and optionally goes into and out of standby at the beginning and end of the function respectively
ashleymills 11:dfd1e0afcb7b 69 int MMA8452::maskAndApplyRegister(char reg, char mask, char value, int toggleActivation) {
ashleymills 11:dfd1e0afcb7b 70 if(toggleActivation) {
ashleymills 11:dfd1e0afcb7b 71 if(standby()) {
ashleymills 11:dfd1e0afcb7b 72 return 1;
ashleymills 11:dfd1e0afcb7b 73 }
ashleymills 11:dfd1e0afcb7b 74 }
ashleymills 11:dfd1e0afcb7b 75
ashleymills 11:dfd1e0afcb7b 76 // read from register
ashleymills 11:dfd1e0afcb7b 77 char oldValue = 0;
ashleymills 11:dfd1e0afcb7b 78 if(readRegister(reg,&oldValue)) {
ashleymills 11:dfd1e0afcb7b 79 return 1;
ashleymills 11:dfd1e0afcb7b 80 }
ashleymills 11:dfd1e0afcb7b 81
ashleymills 11:dfd1e0afcb7b 82 // apply bitmask
ashleymills 11:dfd1e0afcb7b 83 oldValue &= mask;
ashleymills 11:dfd1e0afcb7b 84
ashleymills 11:dfd1e0afcb7b 85 // set value
ashleymills 11:dfd1e0afcb7b 86 oldValue |= value;
ashleymills 11:dfd1e0afcb7b 87
ashleymills 11:dfd1e0afcb7b 88 // write back to register
ashleymills 11:dfd1e0afcb7b 89 if(writeRegister(reg,oldValue)) {
ashleymills 11:dfd1e0afcb7b 90 return 1;
ashleymills 11:dfd1e0afcb7b 91 }
ashleymills 11:dfd1e0afcb7b 92
ashleymills 11:dfd1e0afcb7b 93 if(toggleActivation) {
ashleymills 11:dfd1e0afcb7b 94 if(activate()) {
ashleymills 11:dfd1e0afcb7b 95 return 1;
ashleymills 11:dfd1e0afcb7b 96 }
ashleymills 11:dfd1e0afcb7b 97 }
ashleymills 11:dfd1e0afcb7b 98 return 0;
nherriot 0:bcf2aa85d7f9 99 }
nherriot 0:bcf2aa85d7f9 100
ashleymills 11:dfd1e0afcb7b 101 int MMA8452::setDynamicRange(DynamicRange range, int toggleActivation) {
ashleymills 13:4bd8b4cd479d 102 _dynamicRange = range;
ashleymills 11:dfd1e0afcb7b 103 return maskAndApplyRegister(
ashleymills 11:dfd1e0afcb7b 104 MMA8452_XYZ_DATA_CFG,
ashleymills 11:dfd1e0afcb7b 105 MMA8452_DYNAMIC_RANGE_MASK,
ashleymills 11:dfd1e0afcb7b 106 range,
ashleymills 11:dfd1e0afcb7b 107 toggleActivation
ashleymills 11:dfd1e0afcb7b 108 );
nherriot 0:bcf2aa85d7f9 109 }
nherriot 0:bcf2aa85d7f9 110
ashleymills 11:dfd1e0afcb7b 111 int MMA8452::setDataRate(DataRateHz dataRate, int toggleActivation) {
ashleymills 11:dfd1e0afcb7b 112 return maskAndApplyRegister(
ashleymills 11:dfd1e0afcb7b 113 MMA8452_CTRL_REG_1,
ashleymills 11:dfd1e0afcb7b 114 MMA8452_DATA_RATE_MASK,
ashleymills 11:dfd1e0afcb7b 115 dataRate<<MMA8452_DATA_RATE_MASK_SHIFT,
ashleymills 11:dfd1e0afcb7b 116 toggleActivation
ashleymills 11:dfd1e0afcb7b 117 );
nherriot 3:ffb0b1650ca2 118 }
nherriot 3:ffb0b1650ca2 119
ashleymills 11:dfd1e0afcb7b 120 int MMA8452::setBitDepth(BitDepth depth,int toggleActivation) {
ashleymills 12:172540ff6b8b 121 _bitDepth = depth;
ashleymills 11:dfd1e0afcb7b 122 return maskAndApplyRegister(
ashleymills 11:dfd1e0afcb7b 123 MMA8452_CTRL_REG_1,
ashleymills 11:dfd1e0afcb7b 124 MMA8452_BIT_DEPTH_MASK,
ashleymills 11:dfd1e0afcb7b 125 depth<<MMA8452_BIT_DEPTH_MASK_SHIFT,
ashleymills 11:dfd1e0afcb7b 126 toggleActivation
ashleymills 11:dfd1e0afcb7b 127 );
nherriot 3:ffb0b1650ca2 128 }
nherriot 3:ffb0b1650ca2 129
ashleymills 16:d6dde2318edc 130 char MMA8452::getMaskedRegister(int reg, char mask) {
ashleymills 12:172540ff6b8b 131 char rval = 0;
ashleymills 16:d6dde2318edc 132 if(readRegister(reg,&rval)) {
ashleymills 12:172540ff6b8b 133 return 0;
ashleymills 12:172540ff6b8b 134 }
ashleymills 16:d6dde2318edc 135 return (rval&mask);
ashleymills 16:d6dde2318edc 136 }
ashleymills 16:d6dde2318edc 137
ashleymills 16:d6dde2318edc 138 int MMA8452::isXYZReady() {
ashleymills 16:d6dde2318edc 139 return getMaskedRegister(MMA8452_STATUS,MMA8452_STATUS_ZYXDR_MASK)>0;
ashleymills 16:d6dde2318edc 140 }
ashleymills 16:d6dde2318edc 141
ashleymills 16:d6dde2318edc 142 int MMA8452::isXReady() {
ashleymills 16:d6dde2318edc 143 return getMaskedRegister(MMA8452_STATUS,MMA8452_STATUS_XDR_MASK)>0;
nherriot 1:ef026bf28798 144 }
ashleymills 16:d6dde2318edc 145
ashleymills 16:d6dde2318edc 146 int MMA8452::isYReady() {
ashleymills 16:d6dde2318edc 147 return getMaskedRegister(MMA8452_STATUS,MMA8452_STATUS_YDR_MASK)>0;
ashleymills 16:d6dde2318edc 148 }
ashleymills 16:d6dde2318edc 149
ashleymills 16:d6dde2318edc 150 int MMA8452::isZReady() {
ashleymills 16:d6dde2318edc 151 return getMaskedRegister(MMA8452_STATUS,MMA8452_STATUS_ZDR_MASK)>0;
ashleymills 16:d6dde2318edc 152 }
ashleymills 16:d6dde2318edc 153
ashleymills 16:d6dde2318edc 154
ashleymills 12:172540ff6b8b 155 int MMA8452::getDeviceID(char *dst) {
ashleymills 12:172540ff6b8b 156 return readRegister(MMA8452_WHO_AM_I,dst);
nherriot 3:ffb0b1650ca2 157 }
nherriot 3:ffb0b1650ca2 158
ashleymills 12:172540ff6b8b 159 int MMA8452::getStatus(char* dst) {
ashleymills 12:172540ff6b8b 160 return readRegister(MMA8452_STATUS,dst);
nherriot 3:ffb0b1650ca2 161 }
nherriot 0:bcf2aa85d7f9 162
ashleymills 11:dfd1e0afcb7b 163 MMA8452::DynamicRange MMA8452::getDynamicRange() {
ashleymills 11:dfd1e0afcb7b 164 char rval = 0;
ashleymills 12:172540ff6b8b 165 if(readRegister(MMA8452_XYZ_DATA_CFG,&rval)) {
ashleymills 11:dfd1e0afcb7b 166 return MMA8452::DYNAMIC_RANGE_UNKNOWN;
ashleymills 11:dfd1e0afcb7b 167 }
ashleymills 11:dfd1e0afcb7b 168 rval &= (MMA8452_DYNAMIC_RANGE_MASK^0xFF);
ashleymills 11:dfd1e0afcb7b 169 return (MMA8452::DynamicRange)rval;
ashleymills 11:dfd1e0afcb7b 170 }
ashleymills 11:dfd1e0afcb7b 171
ashleymills 11:dfd1e0afcb7b 172 MMA8452::DataRateHz MMA8452::getDataRate() {
ashleymills 11:dfd1e0afcb7b 173 char rval = 0;
ashleymills 11:dfd1e0afcb7b 174 if(readRegister(MMA8452_CTRL_REG_1,&rval)) {
ashleymills 11:dfd1e0afcb7b 175 return MMA8452::RATE_UNKNOWN;
ashleymills 11:dfd1e0afcb7b 176 }
ashleymills 11:dfd1e0afcb7b 177 // logical AND with inverse of mask
ashleymills 11:dfd1e0afcb7b 178 rval = rval&(MMA8452_DATA_RATE_MASK^0xFF);
ashleymills 11:dfd1e0afcb7b 179 // shift back into position
ashleymills 11:dfd1e0afcb7b 180 rval >>= MMA8452_DATA_RATE_MASK_SHIFT;
ashleymills 11:dfd1e0afcb7b 181 return (MMA8452::DataRateHz)rval;
ashleymills 11:dfd1e0afcb7b 182 }
ashleymills 11:dfd1e0afcb7b 183
nherriot 0:bcf2aa85d7f9 184 // Reads xyz
ashleymills 13:4bd8b4cd479d 185 int MMA8452::readXYZRaw(char *dst) {
ashleymills 12:172540ff6b8b 186 if(_bitDepth==BIT_DEPTH_UNKNOWN) {
ashleymills 12:172540ff6b8b 187 return 1;
ashleymills 12:172540ff6b8b 188 }
ashleymills 12:172540ff6b8b 189 int readLen = 3;
ashleymills 12:172540ff6b8b 190 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 12:172540ff6b8b 191 readLen = 6;
ashleymills 12:172540ff6b8b 192 }
ashleymills 12:172540ff6b8b 193 return readRegister(MMA8452_OUT_X_MSB,dst,readLen);
nherriot 1:ef026bf28798 194 }
nherriot 0:bcf2aa85d7f9 195
ashleymills 19:4d6cd7140a71 196 int MMA8452::readXRaw(char *dst) {
ashleymills 19:4d6cd7140a71 197 if(_bitDepth==BIT_DEPTH_UNKNOWN) {
ashleymills 19:4d6cd7140a71 198 return 1;
ashleymills 19:4d6cd7140a71 199 }
ashleymills 19:4d6cd7140a71 200 int readLen = 1;
ashleymills 19:4d6cd7140a71 201 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 19:4d6cd7140a71 202 readLen = 2;
ashleymills 19:4d6cd7140a71 203 }
ashleymills 19:4d6cd7140a71 204 return readRegister(MMA8452_OUT_X_MSB,dst,readLen);
ashleymills 19:4d6cd7140a71 205 }
ashleymills 19:4d6cd7140a71 206
ashleymills 19:4d6cd7140a71 207 int MMA8452::readYRaw(char *dst) {
ashleymills 19:4d6cd7140a71 208 if(_bitDepth==BIT_DEPTH_UNKNOWN) {
ashleymills 19:4d6cd7140a71 209 return 1;
ashleymills 19:4d6cd7140a71 210 }
ashleymills 19:4d6cd7140a71 211 int readLen = 1;
ashleymills 19:4d6cd7140a71 212 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 19:4d6cd7140a71 213 readLen = 2;
ashleymills 19:4d6cd7140a71 214 }
ashleymills 19:4d6cd7140a71 215 return readRegister(MMA8452_OUT_Y_MSB,dst,readLen);
ashleymills 19:4d6cd7140a71 216 }
ashleymills 19:4d6cd7140a71 217
ashleymills 19:4d6cd7140a71 218 int MMA8452::readZRaw(char *dst) {
ashleymills 19:4d6cd7140a71 219 if(_bitDepth==BIT_DEPTH_UNKNOWN) {
ashleymills 19:4d6cd7140a71 220 return 1;
ashleymills 19:4d6cd7140a71 221 }
ashleymills 19:4d6cd7140a71 222 int readLen = 1;
ashleymills 19:4d6cd7140a71 223 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 19:4d6cd7140a71 224 readLen = 2;
ashleymills 19:4d6cd7140a71 225 }
ashleymills 19:4d6cd7140a71 226 return readRegister(MMA8452_OUT_Z_MSB,dst,readLen);
ashleymills 19:4d6cd7140a71 227 }
ashleymills 19:4d6cd7140a71 228
ashleymills 13:4bd8b4cd479d 229 int MMA8452::readXYZCounts(int *x, int *y, int *z) {
ashleymills 13:4bd8b4cd479d 230 char buf[6];
ashleymills 13:4bd8b4cd479d 231 if(readXYZRaw((char*)&buf)) {
ashleymills 13:4bd8b4cd479d 232 return 1;
ashleymills 13:4bd8b4cd479d 233 }
ashleymills 13:4bd8b4cd479d 234 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 13:4bd8b4cd479d 235 *x = twelveBitToSigned(&buf[0]);
ashleymills 13:4bd8b4cd479d 236 *y = twelveBitToSigned(&buf[2]);
ashleymills 13:4bd8b4cd479d 237 *z = twelveBitToSigned(&buf[4]);
ashleymills 13:4bd8b4cd479d 238 } else {
ashleymills 13:4bd8b4cd479d 239 *x = eightBitToSigned(&buf[0]);
ashleymills 13:4bd8b4cd479d 240 *y = eightBitToSigned(&buf[1]);
ashleymills 13:4bd8b4cd479d 241 *z = eightBitToSigned(&buf[2]);
ashleymills 13:4bd8b4cd479d 242 }
ashleymills 13:4bd8b4cd479d 243
ashleymills 13:4bd8b4cd479d 244 return 0;
ashleymills 13:4bd8b4cd479d 245 }
ashleymills 13:4bd8b4cd479d 246
ashleymills 19:4d6cd7140a71 247 int readXCount(int *x) {
ashleymills 19:4d6cd7140a71 248 char buf[2];
ashleymills 19:4d6cd7140a71 249 if(readXRaw((char*)&buf)) {
ashleymills 19:4d6cd7140a71 250 return 1;
ashleymills 19:4d6cd7140a71 251 }
ashleymills 19:4d6cd7140a71 252 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 19:4d6cd7140a71 253 *x = twelveBitToSigned(&buf[0]);
ashleymills 19:4d6cd7140a71 254 *y = twelveBitToSigned(&buf[2]);
ashleymills 19:4d6cd7140a71 255 *z = twelveBitToSigned(&buf[4]);
ashleymills 19:4d6cd7140a71 256 } else {
ashleymills 19:4d6cd7140a71 257 *x = eightBitToSigned(&buf[0]);
ashleymills 19:4d6cd7140a71 258 *y = eightBitToSigned(&buf[1]);
ashleymills 19:4d6cd7140a71 259 *z = eightBitToSigned(&buf[2]);
ashleymills 19:4d6cd7140a71 260 }
ashleymills 19:4d6cd7140a71 261
ashleymills 19:4d6cd7140a71 262 }
ashleymills 19:4d6cd7140a71 263
ashleymills 13:4bd8b4cd479d 264 double MMA8452::convertCountToGravity(int count, int countsPerG) {
ashleymills 13:4bd8b4cd479d 265 return (double)count/(double)countsPerG;
ashleymills 13:4bd8b4cd479d 266 }
ashleymills 13:4bd8b4cd479d 267
ashleymills 13:4bd8b4cd479d 268 int MMA8452::readXYZGravity(double *x, double *y, double *z) {
ashleymills 13:4bd8b4cd479d 269 int xCount = 0, yCount = 0, zCount = 0;
ashleymills 13:4bd8b4cd479d 270 if(readXYZCounts(&xCount,&yCount,&zCount)) {
ashleymills 13:4bd8b4cd479d 271 return 1;
ashleymills 13:4bd8b4cd479d 272 }
ashleymills 13:4bd8b4cd479d 273
ashleymills 13:4bd8b4cd479d 274 // assume starting with DYNAMIC_RANGE_2G and BIT_DEPTH_12
ashleymills 13:4bd8b4cd479d 275 int countsPerG = 1024;
ashleymills 13:4bd8b4cd479d 276 if(_bitDepth==BIT_DEPTH_8) {
ashleymills 13:4bd8b4cd479d 277 countsPerG = 64;
ashleymills 13:4bd8b4cd479d 278 }
ashleymills 13:4bd8b4cd479d 279 switch(_dynamicRange) {
ashleymills 13:4bd8b4cd479d 280 case DYNAMIC_RANGE_4G:
ashleymills 13:4bd8b4cd479d 281 countsPerG /= 2;
ashleymills 13:4bd8b4cd479d 282 break;
ashleymills 13:4bd8b4cd479d 283 case DYNAMIC_RANGE_8G:
ashleymills 13:4bd8b4cd479d 284 countsPerG /= 4;
ashleymills 13:4bd8b4cd479d 285 break;
ashleymills 13:4bd8b4cd479d 286 }
ashleymills 13:4bd8b4cd479d 287
ashleymills 13:4bd8b4cd479d 288 *x = convertCountToGravity(xCount,countsPerG);
ashleymills 13:4bd8b4cd479d 289 *y = convertCountToGravity(yCount,countsPerG);
ashleymills 13:4bd8b4cd479d 290 *z = convertCountToGravity(zCount,countsPerG);
ashleymills 13:4bd8b4cd479d 291 return 0;
ashleymills 13:4bd8b4cd479d 292 }
ashleymills 13:4bd8b4cd479d 293
ashleymills 11:dfd1e0afcb7b 294 // apply an AND mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 295 int MMA8452::logicalANDRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 296 char value = 0;
ashleymills 11:dfd1e0afcb7b 297 // read register value
ashleymills 11:dfd1e0afcb7b 298 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 299 return 0;
ashleymills 11:dfd1e0afcb7b 300 }
ashleymills 11:dfd1e0afcb7b 301 // apply mask
ashleymills 11:dfd1e0afcb7b 302 value &= mask;
ashleymills 11:dfd1e0afcb7b 303 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 304 }
ashleymills 11:dfd1e0afcb7b 305
ashleymills 11:dfd1e0afcb7b 306
ashleymills 11:dfd1e0afcb7b 307 // apply an OR mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 308 int MMA8452::logicalORRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 309 char value = 0;
ashleymills 11:dfd1e0afcb7b 310 // read register value
ashleymills 11:dfd1e0afcb7b 311 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 312 return 0;
ashleymills 11:dfd1e0afcb7b 313 }
ashleymills 11:dfd1e0afcb7b 314 // apply mask
ashleymills 11:dfd1e0afcb7b 315 value |= mask;
ashleymills 11:dfd1e0afcb7b 316 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 317 }
ashleymills 11:dfd1e0afcb7b 318
ashleymills 11:dfd1e0afcb7b 319 // apply an OR mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 320 int MMA8452::logicalXORRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 321 char value = 0;
ashleymills 11:dfd1e0afcb7b 322 // read register value
ashleymills 11:dfd1e0afcb7b 323 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 324 return 0;
ashleymills 11:dfd1e0afcb7b 325 }
ashleymills 11:dfd1e0afcb7b 326 // apply mask
ashleymills 11:dfd1e0afcb7b 327 value ^= mask;
ashleymills 11:dfd1e0afcb7b 328 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 329 }
ashleymills 11:dfd1e0afcb7b 330
ashleymills 11:dfd1e0afcb7b 331 // Write register (The device must be placed in Standby Mode to change the value of the registers)
ashleymills 11:dfd1e0afcb7b 332 int MMA8452::writeRegister(char addr, char data) {
ashleymills 11:dfd1e0afcb7b 333 // what this actually does is the following
ashleymills 11:dfd1e0afcb7b 334 // 1. tell I2C bus to start transaction
ashleymills 11:dfd1e0afcb7b 335 // 2. tell slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 336 // 3. send the write address
ashleymills 11:dfd1e0afcb7b 337 // 4. send the data to write
ashleymills 11:dfd1e0afcb7b 338 // 5. tell I2C bus to end transaction
ashleymills 11:dfd1e0afcb7b 339
ashleymills 11:dfd1e0afcb7b 340 // we can wrap this up in the I2C library write function
ashleymills 11:dfd1e0afcb7b 341 char buf[2] = {0,0};
ashleymills 11:dfd1e0afcb7b 342 buf[0] = addr;
ashleymills 11:dfd1e0afcb7b 343 buf[1] = data;
ashleymills 11:dfd1e0afcb7b 344 return _i2c.write(MMA8452_ADDRESS, buf,2);
ashleymills 11:dfd1e0afcb7b 345 // note, could also do return writeRegister(addr,&data,1);
nherriot 0:bcf2aa85d7f9 346 }
nherriot 0:bcf2aa85d7f9 347
ashleymills 13:4bd8b4cd479d 348 int MMA8452::eightBitToSigned(char *buf) {
ashleymills 13:4bd8b4cd479d 349 return (int8_t)*buf;
ashleymills 13:4bd8b4cd479d 350 }
ashleymills 13:4bd8b4cd479d 351
ashleymills 13:4bd8b4cd479d 352 int MMA8452::twelveBitToSigned(char *buf) {
ashleymills 13:4bd8b4cd479d 353 // cheat by using the int16_t internal type
ashleymills 13:4bd8b4cd479d 354 // all we need to do is convert to little-endian format and shift right
ashleymills 13:4bd8b4cd479d 355 int16_t x = 0;
ashleymills 13:4bd8b4cd479d 356 ((char*)&x)[1] = buf[0];
ashleymills 13:4bd8b4cd479d 357 ((char*)&x)[0] = buf[1];
ashleymills 13:4bd8b4cd479d 358 // note this only works because the below is an arithmetic right shift
ashleymills 13:4bd8b4cd479d 359 return x>>4;
ashleymills 13:4bd8b4cd479d 360 }
ashleymills 11:dfd1e0afcb7b 361
ashleymills 11:dfd1e0afcb7b 362 int MMA8452::writeRegister(char addr, char *data, int nbytes) {
ashleymills 11:dfd1e0afcb7b 363 // writing multiple bytes is a little bit annoying because
ashleymills 11:dfd1e0afcb7b 364 // the I2C library doesn't support sending the address separately
ashleymills 11:dfd1e0afcb7b 365 // so we just do it manually
nherriot 0:bcf2aa85d7f9 366
ashleymills 11:dfd1e0afcb7b 367 // 1. tell I2C bus to start transaction
ashleymills 11:dfd1e0afcb7b 368 _i2c.start();
ashleymills 11:dfd1e0afcb7b 369 // 2. tell slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 370 if(_i2c.write(_writeAddress)!=1) {
ashleymills 11:dfd1e0afcb7b 371 return 1;
ashleymills 11:dfd1e0afcb7b 372 }
ashleymills 11:dfd1e0afcb7b 373 // 3. send the write address
ashleymills 11:dfd1e0afcb7b 374 if(_i2c.write(addr)!=1) {
ashleymills 11:dfd1e0afcb7b 375 return 1;
ashleymills 11:dfd1e0afcb7b 376 }
ashleymills 11:dfd1e0afcb7b 377 // 4. send the data to write
ashleymills 11:dfd1e0afcb7b 378 for(int i=0; i<nbytes; i++) {
ashleymills 11:dfd1e0afcb7b 379 if(_i2c.write(data[i])!=1) {
ashleymills 11:dfd1e0afcb7b 380 return 1;
ashleymills 11:dfd1e0afcb7b 381 }
ashleymills 11:dfd1e0afcb7b 382 }
ashleymills 11:dfd1e0afcb7b 383 // 5. tell I2C bus to end transaction
ashleymills 11:dfd1e0afcb7b 384 _i2c.stop();
ashleymills 11:dfd1e0afcb7b 385 return 0;
ashleymills 11:dfd1e0afcb7b 386 }
ashleymills 11:dfd1e0afcb7b 387
ashleymills 11:dfd1e0afcb7b 388 int MMA8452::readRegister(char addr, char *dst, int nbytes) {
ashleymills 11:dfd1e0afcb7b 389 // this is a bit odd, but basically proceeds like this
ashleymills 11:dfd1e0afcb7b 390 // 1. Send a start command
ashleymills 11:dfd1e0afcb7b 391 // 2. Tell the slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 392 // 3. Send the address of the register (addr)
ashleymills 11:dfd1e0afcb7b 393 // 4. Send another start command to delineate read portion
ashleymills 11:dfd1e0afcb7b 394 // 5. Tell the slave we want to read (slave address & read flag)
ashleymills 11:dfd1e0afcb7b 395 // 6. Read the register value bytes
ashleymills 11:dfd1e0afcb7b 396 // 7. Send a stop command
ashleymills 11:dfd1e0afcb7b 397
ashleymills 11:dfd1e0afcb7b 398 // we can wrap this process in the I2C library read and write commands
ashleymills 11:dfd1e0afcb7b 399 if(_i2c.write(MMA8452_ADDRESS,&addr,1,true)) {
ashleymills 11:dfd1e0afcb7b 400 return 1;
ashleymills 8:89272163f395 401 }
ashleymills 11:dfd1e0afcb7b 402 return _i2c.read(MMA8452_ADDRESS,dst,nbytes);
ashleymills 11:dfd1e0afcb7b 403 }
ashleymills 11:dfd1e0afcb7b 404
ashleymills 11:dfd1e0afcb7b 405 // most registers are 1 byte, so here is a convenience function
ashleymills 11:dfd1e0afcb7b 406 int MMA8452::readRegister(char addr, char *dst) {
ashleymills 11:dfd1e0afcb7b 407 return readRegister(addr,dst,1);
nherriot 0:bcf2aa85d7f9 408 }
ashleymills 11:dfd1e0afcb7b 409
ashleymills 19:4d6cd7140a71 410 MMA8452::BitDepth MMA8452::getBitDepth() {
ashleymills 19:4d6cd7140a71 411 return _bitDepth;
ashleymills 19:4d6cd7140a71 412 }
ashleymills 19:4d6cd7140a71 413
ashleymills 17:6e4232c421c0 414 #ifdef MMA8452_DEBUG
ashleymills 11:dfd1e0afcb7b 415 void MMA8452::debugRegister(char reg) {
ashleymills 11:dfd1e0afcb7b 416 // get register value
ashleymills 11:dfd1e0afcb7b 417 char v = 0;
ashleymills 11:dfd1e0afcb7b 418 if(readRegister(reg,&v)) {
ashleymills 17:6e4232c421c0 419 MMA8452_DBG("Error reading specified register");
ashleymills 11:dfd1e0afcb7b 420 return;
ashleymills 11:dfd1e0afcb7b 421 }
ashleymills 11:dfd1e0afcb7b 422 // print out details
ashleymills 11:dfd1e0afcb7b 423 switch(reg) {
ashleymills 11:dfd1e0afcb7b 424 case MMA8452_CTRL_REG_1:
ashleymills 17:6e4232c421c0 425 MMA8452_DBG("CTRL_REG_1 has value: 0x%x",v);
ashleymills 17:6e4232c421c0 426 MMA8452_DBG(" 7 ALSP_RATE_1: %d",(v&0x80)>>7);
ashleymills 17:6e4232c421c0 427 MMA8452_DBG(" 6 ALSP_RATE_0: %d",(v&0x40)>>6);
ashleymills 17:6e4232c421c0 428 MMA8452_DBG(" 5 DR2: %d", (v&0x20)>>5);
ashleymills 17:6e4232c421c0 429 MMA8452_DBG(" 4 DR1: %d", (v&0x10)>>4);
ashleymills 17:6e4232c421c0 430 MMA8452_DBG(" 3 DR0: %d", (v&0x08)>>3);
ashleymills 17:6e4232c421c0 431 MMA8452_DBG(" 2 LNOISE: %d", (v&0x04)>>2);
ashleymills 17:6e4232c421c0 432 MMA8452_DBG(" 1 FREAD: %d", (v&0x02)>>1);
ashleymills 17:6e4232c421c0 433 MMA8452_DBG(" 0 ACTIVE: %d", (v&0x01));
ashleymills 11:dfd1e0afcb7b 434 break;
ashleymills 11:dfd1e0afcb7b 435
ashleymills 11:dfd1e0afcb7b 436 case MMA8452_XYZ_DATA_CFG:
ashleymills 17:6e4232c421c0 437 MMA8452_DBG("XYZ_DATA_CFG has value: 0x%x",v);
ashleymills 17:6e4232c421c0 438 MMA8452_DBG(" 7 Unused: %d", (v&0x80)>>7);
ashleymills 17:6e4232c421c0 439 MMA8452_DBG(" 6 0: %d", (v&0x40)>>6);
ashleymills 17:6e4232c421c0 440 MMA8452_DBG(" 5 0: %d", (v&0x20)>>5);
ashleymills 17:6e4232c421c0 441 MMA8452_DBG(" 4 HPF_Out: %d",(v&0x10)>>4);
ashleymills 17:6e4232c421c0 442 MMA8452_DBG(" 3 0: %d", (v&0x08)>>3);
ashleymills 17:6e4232c421c0 443 MMA8452_DBG(" 2 0: %d", (v&0x04)>>2);
ashleymills 17:6e4232c421c0 444 MMA8452_DBG(" 1 FS1: %d", (v&0x02)>>1);
ashleymills 17:6e4232c421c0 445 MMA8452_DBG(" 0 FS0: %d", (v&0x01));
ashleymills 11:dfd1e0afcb7b 446 switch(v&0x03) {
ashleymills 11:dfd1e0afcb7b 447 case 0:
ashleymills 17:6e4232c421c0 448 MMA8452_DBG("Dynamic range: 2G");
ashleymills 11:dfd1e0afcb7b 449 break;
ashleymills 11:dfd1e0afcb7b 450 case 1:
ashleymills 17:6e4232c421c0 451 MMA8452_DBG("Dynamic range: 4G");
ashleymills 11:dfd1e0afcb7b 452 break;
ashleymills 11:dfd1e0afcb7b 453 case 2:
ashleymills 17:6e4232c421c0 454 MMA8452_DBG("Dynamic range: 8G");
ashleymills 11:dfd1e0afcb7b 455 break;
ashleymills 11:dfd1e0afcb7b 456 default:
ashleymills 17:6e4232c421c0 457 MMA8452_DBG("Unknown dynamic range");
ashleymills 11:dfd1e0afcb7b 458 break;
ashleymills 11:dfd1e0afcb7b 459 }
ashleymills 11:dfd1e0afcb7b 460 break;
ashleymills 11:dfd1e0afcb7b 461
ashleymills 12:172540ff6b8b 462 case MMA8452_STATUS:
ashleymills 17:6e4232c421c0 463 MMA8452_DBG("STATUS has value: 0x%x",v);
ashleymills 17:6e4232c421c0 464 MMA8452_DBG(" 7 ZYXOW: %d",(v&0x80)>>7);
ashleymills 17:6e4232c421c0 465 MMA8452_DBG(" 6 ZOW: %d", (v&0x40)>>6);
ashleymills 17:6e4232c421c0 466 MMA8452_DBG(" 5 YOW: %d", (v&0x20)>>5);
ashleymills 17:6e4232c421c0 467 MMA8452_DBG(" 4 XOW: %d", (v&0x10)>>4);
ashleymills 17:6e4232c421c0 468 MMA8452_DBG(" 3 ZYXDR: %d",(v&0x08)>>3);
ashleymills 17:6e4232c421c0 469 MMA8452_DBG(" 2 ZDR: %d", (v&0x04)>>2);
ashleymills 17:6e4232c421c0 470 MMA8452_DBG(" 1 YDR: %d", (v&0x02)>>1);
ashleymills 17:6e4232c421c0 471 MMA8452_DBG(" 0 XDR: %d", (v&0x01));
ashleymills 12:172540ff6b8b 472 break;
ashleymills 12:172540ff6b8b 473
ashleymills 11:dfd1e0afcb7b 474 default:
ashleymills 17:6e4232c421c0 475 MMA8452_DBG("Unknown register address: 0x%x",reg);
ashleymills 11:dfd1e0afcb7b 476 break;
ashleymills 11:dfd1e0afcb7b 477 }
ashleymills 17:6e4232c421c0 478 }
ashleymills 17:6e4232c421c0 479 #endif