Asteroid

Dependencies:   4DGL-uLCD-SE PinDetect mbed

Committer:
Philipjp
Date:
Tue Nov 14 18:03:31 2017 +0000
Revision:
0:73375f76583c
Asteroid

Who changed what in which revision?

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