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:
Fri Mar 07 14:53:40 2014 +0000
Revision:
21:a92a632a0cc7
Parent:
20:d55e9d7eb17e
Improved doxygen.

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 21:a92a632a0cc7 130 char MMA8452::getMaskedRegister(int addr, char mask) {
ashleymills 12:172540ff6b8b 131 char rval = 0;
ashleymills 21:a92a632a0cc7 132 if(readRegister(addr,&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 20:d55e9d7eb17e 247 int MMA8452::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 } else {
ashleymills 19:4d6cd7140a71 255 *x = eightBitToSigned(&buf[0]);
ashleymills 20:d55e9d7eb17e 256 }
ashleymills 20:d55e9d7eb17e 257 return 0;
ashleymills 20:d55e9d7eb17e 258 }
ashleymills 20:d55e9d7eb17e 259
ashleymills 20:d55e9d7eb17e 260 int MMA8452::readYCount(int *y) {
ashleymills 20:d55e9d7eb17e 261 char buf[2];
ashleymills 20:d55e9d7eb17e 262 if(readYRaw((char*)&buf)) {
ashleymills 20:d55e9d7eb17e 263 return 1;
ashleymills 20:d55e9d7eb17e 264 }
ashleymills 20:d55e9d7eb17e 265 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 20:d55e9d7eb17e 266 *y = twelveBitToSigned(&buf[0]);
ashleymills 20:d55e9d7eb17e 267 } else {
ashleymills 20:d55e9d7eb17e 268 *y = eightBitToSigned(&buf[0]);
ashleymills 19:4d6cd7140a71 269 }
ashleymills 20:d55e9d7eb17e 270 return 0;
ashleymills 20:d55e9d7eb17e 271 }
ashleymills 20:d55e9d7eb17e 272
ashleymills 20:d55e9d7eb17e 273 int MMA8452::readZCount(int *z) {
ashleymills 20:d55e9d7eb17e 274 char buf[2];
ashleymills 20:d55e9d7eb17e 275 if(readZRaw((char*)&buf)) {
ashleymills 20:d55e9d7eb17e 276 return 1;
ashleymills 20:d55e9d7eb17e 277 }
ashleymills 20:d55e9d7eb17e 278 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 20:d55e9d7eb17e 279 *z = twelveBitToSigned(&buf[0]);
ashleymills 20:d55e9d7eb17e 280 } else {
ashleymills 20:d55e9d7eb17e 281 *z = eightBitToSigned(&buf[0]);
ashleymills 20:d55e9d7eb17e 282 }
ashleymills 20:d55e9d7eb17e 283 return 0;
ashleymills 19:4d6cd7140a71 284 }
ashleymills 19:4d6cd7140a71 285
ashleymills 13:4bd8b4cd479d 286 double MMA8452::convertCountToGravity(int count, int countsPerG) {
ashleymills 13:4bd8b4cd479d 287 return (double)count/(double)countsPerG;
ashleymills 13:4bd8b4cd479d 288 }
ashleymills 13:4bd8b4cd479d 289
ashleymills 20:d55e9d7eb17e 290 int MMA8452::getCountsPerG() {
ashleymills 20:d55e9d7eb17e 291 // assume starting with DYNAMIC_RANGE_2G and BIT_DEPTH_12
ashleymills 13:4bd8b4cd479d 292 int countsPerG = 1024;
ashleymills 13:4bd8b4cd479d 293 if(_bitDepth==BIT_DEPTH_8) {
ashleymills 13:4bd8b4cd479d 294 countsPerG = 64;
ashleymills 13:4bd8b4cd479d 295 }
ashleymills 13:4bd8b4cd479d 296 switch(_dynamicRange) {
ashleymills 13:4bd8b4cd479d 297 case DYNAMIC_RANGE_4G:
ashleymills 13:4bd8b4cd479d 298 countsPerG /= 2;
ashleymills 13:4bd8b4cd479d 299 break;
ashleymills 13:4bd8b4cd479d 300 case DYNAMIC_RANGE_8G:
ashleymills 13:4bd8b4cd479d 301 countsPerG /= 4;
ashleymills 13:4bd8b4cd479d 302 break;
ashleymills 13:4bd8b4cd479d 303 }
ashleymills 20:d55e9d7eb17e 304 return countsPerG;
ashleymills 20:d55e9d7eb17e 305 }
ashleymills 20:d55e9d7eb17e 306
ashleymills 20:d55e9d7eb17e 307 int MMA8452::readXYZGravity(double *x, double *y, double *z) {
ashleymills 20:d55e9d7eb17e 308 int xCount = 0, yCount = 0, zCount = 0;
ashleymills 20:d55e9d7eb17e 309 if(readXYZCounts(&xCount,&yCount,&zCount)) {
ashleymills 20:d55e9d7eb17e 310 return 1;
ashleymills 20:d55e9d7eb17e 311 }
ashleymills 20:d55e9d7eb17e 312 int countsPerG = getCountsPerG();
ashleymills 13:4bd8b4cd479d 313
ashleymills 13:4bd8b4cd479d 314 *x = convertCountToGravity(xCount,countsPerG);
ashleymills 13:4bd8b4cd479d 315 *y = convertCountToGravity(yCount,countsPerG);
ashleymills 13:4bd8b4cd479d 316 *z = convertCountToGravity(zCount,countsPerG);
ashleymills 13:4bd8b4cd479d 317 return 0;
ashleymills 13:4bd8b4cd479d 318 }
ashleymills 13:4bd8b4cd479d 319
ashleymills 20:d55e9d7eb17e 320 int MMA8452::readXGravity(double *x) {
ashleymills 20:d55e9d7eb17e 321 int xCount = 0;
ashleymills 20:d55e9d7eb17e 322 if(readXCount(&xCount)) {
ashleymills 20:d55e9d7eb17e 323 return 1;
ashleymills 20:d55e9d7eb17e 324 }
ashleymills 20:d55e9d7eb17e 325 int countsPerG = getCountsPerG();
ashleymills 20:d55e9d7eb17e 326
ashleymills 20:d55e9d7eb17e 327 *x = convertCountToGravity(xCount,countsPerG);
ashleymills 20:d55e9d7eb17e 328 return 0;
ashleymills 20:d55e9d7eb17e 329 }
ashleymills 20:d55e9d7eb17e 330
ashleymills 20:d55e9d7eb17e 331 int MMA8452::readYGravity(double *y) {
ashleymills 20:d55e9d7eb17e 332 int yCount = 0;
ashleymills 20:d55e9d7eb17e 333 if(readYCount(&yCount)) {
ashleymills 20:d55e9d7eb17e 334 return 1;
ashleymills 20:d55e9d7eb17e 335 }
ashleymills 20:d55e9d7eb17e 336 int countsPerG = getCountsPerG();
ashleymills 20:d55e9d7eb17e 337
ashleymills 20:d55e9d7eb17e 338 *y = convertCountToGravity(yCount,countsPerG);
ashleymills 20:d55e9d7eb17e 339 return 0;
ashleymills 20:d55e9d7eb17e 340 }
ashleymills 20:d55e9d7eb17e 341
ashleymills 20:d55e9d7eb17e 342 int MMA8452::readZGravity(double *z) {
ashleymills 20:d55e9d7eb17e 343 int zCount = 0;
ashleymills 20:d55e9d7eb17e 344 if(readZCount(&zCount)) {
ashleymills 20:d55e9d7eb17e 345 return 1;
ashleymills 20:d55e9d7eb17e 346 }
ashleymills 20:d55e9d7eb17e 347 int countsPerG = getCountsPerG();
ashleymills 20:d55e9d7eb17e 348
ashleymills 20:d55e9d7eb17e 349 *z = convertCountToGravity(zCount,countsPerG);
ashleymills 20:d55e9d7eb17e 350 return 0;
ashleymills 20:d55e9d7eb17e 351 }
ashleymills 20:d55e9d7eb17e 352
ashleymills 11:dfd1e0afcb7b 353 // apply an AND mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 354 int MMA8452::logicalANDRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 355 char value = 0;
ashleymills 11:dfd1e0afcb7b 356 // read register value
ashleymills 11:dfd1e0afcb7b 357 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 358 return 0;
ashleymills 11:dfd1e0afcb7b 359 }
ashleymills 11:dfd1e0afcb7b 360 // apply mask
ashleymills 11:dfd1e0afcb7b 361 value &= mask;
ashleymills 11:dfd1e0afcb7b 362 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 363 }
ashleymills 11:dfd1e0afcb7b 364
ashleymills 11:dfd1e0afcb7b 365
ashleymills 11:dfd1e0afcb7b 366 // apply an OR mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 367 int MMA8452::logicalORRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 368 char value = 0;
ashleymills 11:dfd1e0afcb7b 369 // read register value
ashleymills 11:dfd1e0afcb7b 370 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 371 return 0;
ashleymills 11:dfd1e0afcb7b 372 }
ashleymills 11:dfd1e0afcb7b 373 // apply mask
ashleymills 11:dfd1e0afcb7b 374 value |= mask;
ashleymills 11:dfd1e0afcb7b 375 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 376 }
ashleymills 11:dfd1e0afcb7b 377
ashleymills 11:dfd1e0afcb7b 378 // apply an OR mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 379 int MMA8452::logicalXORRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 380 char value = 0;
ashleymills 11:dfd1e0afcb7b 381 // read register value
ashleymills 11:dfd1e0afcb7b 382 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 383 return 0;
ashleymills 11:dfd1e0afcb7b 384 }
ashleymills 11:dfd1e0afcb7b 385 // apply mask
ashleymills 11:dfd1e0afcb7b 386 value ^= mask;
ashleymills 11:dfd1e0afcb7b 387 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 388 }
ashleymills 11:dfd1e0afcb7b 389
ashleymills 11:dfd1e0afcb7b 390 // Write register (The device must be placed in Standby Mode to change the value of the registers)
ashleymills 11:dfd1e0afcb7b 391 int MMA8452::writeRegister(char addr, char data) {
ashleymills 11:dfd1e0afcb7b 392 // what this actually does is the following
ashleymills 11:dfd1e0afcb7b 393 // 1. tell I2C bus to start transaction
ashleymills 11:dfd1e0afcb7b 394 // 2. tell slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 395 // 3. send the write address
ashleymills 11:dfd1e0afcb7b 396 // 4. send the data to write
ashleymills 11:dfd1e0afcb7b 397 // 5. tell I2C bus to end transaction
ashleymills 11:dfd1e0afcb7b 398
ashleymills 11:dfd1e0afcb7b 399 // we can wrap this up in the I2C library write function
ashleymills 11:dfd1e0afcb7b 400 char buf[2] = {0,0};
ashleymills 11:dfd1e0afcb7b 401 buf[0] = addr;
ashleymills 11:dfd1e0afcb7b 402 buf[1] = data;
ashleymills 11:dfd1e0afcb7b 403 return _i2c.write(MMA8452_ADDRESS, buf,2);
ashleymills 11:dfd1e0afcb7b 404 // note, could also do return writeRegister(addr,&data,1);
nherriot 0:bcf2aa85d7f9 405 }
nherriot 0:bcf2aa85d7f9 406
ashleymills 13:4bd8b4cd479d 407 int MMA8452::eightBitToSigned(char *buf) {
ashleymills 13:4bd8b4cd479d 408 return (int8_t)*buf;
ashleymills 13:4bd8b4cd479d 409 }
ashleymills 13:4bd8b4cd479d 410
ashleymills 13:4bd8b4cd479d 411 int MMA8452::twelveBitToSigned(char *buf) {
ashleymills 13:4bd8b4cd479d 412 // cheat by using the int16_t internal type
ashleymills 13:4bd8b4cd479d 413 // all we need to do is convert to little-endian format and shift right
ashleymills 13:4bd8b4cd479d 414 int16_t x = 0;
ashleymills 13:4bd8b4cd479d 415 ((char*)&x)[1] = buf[0];
ashleymills 13:4bd8b4cd479d 416 ((char*)&x)[0] = buf[1];
ashleymills 13:4bd8b4cd479d 417 // note this only works because the below is an arithmetic right shift
ashleymills 13:4bd8b4cd479d 418 return x>>4;
ashleymills 13:4bd8b4cd479d 419 }
ashleymills 11:dfd1e0afcb7b 420
ashleymills 11:dfd1e0afcb7b 421 int MMA8452::writeRegister(char addr, char *data, int nbytes) {
ashleymills 11:dfd1e0afcb7b 422 // writing multiple bytes is a little bit annoying because
ashleymills 11:dfd1e0afcb7b 423 // the I2C library doesn't support sending the address separately
ashleymills 11:dfd1e0afcb7b 424 // so we just do it manually
nherriot 0:bcf2aa85d7f9 425
ashleymills 11:dfd1e0afcb7b 426 // 1. tell I2C bus to start transaction
ashleymills 11:dfd1e0afcb7b 427 _i2c.start();
ashleymills 11:dfd1e0afcb7b 428 // 2. tell slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 429 if(_i2c.write(_writeAddress)!=1) {
ashleymills 11:dfd1e0afcb7b 430 return 1;
ashleymills 11:dfd1e0afcb7b 431 }
ashleymills 11:dfd1e0afcb7b 432 // 3. send the write address
ashleymills 11:dfd1e0afcb7b 433 if(_i2c.write(addr)!=1) {
ashleymills 11:dfd1e0afcb7b 434 return 1;
ashleymills 11:dfd1e0afcb7b 435 }
ashleymills 11:dfd1e0afcb7b 436 // 4. send the data to write
ashleymills 11:dfd1e0afcb7b 437 for(int i=0; i<nbytes; i++) {
ashleymills 11:dfd1e0afcb7b 438 if(_i2c.write(data[i])!=1) {
ashleymills 11:dfd1e0afcb7b 439 return 1;
ashleymills 11:dfd1e0afcb7b 440 }
ashleymills 11:dfd1e0afcb7b 441 }
ashleymills 11:dfd1e0afcb7b 442 // 5. tell I2C bus to end transaction
ashleymills 11:dfd1e0afcb7b 443 _i2c.stop();
ashleymills 11:dfd1e0afcb7b 444 return 0;
ashleymills 11:dfd1e0afcb7b 445 }
ashleymills 11:dfd1e0afcb7b 446
ashleymills 11:dfd1e0afcb7b 447 int MMA8452::readRegister(char addr, char *dst, int nbytes) {
ashleymills 11:dfd1e0afcb7b 448 // this is a bit odd, but basically proceeds like this
ashleymills 11:dfd1e0afcb7b 449 // 1. Send a start command
ashleymills 11:dfd1e0afcb7b 450 // 2. Tell the slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 451 // 3. Send the address of the register (addr)
ashleymills 11:dfd1e0afcb7b 452 // 4. Send another start command to delineate read portion
ashleymills 11:dfd1e0afcb7b 453 // 5. Tell the slave we want to read (slave address & read flag)
ashleymills 11:dfd1e0afcb7b 454 // 6. Read the register value bytes
ashleymills 11:dfd1e0afcb7b 455 // 7. Send a stop command
ashleymills 11:dfd1e0afcb7b 456
ashleymills 11:dfd1e0afcb7b 457 // we can wrap this process in the I2C library read and write commands
ashleymills 11:dfd1e0afcb7b 458 if(_i2c.write(MMA8452_ADDRESS,&addr,1,true)) {
ashleymills 11:dfd1e0afcb7b 459 return 1;
ashleymills 8:89272163f395 460 }
ashleymills 11:dfd1e0afcb7b 461 return _i2c.read(MMA8452_ADDRESS,dst,nbytes);
ashleymills 11:dfd1e0afcb7b 462 }
ashleymills 11:dfd1e0afcb7b 463
ashleymills 11:dfd1e0afcb7b 464 // most registers are 1 byte, so here is a convenience function
ashleymills 11:dfd1e0afcb7b 465 int MMA8452::readRegister(char addr, char *dst) {
ashleymills 11:dfd1e0afcb7b 466 return readRegister(addr,dst,1);
nherriot 0:bcf2aa85d7f9 467 }
ashleymills 11:dfd1e0afcb7b 468
ashleymills 19:4d6cd7140a71 469 MMA8452::BitDepth MMA8452::getBitDepth() {
ashleymills 19:4d6cd7140a71 470 return _bitDepth;
ashleymills 19:4d6cd7140a71 471 }
ashleymills 19:4d6cd7140a71 472
ashleymills 17:6e4232c421c0 473 #ifdef MMA8452_DEBUG
ashleymills 11:dfd1e0afcb7b 474 void MMA8452::debugRegister(char reg) {
ashleymills 11:dfd1e0afcb7b 475 // get register value
ashleymills 11:dfd1e0afcb7b 476 char v = 0;
ashleymills 11:dfd1e0afcb7b 477 if(readRegister(reg,&v)) {
ashleymills 17:6e4232c421c0 478 MMA8452_DBG("Error reading specified register");
ashleymills 11:dfd1e0afcb7b 479 return;
ashleymills 11:dfd1e0afcb7b 480 }
ashleymills 11:dfd1e0afcb7b 481 // print out details
ashleymills 11:dfd1e0afcb7b 482 switch(reg) {
ashleymills 11:dfd1e0afcb7b 483 case MMA8452_CTRL_REG_1:
ashleymills 17:6e4232c421c0 484 MMA8452_DBG("CTRL_REG_1 has value: 0x%x",v);
ashleymills 17:6e4232c421c0 485 MMA8452_DBG(" 7 ALSP_RATE_1: %d",(v&0x80)>>7);
ashleymills 17:6e4232c421c0 486 MMA8452_DBG(" 6 ALSP_RATE_0: %d",(v&0x40)>>6);
ashleymills 17:6e4232c421c0 487 MMA8452_DBG(" 5 DR2: %d", (v&0x20)>>5);
ashleymills 17:6e4232c421c0 488 MMA8452_DBG(" 4 DR1: %d", (v&0x10)>>4);
ashleymills 17:6e4232c421c0 489 MMA8452_DBG(" 3 DR0: %d", (v&0x08)>>3);
ashleymills 17:6e4232c421c0 490 MMA8452_DBG(" 2 LNOISE: %d", (v&0x04)>>2);
ashleymills 17:6e4232c421c0 491 MMA8452_DBG(" 1 FREAD: %d", (v&0x02)>>1);
ashleymills 17:6e4232c421c0 492 MMA8452_DBG(" 0 ACTIVE: %d", (v&0x01));
ashleymills 11:dfd1e0afcb7b 493 break;
ashleymills 11:dfd1e0afcb7b 494
ashleymills 11:dfd1e0afcb7b 495 case MMA8452_XYZ_DATA_CFG:
ashleymills 17:6e4232c421c0 496 MMA8452_DBG("XYZ_DATA_CFG has value: 0x%x",v);
ashleymills 17:6e4232c421c0 497 MMA8452_DBG(" 7 Unused: %d", (v&0x80)>>7);
ashleymills 17:6e4232c421c0 498 MMA8452_DBG(" 6 0: %d", (v&0x40)>>6);
ashleymills 17:6e4232c421c0 499 MMA8452_DBG(" 5 0: %d", (v&0x20)>>5);
ashleymills 17:6e4232c421c0 500 MMA8452_DBG(" 4 HPF_Out: %d",(v&0x10)>>4);
ashleymills 17:6e4232c421c0 501 MMA8452_DBG(" 3 0: %d", (v&0x08)>>3);
ashleymills 17:6e4232c421c0 502 MMA8452_DBG(" 2 0: %d", (v&0x04)>>2);
ashleymills 17:6e4232c421c0 503 MMA8452_DBG(" 1 FS1: %d", (v&0x02)>>1);
ashleymills 17:6e4232c421c0 504 MMA8452_DBG(" 0 FS0: %d", (v&0x01));
ashleymills 11:dfd1e0afcb7b 505 switch(v&0x03) {
ashleymills 11:dfd1e0afcb7b 506 case 0:
ashleymills 17:6e4232c421c0 507 MMA8452_DBG("Dynamic range: 2G");
ashleymills 11:dfd1e0afcb7b 508 break;
ashleymills 11:dfd1e0afcb7b 509 case 1:
ashleymills 17:6e4232c421c0 510 MMA8452_DBG("Dynamic range: 4G");
ashleymills 11:dfd1e0afcb7b 511 break;
ashleymills 11:dfd1e0afcb7b 512 case 2:
ashleymills 17:6e4232c421c0 513 MMA8452_DBG("Dynamic range: 8G");
ashleymills 11:dfd1e0afcb7b 514 break;
ashleymills 11:dfd1e0afcb7b 515 default:
ashleymills 17:6e4232c421c0 516 MMA8452_DBG("Unknown dynamic range");
ashleymills 11:dfd1e0afcb7b 517 break;
ashleymills 11:dfd1e0afcb7b 518 }
ashleymills 11:dfd1e0afcb7b 519 break;
ashleymills 11:dfd1e0afcb7b 520
ashleymills 12:172540ff6b8b 521 case MMA8452_STATUS:
ashleymills 17:6e4232c421c0 522 MMA8452_DBG("STATUS has value: 0x%x",v);
ashleymills 17:6e4232c421c0 523 MMA8452_DBG(" 7 ZYXOW: %d",(v&0x80)>>7);
ashleymills 17:6e4232c421c0 524 MMA8452_DBG(" 6 ZOW: %d", (v&0x40)>>6);
ashleymills 17:6e4232c421c0 525 MMA8452_DBG(" 5 YOW: %d", (v&0x20)>>5);
ashleymills 17:6e4232c421c0 526 MMA8452_DBG(" 4 XOW: %d", (v&0x10)>>4);
ashleymills 17:6e4232c421c0 527 MMA8452_DBG(" 3 ZYXDR: %d",(v&0x08)>>3);
ashleymills 17:6e4232c421c0 528 MMA8452_DBG(" 2 ZDR: %d", (v&0x04)>>2);
ashleymills 17:6e4232c421c0 529 MMA8452_DBG(" 1 YDR: %d", (v&0x02)>>1);
ashleymills 17:6e4232c421c0 530 MMA8452_DBG(" 0 XDR: %d", (v&0x01));
ashleymills 12:172540ff6b8b 531 break;
ashleymills 12:172540ff6b8b 532
ashleymills 11:dfd1e0afcb7b 533 default:
ashleymills 17:6e4232c421c0 534 MMA8452_DBG("Unknown register address: 0x%x",reg);
ashleymills 11:dfd1e0afcb7b 535 break;
ashleymills 11:dfd1e0afcb7b 536 }
ashleymills 17:6e4232c421c0 537 }
ashleymills 17:6e4232c421c0 538 #endif