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 17:01:00 2014 +0000
Revision:
17:6e4232c421c0
Parent:
16:d6dde2318edc
Child:
19:4d6cd7140a71
Cleaned up debug handling

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