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:
Wed Mar 05 15:09:21 2014 +0000
Revision:
14:0602b45ca70f
Parent:
13:4bd8b4cd479d
Child:
16:d6dde2318edc
Updated author priority to reflect work

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 11:dfd1e0afcb7b 23 extern Serial pc;
nherriot 0:bcf2aa85d7f9 24
nherriot 0:bcf2aa85d7f9 25 // Connect module at I2C address using I2C port pins sda and scl
ashleymills 11:dfd1e0afcb7b 26 MMA8452::MMA8452(PinName sda, PinName scl, int frequency) : _i2c(sda, scl) , _frequency(frequency) {
ashleymills 11:dfd1e0afcb7b 27 DBG("Creating MMA8452");
ashleymills 12:172540ff6b8b 28
ashleymills 12:172540ff6b8b 29 // set I2C frequency
ashleymills 11:dfd1e0afcb7b 30 _i2c.frequency(_frequency);
ashleymills 11:dfd1e0afcb7b 31
ashleymills 12:172540ff6b8b 32 // setup read and write addresses for convenience
ashleymills 11:dfd1e0afcb7b 33 _readAddress = MMA8452_ADDRESS | 0x01;
ashleymills 11:dfd1e0afcb7b 34 _writeAddress = MMA8452_ADDRESS & 0xFE;
ashleymills 12:172540ff6b8b 35
ashleymills 12:172540ff6b8b 36 // set some defaults
ashleymills 12:172540ff6b8b 37 _bitDepth = BIT_DEPTH_UNKNOWN;
ashleymills 12:172540ff6b8b 38 setBitDepth(BIT_DEPTH_12);
ashleymills 13:4bd8b4cd479d 39 _dynamicRange = DYNAMIC_RANGE_UNKNOWN;
ashleymills 13:4bd8b4cd479d 40 setDynamicRange(DYNAMIC_RANGE_2G);
ashleymills 13:4bd8b4cd479d 41
ashleymills 11:dfd1e0afcb7b 42 DBG("Done");
nherriot 0:bcf2aa85d7f9 43 }
nherriot 0:bcf2aa85d7f9 44
nherriot 0:bcf2aa85d7f9 45
nherriot 0:bcf2aa85d7f9 46 // Destroys instance
ashleymills 10:ca9ba7ad4e94 47 MMA8452::~MMA8452() {}
nherriot 0:bcf2aa85d7f9 48
nherriot 0:bcf2aa85d7f9 49 // Setting the control register bit 1 to true to activate the MMA8452
ashleymills 10:ca9ba7ad4e94 50 int MMA8452::activate() {
ashleymills 6:f6bde04bf8be 51 // perform write and return error code
ashleymills 12:172540ff6b8b 52 return logicalORRegister(MMA8452_CTRL_REG_1,MMA8452_ACTIVE_MASK);
nherriot 3:ffb0b1650ca2 53 }
nherriot 3:ffb0b1650ca2 54
ashleymills 11:dfd1e0afcb7b 55 // Setting the control register bit 1 to 0 to standby the MMA8452
ashleymills 11:dfd1e0afcb7b 56 int MMA8452::standby() {
ashleymills 11:dfd1e0afcb7b 57 // perform write and return error code
ashleymills 12:172540ff6b8b 58 return logicalANDRegister(MMA8452_CTRL_REG_1,MMA8452_STANDBY_MASK);
nherriot 5:b3d0abd97e55 59 }
nherriot 5:b3d0abd97e55 60
ashleymills 11:dfd1e0afcb7b 61 // this reads a register, applies a bitmask with logical AND, sets a value with logical OR,
ashleymills 11:dfd1e0afcb7b 62 // and optionally goes into and out of standby at the beginning and end of the function respectively
ashleymills 11:dfd1e0afcb7b 63 int MMA8452::maskAndApplyRegister(char reg, char mask, char value, int toggleActivation) {
ashleymills 11:dfd1e0afcb7b 64 if(toggleActivation) {
ashleymills 11:dfd1e0afcb7b 65 if(standby()) {
ashleymills 11:dfd1e0afcb7b 66 return 1;
ashleymills 11:dfd1e0afcb7b 67 }
ashleymills 11:dfd1e0afcb7b 68 }
ashleymills 11:dfd1e0afcb7b 69
ashleymills 11:dfd1e0afcb7b 70 // read from register
ashleymills 11:dfd1e0afcb7b 71 char oldValue = 0;
ashleymills 11:dfd1e0afcb7b 72 if(readRegister(reg,&oldValue)) {
ashleymills 11:dfd1e0afcb7b 73 return 1;
ashleymills 11:dfd1e0afcb7b 74 }
ashleymills 11:dfd1e0afcb7b 75
ashleymills 11:dfd1e0afcb7b 76 // apply bitmask
ashleymills 11:dfd1e0afcb7b 77 oldValue &= mask;
ashleymills 11:dfd1e0afcb7b 78
ashleymills 11:dfd1e0afcb7b 79 // set value
ashleymills 11:dfd1e0afcb7b 80 oldValue |= value;
ashleymills 11:dfd1e0afcb7b 81
ashleymills 11:dfd1e0afcb7b 82 // write back to register
ashleymills 11:dfd1e0afcb7b 83 if(writeRegister(reg,oldValue)) {
ashleymills 11:dfd1e0afcb7b 84 return 1;
ashleymills 11:dfd1e0afcb7b 85 }
ashleymills 11:dfd1e0afcb7b 86
ashleymills 11:dfd1e0afcb7b 87 if(toggleActivation) {
ashleymills 11:dfd1e0afcb7b 88 if(activate()) {
ashleymills 11:dfd1e0afcb7b 89 return 1;
ashleymills 11:dfd1e0afcb7b 90 }
ashleymills 11:dfd1e0afcb7b 91 }
ashleymills 11:dfd1e0afcb7b 92 return 0;
nherriot 0:bcf2aa85d7f9 93 }
nherriot 0:bcf2aa85d7f9 94
ashleymills 11:dfd1e0afcb7b 95 int MMA8452::setDynamicRange(DynamicRange range, int toggleActivation) {
ashleymills 13:4bd8b4cd479d 96 _dynamicRange = range;
ashleymills 11:dfd1e0afcb7b 97 return maskAndApplyRegister(
ashleymills 11:dfd1e0afcb7b 98 MMA8452_XYZ_DATA_CFG,
ashleymills 11:dfd1e0afcb7b 99 MMA8452_DYNAMIC_RANGE_MASK,
ashleymills 11:dfd1e0afcb7b 100 range,
ashleymills 11:dfd1e0afcb7b 101 toggleActivation
ashleymills 11:dfd1e0afcb7b 102 );
nherriot 0:bcf2aa85d7f9 103 }
nherriot 0:bcf2aa85d7f9 104
ashleymills 11:dfd1e0afcb7b 105 int MMA8452::setDataRate(DataRateHz dataRate, int toggleActivation) {
ashleymills 11:dfd1e0afcb7b 106 return maskAndApplyRegister(
ashleymills 11:dfd1e0afcb7b 107 MMA8452_CTRL_REG_1,
ashleymills 11:dfd1e0afcb7b 108 MMA8452_DATA_RATE_MASK,
ashleymills 11:dfd1e0afcb7b 109 dataRate<<MMA8452_DATA_RATE_MASK_SHIFT,
ashleymills 11:dfd1e0afcb7b 110 toggleActivation
ashleymills 11:dfd1e0afcb7b 111 );
nherriot 3:ffb0b1650ca2 112 }
nherriot 3:ffb0b1650ca2 113
ashleymills 11:dfd1e0afcb7b 114 int MMA8452::setBitDepth(BitDepth depth,int toggleActivation) {
ashleymills 12:172540ff6b8b 115 _bitDepth = depth;
ashleymills 11:dfd1e0afcb7b 116 return maskAndApplyRegister(
ashleymills 11:dfd1e0afcb7b 117 MMA8452_CTRL_REG_1,
ashleymills 11:dfd1e0afcb7b 118 MMA8452_BIT_DEPTH_MASK,
ashleymills 11:dfd1e0afcb7b 119 depth<<MMA8452_BIT_DEPTH_MASK_SHIFT,
ashleymills 11:dfd1e0afcb7b 120 toggleActivation
ashleymills 11:dfd1e0afcb7b 121 );
nherriot 3:ffb0b1650ca2 122 }
nherriot 3:ffb0b1650ca2 123
ashleymills 12:172540ff6b8b 124 int MMA8452::isXYZReady() {
ashleymills 12:172540ff6b8b 125 char rval = 0;
ashleymills 12:172540ff6b8b 126 if(readRegister(MMA8452_STATUS,&rval)) {
ashleymills 12:172540ff6b8b 127 return 0;
ashleymills 12:172540ff6b8b 128 }
ashleymills 12:172540ff6b8b 129 return (rval&MMA8452_STATUS_ZYXDR_MASK);
nherriot 1:ef026bf28798 130 }
ashleymills 12:172540ff6b8b 131
ashleymills 12:172540ff6b8b 132 int MMA8452::getDeviceID(char *dst) {
ashleymills 12:172540ff6b8b 133 return readRegister(MMA8452_WHO_AM_I,dst);
nherriot 3:ffb0b1650ca2 134 }
nherriot 3:ffb0b1650ca2 135
ashleymills 12:172540ff6b8b 136 int MMA8452::getStatus(char* dst) {
ashleymills 12:172540ff6b8b 137 return readRegister(MMA8452_STATUS,dst);
nherriot 3:ffb0b1650ca2 138 }
nherriot 0:bcf2aa85d7f9 139
ashleymills 11:dfd1e0afcb7b 140 MMA8452::DynamicRange MMA8452::getDynamicRange() {
ashleymills 11:dfd1e0afcb7b 141 char rval = 0;
ashleymills 12:172540ff6b8b 142 if(readRegister(MMA8452_XYZ_DATA_CFG,&rval)) {
ashleymills 11:dfd1e0afcb7b 143 return MMA8452::DYNAMIC_RANGE_UNKNOWN;
ashleymills 11:dfd1e0afcb7b 144 }
ashleymills 11:dfd1e0afcb7b 145 rval &= (MMA8452_DYNAMIC_RANGE_MASK^0xFF);
ashleymills 11:dfd1e0afcb7b 146 return (MMA8452::DynamicRange)rval;
ashleymills 11:dfd1e0afcb7b 147 }
ashleymills 11:dfd1e0afcb7b 148
ashleymills 11:dfd1e0afcb7b 149 MMA8452::DataRateHz MMA8452::getDataRate() {
ashleymills 11:dfd1e0afcb7b 150 char rval = 0;
ashleymills 11:dfd1e0afcb7b 151 if(readRegister(MMA8452_CTRL_REG_1,&rval)) {
ashleymills 11:dfd1e0afcb7b 152 return MMA8452::RATE_UNKNOWN;
ashleymills 11:dfd1e0afcb7b 153 }
ashleymills 11:dfd1e0afcb7b 154 // logical AND with inverse of mask
ashleymills 11:dfd1e0afcb7b 155 rval = rval&(MMA8452_DATA_RATE_MASK^0xFF);
ashleymills 11:dfd1e0afcb7b 156 // shift back into position
ashleymills 11:dfd1e0afcb7b 157 rval >>= MMA8452_DATA_RATE_MASK_SHIFT;
ashleymills 11:dfd1e0afcb7b 158 return (MMA8452::DataRateHz)rval;
ashleymills 11:dfd1e0afcb7b 159 }
ashleymills 11:dfd1e0afcb7b 160
nherriot 0:bcf2aa85d7f9 161 // Reads xyz
ashleymills 13:4bd8b4cd479d 162 int MMA8452::readXYZRaw(char *dst) {
ashleymills 12:172540ff6b8b 163 if(_bitDepth==BIT_DEPTH_UNKNOWN) {
ashleymills 12:172540ff6b8b 164 return 1;
ashleymills 12:172540ff6b8b 165 }
ashleymills 12:172540ff6b8b 166 int readLen = 3;
ashleymills 12:172540ff6b8b 167 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 12:172540ff6b8b 168 readLen = 6;
ashleymills 12:172540ff6b8b 169 }
ashleymills 12:172540ff6b8b 170 return readRegister(MMA8452_OUT_X_MSB,dst,readLen);
nherriot 1:ef026bf28798 171 }
nherriot 0:bcf2aa85d7f9 172
ashleymills 13:4bd8b4cd479d 173 int MMA8452::readXYZCounts(int *x, int *y, int *z) {
ashleymills 13:4bd8b4cd479d 174 char buf[6];
ashleymills 13:4bd8b4cd479d 175 if(readXYZRaw((char*)&buf)) {
ashleymills 13:4bd8b4cd479d 176 return 1;
ashleymills 13:4bd8b4cd479d 177 }
ashleymills 13:4bd8b4cd479d 178 if(_bitDepth==BIT_DEPTH_12) {
ashleymills 13:4bd8b4cd479d 179 *x = twelveBitToSigned(&buf[0]);
ashleymills 13:4bd8b4cd479d 180 *y = twelveBitToSigned(&buf[2]);
ashleymills 13:4bd8b4cd479d 181 *z = twelveBitToSigned(&buf[4]);
ashleymills 13:4bd8b4cd479d 182 } else {
ashleymills 13:4bd8b4cd479d 183 *x = eightBitToSigned(&buf[0]);
ashleymills 13:4bd8b4cd479d 184 *y = eightBitToSigned(&buf[1]);
ashleymills 13:4bd8b4cd479d 185 *z = eightBitToSigned(&buf[2]);
ashleymills 13:4bd8b4cd479d 186 }
ashleymills 13:4bd8b4cd479d 187
ashleymills 13:4bd8b4cd479d 188 return 0;
ashleymills 13:4bd8b4cd479d 189 }
ashleymills 13:4bd8b4cd479d 190
ashleymills 13:4bd8b4cd479d 191 double MMA8452::convertCountToGravity(int count, int countsPerG) {
ashleymills 13:4bd8b4cd479d 192 return (double)count/(double)countsPerG;
ashleymills 13:4bd8b4cd479d 193 }
ashleymills 13:4bd8b4cd479d 194
ashleymills 13:4bd8b4cd479d 195 int MMA8452::readXYZGravity(double *x, double *y, double *z) {
ashleymills 13:4bd8b4cd479d 196 int xCount = 0, yCount = 0, zCount = 0;
ashleymills 13:4bd8b4cd479d 197 if(readXYZCounts(&xCount,&yCount,&zCount)) {
ashleymills 13:4bd8b4cd479d 198 return 1;
ashleymills 13:4bd8b4cd479d 199 }
ashleymills 13:4bd8b4cd479d 200
ashleymills 13:4bd8b4cd479d 201 // assume starting with DYNAMIC_RANGE_2G and BIT_DEPTH_12
ashleymills 13:4bd8b4cd479d 202 int countsPerG = 1024;
ashleymills 13:4bd8b4cd479d 203 if(_bitDepth==BIT_DEPTH_8) {
ashleymills 13:4bd8b4cd479d 204 countsPerG = 64;
ashleymills 13:4bd8b4cd479d 205 }
ashleymills 13:4bd8b4cd479d 206 switch(_dynamicRange) {
ashleymills 13:4bd8b4cd479d 207 case DYNAMIC_RANGE_4G:
ashleymills 13:4bd8b4cd479d 208 countsPerG /= 2;
ashleymills 13:4bd8b4cd479d 209 break;
ashleymills 13:4bd8b4cd479d 210 case DYNAMIC_RANGE_8G:
ashleymills 13:4bd8b4cd479d 211 countsPerG /= 4;
ashleymills 13:4bd8b4cd479d 212 break;
ashleymills 13:4bd8b4cd479d 213 }
ashleymills 13:4bd8b4cd479d 214
ashleymills 13:4bd8b4cd479d 215 *x = convertCountToGravity(xCount,countsPerG);
ashleymills 13:4bd8b4cd479d 216 *y = convertCountToGravity(yCount,countsPerG);
ashleymills 13:4bd8b4cd479d 217 *z = convertCountToGravity(zCount,countsPerG);
ashleymills 13:4bd8b4cd479d 218 return 0;
ashleymills 13:4bd8b4cd479d 219 }
ashleymills 13:4bd8b4cd479d 220
ashleymills 11:dfd1e0afcb7b 221 // apply an AND mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 222 int MMA8452::logicalANDRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 223 char value = 0;
ashleymills 11:dfd1e0afcb7b 224 // read register value
ashleymills 11:dfd1e0afcb7b 225 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 226 return 0;
ashleymills 11:dfd1e0afcb7b 227 }
ashleymills 11:dfd1e0afcb7b 228 // apply mask
ashleymills 11:dfd1e0afcb7b 229 value &= mask;
ashleymills 11:dfd1e0afcb7b 230 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 231 }
ashleymills 11:dfd1e0afcb7b 232
ashleymills 11:dfd1e0afcb7b 233
ashleymills 11:dfd1e0afcb7b 234 // apply an OR mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 235 int MMA8452::logicalORRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 236 char value = 0;
ashleymills 11:dfd1e0afcb7b 237 // read register value
ashleymills 11:dfd1e0afcb7b 238 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 239 return 0;
ashleymills 11:dfd1e0afcb7b 240 }
ashleymills 11:dfd1e0afcb7b 241 // apply mask
ashleymills 11:dfd1e0afcb7b 242 value |= mask;
ashleymills 11:dfd1e0afcb7b 243 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 244 }
ashleymills 11:dfd1e0afcb7b 245
ashleymills 11:dfd1e0afcb7b 246 // apply an OR mask to a register. read register value, apply mask, write it back
ashleymills 11:dfd1e0afcb7b 247 int MMA8452::logicalXORRegister(char addr, char mask) {
ashleymills 11:dfd1e0afcb7b 248 char value = 0;
ashleymills 11:dfd1e0afcb7b 249 // read register value
ashleymills 11:dfd1e0afcb7b 250 if(readRegister(addr,&value)) {
ashleymills 11:dfd1e0afcb7b 251 return 0;
ashleymills 11:dfd1e0afcb7b 252 }
ashleymills 11:dfd1e0afcb7b 253 // apply mask
ashleymills 11:dfd1e0afcb7b 254 value ^= mask;
ashleymills 11:dfd1e0afcb7b 255 return writeRegister(addr,value);
ashleymills 11:dfd1e0afcb7b 256 }
ashleymills 11:dfd1e0afcb7b 257
ashleymills 11:dfd1e0afcb7b 258 // Write register (The device must be placed in Standby Mode to change the value of the registers)
ashleymills 11:dfd1e0afcb7b 259 int MMA8452::writeRegister(char addr, char data) {
ashleymills 11:dfd1e0afcb7b 260 // what this actually does is the following
ashleymills 11:dfd1e0afcb7b 261 // 1. tell I2C bus to start transaction
ashleymills 11:dfd1e0afcb7b 262 // 2. tell slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 263 // 3. send the write address
ashleymills 11:dfd1e0afcb7b 264 // 4. send the data to write
ashleymills 11:dfd1e0afcb7b 265 // 5. tell I2C bus to end transaction
ashleymills 11:dfd1e0afcb7b 266
ashleymills 11:dfd1e0afcb7b 267 // we can wrap this up in the I2C library write function
ashleymills 11:dfd1e0afcb7b 268 char buf[2] = {0,0};
ashleymills 11:dfd1e0afcb7b 269 buf[0] = addr;
ashleymills 11:dfd1e0afcb7b 270 buf[1] = data;
ashleymills 11:dfd1e0afcb7b 271 return _i2c.write(MMA8452_ADDRESS, buf,2);
ashleymills 11:dfd1e0afcb7b 272 // note, could also do return writeRegister(addr,&data,1);
nherriot 0:bcf2aa85d7f9 273 }
nherriot 0:bcf2aa85d7f9 274
ashleymills 13:4bd8b4cd479d 275 int MMA8452::eightBitToSigned(char *buf) {
ashleymills 13:4bd8b4cd479d 276 return (int8_t)*buf;
ashleymills 13:4bd8b4cd479d 277 }
ashleymills 13:4bd8b4cd479d 278
ashleymills 13:4bd8b4cd479d 279 int MMA8452::twelveBitToSigned(char *buf) {
ashleymills 13:4bd8b4cd479d 280 // cheat by using the int16_t internal type
ashleymills 13:4bd8b4cd479d 281 // all we need to do is convert to little-endian format and shift right
ashleymills 13:4bd8b4cd479d 282 int16_t x = 0;
ashleymills 13:4bd8b4cd479d 283 ((char*)&x)[1] = buf[0];
ashleymills 13:4bd8b4cd479d 284 ((char*)&x)[0] = buf[1];
ashleymills 13:4bd8b4cd479d 285 // note this only works because the below is an arithmetic right shift
ashleymills 13:4bd8b4cd479d 286 return x>>4;
ashleymills 13:4bd8b4cd479d 287 }
ashleymills 11:dfd1e0afcb7b 288
ashleymills 11:dfd1e0afcb7b 289 int MMA8452::writeRegister(char addr, char *data, int nbytes) {
ashleymills 11:dfd1e0afcb7b 290 // writing multiple bytes is a little bit annoying because
ashleymills 11:dfd1e0afcb7b 291 // the I2C library doesn't support sending the address separately
ashleymills 11:dfd1e0afcb7b 292 // so we just do it manually
nherriot 0:bcf2aa85d7f9 293
ashleymills 11:dfd1e0afcb7b 294 // 1. tell I2C bus to start transaction
ashleymills 11:dfd1e0afcb7b 295 _i2c.start();
ashleymills 11:dfd1e0afcb7b 296 // 2. tell slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 297 if(_i2c.write(_writeAddress)!=1) {
ashleymills 11:dfd1e0afcb7b 298 return 1;
ashleymills 11:dfd1e0afcb7b 299 }
ashleymills 11:dfd1e0afcb7b 300 // 3. send the write address
ashleymills 11:dfd1e0afcb7b 301 if(_i2c.write(addr)!=1) {
ashleymills 11:dfd1e0afcb7b 302 return 1;
ashleymills 11:dfd1e0afcb7b 303 }
ashleymills 11:dfd1e0afcb7b 304 // 4. send the data to write
ashleymills 11:dfd1e0afcb7b 305 for(int i=0; i<nbytes; i++) {
ashleymills 11:dfd1e0afcb7b 306 if(_i2c.write(data[i])!=1) {
ashleymills 11:dfd1e0afcb7b 307 return 1;
ashleymills 11:dfd1e0afcb7b 308 }
ashleymills 11:dfd1e0afcb7b 309 }
ashleymills 11:dfd1e0afcb7b 310 // 5. tell I2C bus to end transaction
ashleymills 11:dfd1e0afcb7b 311 _i2c.stop();
ashleymills 11:dfd1e0afcb7b 312 return 0;
ashleymills 11:dfd1e0afcb7b 313 }
ashleymills 11:dfd1e0afcb7b 314
ashleymills 11:dfd1e0afcb7b 315 int MMA8452::readRegister(char addr, char *dst, int nbytes) {
ashleymills 11:dfd1e0afcb7b 316 // this is a bit odd, but basically proceeds like this
ashleymills 11:dfd1e0afcb7b 317 // 1. Send a start command
ashleymills 11:dfd1e0afcb7b 318 // 2. Tell the slave we want to write (slave address & write flag)
ashleymills 11:dfd1e0afcb7b 319 // 3. Send the address of the register (addr)
ashleymills 11:dfd1e0afcb7b 320 // 4. Send another start command to delineate read portion
ashleymills 11:dfd1e0afcb7b 321 // 5. Tell the slave we want to read (slave address & read flag)
ashleymills 11:dfd1e0afcb7b 322 // 6. Read the register value bytes
ashleymills 11:dfd1e0afcb7b 323 // 7. Send a stop command
ashleymills 11:dfd1e0afcb7b 324
ashleymills 11:dfd1e0afcb7b 325 // we can wrap this process in the I2C library read and write commands
ashleymills 11:dfd1e0afcb7b 326 if(_i2c.write(MMA8452_ADDRESS,&addr,1,true)) {
ashleymills 11:dfd1e0afcb7b 327 return 1;
ashleymills 8:89272163f395 328 }
ashleymills 11:dfd1e0afcb7b 329 return _i2c.read(MMA8452_ADDRESS,dst,nbytes);
ashleymills 11:dfd1e0afcb7b 330 }
ashleymills 11:dfd1e0afcb7b 331
ashleymills 11:dfd1e0afcb7b 332 // most registers are 1 byte, so here is a convenience function
ashleymills 11:dfd1e0afcb7b 333 int MMA8452::readRegister(char addr, char *dst) {
ashleymills 11:dfd1e0afcb7b 334 return readRegister(addr,dst,1);
nherriot 0:bcf2aa85d7f9 335 }
ashleymills 11:dfd1e0afcb7b 336
ashleymills 11:dfd1e0afcb7b 337 void MMA8452::debugRegister(char reg) {
ashleymills 11:dfd1e0afcb7b 338 // get register value
ashleymills 11:dfd1e0afcb7b 339 char v = 0;
ashleymills 11:dfd1e0afcb7b 340 if(readRegister(reg,&v)) {
ashleymills 12:172540ff6b8b 341 DBG("Error reading specified register");
ashleymills 11:dfd1e0afcb7b 342 return;
ashleymills 11:dfd1e0afcb7b 343 }
ashleymills 11:dfd1e0afcb7b 344 // print out details
ashleymills 11:dfd1e0afcb7b 345 switch(reg) {
ashleymills 11:dfd1e0afcb7b 346 case MMA8452_CTRL_REG_1:
ashleymills 11:dfd1e0afcb7b 347 DBG("CTRL_REG_1 has value: 0x%x",v);
ashleymills 11:dfd1e0afcb7b 348 DBG(" 7 ALSP_RATE_1: %d",(v&0x80)>>7);
ashleymills 11:dfd1e0afcb7b 349 DBG(" 6 ALSP_RATE_0: %d",(v&0x40)>>6);
ashleymills 11:dfd1e0afcb7b 350 DBG(" 5 DR2: %d", (v&0x20)>>5);
ashleymills 11:dfd1e0afcb7b 351 DBG(" 4 DR1: %d", (v&0x10)>>4);
ashleymills 11:dfd1e0afcb7b 352 DBG(" 3 DR0: %d", (v&0x08)>>3);
ashleymills 11:dfd1e0afcb7b 353 DBG(" 2 LNOISE: %d", (v&0x04)>>2);
ashleymills 11:dfd1e0afcb7b 354 DBG(" 1 FREAD: %d", (v&0x02)>>1);
ashleymills 11:dfd1e0afcb7b 355 DBG(" 0 ACTIVE: %d", (v&0x01));
ashleymills 11:dfd1e0afcb7b 356 break;
ashleymills 11:dfd1e0afcb7b 357
ashleymills 11:dfd1e0afcb7b 358 case MMA8452_XYZ_DATA_CFG:
ashleymills 11:dfd1e0afcb7b 359 DBG("XYZ_DATA_CFG has value: 0x%x",v);
ashleymills 11:dfd1e0afcb7b 360 DBG(" 7 Unused: %d", (v&0x80)>>7);
ashleymills 11:dfd1e0afcb7b 361 DBG(" 6 0: %d", (v&0x40)>>6);
ashleymills 11:dfd1e0afcb7b 362 DBG(" 5 0: %d", (v&0x20)>>5);
ashleymills 11:dfd1e0afcb7b 363 DBG(" 4 HPF_Out: %d",(v&0x10)>>4);
ashleymills 11:dfd1e0afcb7b 364 DBG(" 3 0: %d", (v&0x08)>>3);
ashleymills 11:dfd1e0afcb7b 365 DBG(" 2 0: %d", (v&0x04)>>2);
ashleymills 11:dfd1e0afcb7b 366 DBG(" 1 FS1: %d", (v&0x02)>>1);
ashleymills 11:dfd1e0afcb7b 367 DBG(" 0 FS0: %d", (v&0x01));
ashleymills 11:dfd1e0afcb7b 368 switch(v&0x03) {
ashleymills 11:dfd1e0afcb7b 369 case 0:
ashleymills 11:dfd1e0afcb7b 370 DBG("Dynamic range: 2G");
ashleymills 11:dfd1e0afcb7b 371 break;
ashleymills 11:dfd1e0afcb7b 372 case 1:
ashleymills 11:dfd1e0afcb7b 373 DBG("Dynamic range: 4G");
ashleymills 11:dfd1e0afcb7b 374 break;
ashleymills 11:dfd1e0afcb7b 375 case 2:
ashleymills 11:dfd1e0afcb7b 376 DBG("Dynamic range: 8G");
ashleymills 11:dfd1e0afcb7b 377 break;
ashleymills 11:dfd1e0afcb7b 378 default:
ashleymills 11:dfd1e0afcb7b 379 DBG("Unknown dynamic range");
ashleymills 11:dfd1e0afcb7b 380 break;
ashleymills 11:dfd1e0afcb7b 381 }
ashleymills 11:dfd1e0afcb7b 382 break;
ashleymills 11:dfd1e0afcb7b 383
ashleymills 12:172540ff6b8b 384 case MMA8452_STATUS:
ashleymills 12:172540ff6b8b 385 DBG("STATUS has value: 0x%x",v);
ashleymills 12:172540ff6b8b 386 DBG(" 7 ZYXOW: %d",(v&0x80)>>7);
ashleymills 12:172540ff6b8b 387 DBG(" 6 ZOW: %d", (v&0x40)>>6);
ashleymills 12:172540ff6b8b 388 DBG(" 5 YOW: %d", (v&0x20)>>5);
ashleymills 12:172540ff6b8b 389 DBG(" 4 XOW: %d", (v&0x10)>>4);
ashleymills 12:172540ff6b8b 390 DBG(" 3 ZYXDR: %d",(v&0x08)>>3);
ashleymills 12:172540ff6b8b 391 DBG(" 2 ZDR: %d", (v&0x04)>>2);
ashleymills 12:172540ff6b8b 392 DBG(" 1 YDR: %d", (v&0x02)>>1);
ashleymills 12:172540ff6b8b 393 DBG(" 0 XDR: %d", (v&0x01));
ashleymills 12:172540ff6b8b 394 break;
ashleymills 12:172540ff6b8b 395
ashleymills 11:dfd1e0afcb7b 396 default:
ashleymills 11:dfd1e0afcb7b 397 DBG("Unknown register address: 0x%x",reg);
ashleymills 11:dfd1e0afcb7b 398 break;
ashleymills 11:dfd1e0afcb7b 399 }
ashleymills 11:dfd1e0afcb7b 400 }