A library with drivers for different peripherals on the LPC4088 QuickStart Board or related add-on boards.
Dependents: LPC4088test LPC4088test_ledonly LPC4088test_deleteall LPC4088_RAMtest ... more
MMA7455.cpp
- Committer:
- embeddedartists
- Date:
- 2014-01-30
- Revision:
- 12:15597e45eea0
- Parent:
- 4:b32cf4ef45c5
File content as of revision 12:15597e45eea0:
/* * Copyright 2013 Embedded Artists AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /****************************************************************************** * Includes *****************************************************************************/ #include "mbed.h" #include "mbed_debug.h" #include "MMA7455.h" /****************************************************************************** * Defines and typedefs *****************************************************************************/ #define MMA7455_I2C_ADDR (0x1D << 1) #define MMA7455_ADDR_XOUTL 0x00 #define MMA7455_ADDR_XOUTH 0x01 #define MMA7455_ADDR_YOUTL 0x02 #define MMA7455_ADDR_YOUTH 0x03 #define MMA7455_ADDR_ZOUTL 0x04 #define MMA7455_ADDR_ZOUTH 0x05 #define MMA7455_ADDR_XOUT8 0x06 #define MMA7455_ADDR_YOUT8 0x07 #define MMA7455_ADDR_ZOUT8 0x08 #define MMA7455_ADDR_STATUS 0x09 #define MMA7455_ADDR_DETSRC 0x0A #define MMA7455_ADDR_TOUT 0x0B #define MMA7455_ADDR_I2CAD 0x0D #define MMA7455_ADDR_USRINF 0x0E #define MMA7455_ADDR_WHOAMI 0x0F #define MMA7455_ADDR_XOFFL 0x10 #define MMA7455_ADDR_XOFFH 0x11 #define MMA7455_ADDR_YOFFL 0x12 #define MMA7455_ADDR_YOFFH 0x13 #define MMA7455_ADDR_ZOFFL 0x14 #define MMA7455_ADDR_ZOFFH 0x15 #define MMA7455_ADDR_MCTL 0x16 #define MMA7455_ADDR_INTRST 0x17 #define MMA7455_ADDR_CTL1 0x18 #define MMA7455_ADDR_CTL2 0x19 #define MMA7455_ADDR_LDTH 0x1A #define MMA7455_ADDR_PDTH 0x1B #define MMA7455_ADDR_PW 0x1C #define MMA7455_ADDR_LT 0x1D #define MMA7455_ADDR_TW 0x1E #define MMA7455_MCTL_MODE(m) ((m) << 0) #define MMA7455_MCTL_GLVL(g) ((g) << 2) #define MMA7455_STATUS_DRDY (1 << 0) #define MMA7455_STATUS_DOVR (1 << 1) #define MMA7455_STATUS_PERR (1 << 2) MMA7455::MMA7455(PinName sda, PinName scl) : _i2c(sda, scl) { _mode = ModeStandby; _range = Range_8g; _xOff = 0; _yOff = 0; _zOff = 0; } bool MMA7455::setMode(Mode mode) { bool result = false; int mCtrl = 0; do { mCtrl = getModeControl(); if (mCtrl < 0) break; mCtrl &= ~(0x03 << 0); mCtrl |= MMA7455_MCTL_MODE(mode); if (setModeControl((uint8_t)mCtrl) < 0) { break; } _mode = mode; result = true; } while(0); return result; } bool MMA7455::setRange(Range range) { bool result = false; int mCtrl = 0; do { mCtrl = getModeControl(); if (mCtrl < 0) break; mCtrl &= ~(0x03 << 2); mCtrl |= MMA7455_MCTL_GLVL(range); if (setModeControl((uint8_t)mCtrl) < 0) { break; } _range = range; result = true; } while(0); return result; } bool MMA7455::read(int32_t& x, int32_t& y, int32_t& z) { bool result = false; // nothing to read in standby mode if (_mode == ModeStandby) return false; // wait for ready flag int status = 0; do { status = getStatus(); } while (status >= 0 && (status & MMA7455_STATUS_DRDY) == 0); do { if (status < 0) break; char buf[6]; buf[0] = MMA7455_ADDR_XOUTL; if (_i2c.write(MMA7455_I2C_ADDR, buf, 1) != 0) break; if (_i2c.read(MMA7455_I2C_ADDR, buf, 6) != 0) break; // check if second bit is set in high byte -> negative value // expand negative value to full byte if (buf[1] & 0x02) buf[1] |= 0xFC; if (buf[3] & 0x02) buf[3] |= 0xFC; if (buf[5] & 0x02) buf[5] |= 0xFC; x = (int16_t)((buf[1] << 8) | buf[0]) + _xOff; y = (int16_t)((buf[3] << 8) | buf[2]) + _yOff; z = (int16_t)((buf[5] << 8) | buf[4]) + _zOff; result = true; } while(0); return result; } bool MMA7455::calibrate() { bool result = false; bool failed = false; int32_t x = 0; int32_t y = 0; int32_t z = 0; int32_t xr = 0; int32_t yr = 0; int32_t zr = 0; int xOff = 0; int yOff = 0; int zOff = 16; if (_range == Range_2g) { zOff = 64; } if (_range == Range_4g) { zOff = 32; } do { // get an average of 6 values for (int i = 0; i < 6; i++) { if (!read(xr, yr, zr)) { failed = true; break; } x += xr; y += yr; z += zr; wait_ms(100); } if (failed) break; x /= 6; y /= 6; z /= 6; xOff -= x; yOff -= y; zOff -= z; /* * For some reason we have not got correct/reliable calibration * by using the offset drift registers. Instead we are * calculating the offsets and store them in member variables. * * These member variables are then used in the read() method */ _xOff = xOff; _yOff = yOff; _zOff = zOff; result = true; } while (0); return result; } bool MMA7455::setCalibrationOffsets(int32_t xOff, int32_t yOff, int32_t zOff) { _xOff = xOff; _yOff = yOff; _zOff = zOff; return true; } bool MMA7455::getCalibrationOffsets(int32_t& xOff, int32_t& yOff, int32_t& zOff) { xOff = _xOff; yOff = _yOff; zOff = _zOff; return true; } int MMA7455::getStatus() { int result = -1; char data[1]; do { data[0] = MMA7455_ADDR_STATUS; if (_i2c.write(MMA7455_I2C_ADDR, data, 1) != 0) break; if (_i2c.read(MMA7455_I2C_ADDR, data, 1) != 0) break; result = data[0]; } while (0); return result; } int MMA7455::getModeControl() { int result = -1; char data[1]; do { data[0] = MMA7455_ADDR_MCTL; if (_i2c.write(MMA7455_I2C_ADDR, data, 1) != 0) break; if (_i2c.read(MMA7455_I2C_ADDR, data, 1) != 0) break; result = data[0]; } while (0); return result; } int MMA7455::setModeControl(uint8_t mctl) { int result = -1; char data[2]; do { data[0] = MMA7455_ADDR_MCTL; data[1] = (char)mctl; if (_i2c.write(MMA7455_I2C_ADDR, data, 2) != 0) break; result = 0; } while (0); return result; }