Device driver for the Freescale MMA845x family of accelerometers.

Dependents:   MMA845x_test KL05_accel-test

Work in Progress

Committer:
sam_grove
Date:
Fri Mar 29 21:51:11 2013 +0000
Revision:
0:9d1e3a344e4f
Work in progress

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 0:9d1e3a344e4f 1 /**
sam_grove 0:9d1e3a344e4f 2 * @file MMA845x.cpp
sam_grove 0:9d1e3a344e4f 3 * @brief Device driver - MMA845X 3-axis accelerometer IC
sam_grove 0:9d1e3a344e4f 4 * @author sam grove
sam_grove 0:9d1e3a344e4f 5 * @version 1.0
sam_grove 0:9d1e3a344e4f 6 * @see http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf
sam_grove 0:9d1e3a344e4f 7 * @see http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8452Q.pdf
sam_grove 0:9d1e3a344e4f 8 * @see http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8453Q.pdf
sam_grove 0:9d1e3a344e4f 9 *
sam_grove 0:9d1e3a344e4f 10 * Copyright (c) 2013
sam_grove 0:9d1e3a344e4f 11 *
sam_grove 0:9d1e3a344e4f 12 * Licensed under the Apache License, Version 2.0 (the "License");
sam_grove 0:9d1e3a344e4f 13 * you may not use this file except in compliance with the License.
sam_grove 0:9d1e3a344e4f 14 * You may obtain a copy of the License at
sam_grove 0:9d1e3a344e4f 15 *
sam_grove 0:9d1e3a344e4f 16 * http://www.apache.org/licenses/LICENSE-2.0
sam_grove 0:9d1e3a344e4f 17 *
sam_grove 0:9d1e3a344e4f 18 * Unless required by applicable law or agreed to in writing, software
sam_grove 0:9d1e3a344e4f 19 * distributed under the License is distributed on an "AS IS" BASIS,
sam_grove 0:9d1e3a344e4f 20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sam_grove 0:9d1e3a344e4f 21 * See the License for the specific language governing permissions and
sam_grove 0:9d1e3a344e4f 22 * limitations under the License.
sam_grove 0:9d1e3a344e4f 23 */
sam_grove 0:9d1e3a344e4f 24
sam_grove 0:9d1e3a344e4f 25 #include "MMA845x.h"
sam_grove 0:9d1e3a344e4f 26
sam_grove 0:9d1e3a344e4f 27 MMA845x::MMA845x(I2C &i2c, InterruptIn &int1, InterruptIn &int2, MMA845x_SA0 const i2c_addr)
sam_grove 0:9d1e3a344e4f 28 {
sam_grove 0:9d1e3a344e4f 29 _i2c = &i2c;
sam_grove 0:9d1e3a344e4f 30 _int1 = &int1;
sam_grove 0:9d1e3a344e4f 31 _int2 = &int2;
sam_grove 0:9d1e3a344e4f 32
sam_grove 0:9d1e3a344e4f 33 _i2c_addr = (0x1c << 2) | (i2c_addr << 0x1);
sam_grove 0:9d1e3a344e4f 34
sam_grove 0:9d1e3a344e4f 35 return;
sam_grove 0:9d1e3a344e4f 36 }
sam_grove 0:9d1e3a344e4f 37
sam_grove 0:9d1e3a344e4f 38 void MMA845x::init(void) const
sam_grove 0:9d1e3a344e4f 39 {
sam_grove 0:9d1e3a344e4f 40 uint8_t reg_val = 0;
sam_grove 0:9d1e3a344e4f 41
sam_grove 0:9d1e3a344e4f 42 _i2c->frequency(400000);
sam_grove 0:9d1e3a344e4f 43
sam_grove 0:9d1e3a344e4f 44 // Reset all registers to POR values
sam_grove 0:9d1e3a344e4f 45 MMA845x::writeRegister(CTRL_REG2, 0xFF); //REG 0x2B
sam_grove 0:9d1e3a344e4f 46 do{
sam_grove 0:9d1e3a344e4f 47 // wait for the reset bit to clear
sam_grove 0:9d1e3a344e4f 48 reg_val = MMA845x::readRegister(CTRL_REG2) & 0x40;
sam_grove 0:9d1e3a344e4f 49 }while(reg_val);
sam_grove 0:9d1e3a344e4f 50
sam_grove 0:9d1e3a344e4f 51 // setup the registers that are common among modes
sam_grove 0:9d1e3a344e4f 52 MMA845x::writeRegister(CTRL_REG1, 0xd8); //REG 0x2A
sam_grove 0:9d1e3a344e4f 53 MMA845x::writeRegister(CTRL_REG2, 0x00); //REG 0x2B
sam_grove 0:9d1e3a344e4f 54 MMA845x::writeRegister(CTRL_REG3, 0x00); //REG 0x2C
sam_grove 0:9d1e3a344e4f 55
sam_grove 0:9d1e3a344e4f 56 MMA845x::writeRegister(XYZ_DATA_CFG, 0x0); //REG 0xE HPF / scale +/-2,4,8g
sam_grove 0:9d1e3a344e4f 57 MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x0); //REG 0xF HPF settings
sam_grove 0:9d1e3a344e4f 58
sam_grove 0:9d1e3a344e4f 59 return;
sam_grove 0:9d1e3a344e4f 60 }
sam_grove 0:9d1e3a344e4f 61
sam_grove 0:9d1e3a344e4f 62 void MMA845x::enableDataReadyMode(void) const
sam_grove 0:9d1e3a344e4f 63 {
sam_grove 0:9d1e3a344e4f 64 MMA845x::init();
sam_grove 0:9d1e3a344e4f 65 MMA845x::writeRegister(SYSMOD, 0x1); //REG 0x0B
sam_grove 0:9d1e3a344e4f 66 MMA845x::writeRegister(INT_SOURCE, 0x1); //REG 0x0C
sam_grove 0:9d1e3a344e4f 67 // need to finish up these config registers..... 3/8/13
sam_grove 0:9d1e3a344e4f 68
sam_grove 0:9d1e3a344e4f 69 }
sam_grove 0:9d1e3a344e4f 70
sam_grove 0:9d1e3a344e4f 71 void MMA845x::enableMotionMode(void) const{}
sam_grove 0:9d1e3a344e4f 72 void MMA845x::enablePulseMode(void) const{}
sam_grove 0:9d1e3a344e4f 73
sam_grove 0:9d1e3a344e4f 74 void MMA845x::enableOrientationMode(void) const
sam_grove 0:9d1e3a344e4f 75 {
sam_grove 0:9d1e3a344e4f 76 uint16_t who_am_i = MMA845x::readRegister(WHO_AM_I);
sam_grove 0:9d1e3a344e4f 77 if(who_am_i != MMA8451)
sam_grove 0:9d1e3a344e4f 78 {
sam_grove 0:9d1e3a344e4f 79 error("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
sam_grove 0:9d1e3a344e4f 80 }
sam_grove 0:9d1e3a344e4f 81
sam_grove 0:9d1e3a344e4f 82 return;
sam_grove 0:9d1e3a344e4f 83 }
sam_grove 0:9d1e3a344e4f 84
sam_grove 0:9d1e3a344e4f 85 void MMA845x::enableTransitMode(void) const{}
sam_grove 0:9d1e3a344e4f 86 void MMA845x::enableAutoSleepMode(void) const{}
sam_grove 0:9d1e3a344e4f 87
sam_grove 0:9d1e3a344e4f 88 void MMA845x::enableFIFOMode(void) const
sam_grove 0:9d1e3a344e4f 89 {
sam_grove 0:9d1e3a344e4f 90 uint16_t who_am_i = MMA845x::readRegister(WHO_AM_I);
sam_grove 0:9d1e3a344e4f 91 if(who_am_i != MMA8451)
sam_grove 0:9d1e3a344e4f 92 {
sam_grove 0:9d1e3a344e4f 93 error("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
sam_grove 0:9d1e3a344e4f 94 }
sam_grove 0:9d1e3a344e4f 95
sam_grove 0:9d1e3a344e4f 96 //MMA845x::writeRegister(
sam_grove 0:9d1e3a344e4f 97
sam_grove 0:9d1e3a344e4f 98 return;
sam_grove 0:9d1e3a344e4f 99 }
sam_grove 0:9d1e3a344e4f 100
sam_grove 0:9d1e3a344e4f 101 uint16_t MMA845x::getX(void) const
sam_grove 0:9d1e3a344e4f 102 {
sam_grove 0:9d1e3a344e4f 103 return _data._x;
sam_grove 0:9d1e3a344e4f 104 }
sam_grove 0:9d1e3a344e4f 105
sam_grove 0:9d1e3a344e4f 106 uint16_t MMA845x::getY(void) const
sam_grove 0:9d1e3a344e4f 107 {
sam_grove 0:9d1e3a344e4f 108 return _data._y;
sam_grove 0:9d1e3a344e4f 109 }
sam_grove 0:9d1e3a344e4f 110
sam_grove 0:9d1e3a344e4f 111 uint16_t MMA845x::getZ(void) const
sam_grove 0:9d1e3a344e4f 112 {
sam_grove 0:9d1e3a344e4f 113 return _data._z;
sam_grove 0:9d1e3a344e4f 114 }
sam_grove 0:9d1e3a344e4f 115
sam_grove 0:9d1e3a344e4f 116 MMA845x_DATA MMA845x::getXYZ(void) const
sam_grove 0:9d1e3a344e4f 117 {
sam_grove 0:9d1e3a344e4f 118 return _data;
sam_grove 0:9d1e3a344e4f 119 }
sam_grove 0:9d1e3a344e4f 120
sam_grove 0:9d1e3a344e4f 121 void MMA845x::writeRegister(uint8_t const reg, uint8_t const data) const
sam_grove 0:9d1e3a344e4f 122 {
sam_grove 0:9d1e3a344e4f 123 char buf[2] = {reg, data};
sam_grove 0:9d1e3a344e4f 124 uint8_t result = 0;
sam_grove 0:9d1e3a344e4f 125
sam_grove 0:9d1e3a344e4f 126 __disable_irq(); // Tickers and other timebase events can jack up the I2C bus for some deicse
sam_grove 0:9d1e3a344e4f 127 result = _i2c->write(_i2c_addr, buf, 2);
sam_grove 0:9d1e3a344e4f 128 __enable_irq(); // Just need to block during the transaction
sam_grove 0:9d1e3a344e4f 129
sam_grove 0:9d1e3a344e4f 130 if(0 != result)
sam_grove 0:9d1e3a344e4f 131 {
sam_grove 0:9d1e3a344e4f 132 error("%s %d: I2c write failed\n", __FILE__, __LINE__);
sam_grove 0:9d1e3a344e4f 133 }
sam_grove 0:9d1e3a344e4f 134
sam_grove 0:9d1e3a344e4f 135 return;
sam_grove 0:9d1e3a344e4f 136 }
sam_grove 0:9d1e3a344e4f 137
sam_grove 0:9d1e3a344e4f 138 uint8_t MMA845x::readRegister(uint8_t const reg) const
sam_grove 0:9d1e3a344e4f 139 {
sam_grove 0:9d1e3a344e4f 140 uint8_t result = 1, data = 0;
sam_grove 0:9d1e3a344e4f 141
sam_grove 0:9d1e3a344e4f 142 __disable_irq(); // Tickers and other timebase events can jack up the I2C bus
sam_grove 0:9d1e3a344e4f 143 _i2c->start();
sam_grove 0:9d1e3a344e4f 144 result &= _i2c->write(_i2c_addr);
sam_grove 0:9d1e3a344e4f 145 result &= _i2c->write(reg);
sam_grove 0:9d1e3a344e4f 146 // issue a repeated start...
sam_grove 0:9d1e3a344e4f 147 _i2c->start();
sam_grove 0:9d1e3a344e4f 148 result &= _i2c->write(_i2c_addr | 0x01);
sam_grove 0:9d1e3a344e4f 149 // read with nak
sam_grove 0:9d1e3a344e4f 150 data = _i2c->read(0);
sam_grove 0:9d1e3a344e4f 151 _i2c->stop();
sam_grove 0:9d1e3a344e4f 152 __enable_irq(); // Just need to block during the transaction
sam_grove 0:9d1e3a344e4f 153
sam_grove 0:9d1e3a344e4f 154 if(1 != result)
sam_grove 0:9d1e3a344e4f 155 {
sam_grove 0:9d1e3a344e4f 156 error("%s %d: I2C read failed\n", __FILE__, __LINE__);
sam_grove 0:9d1e3a344e4f 157 }
sam_grove 0:9d1e3a344e4f 158
sam_grove 0:9d1e3a344e4f 159 return data;
sam_grove 0:9d1e3a344e4f 160 }
sam_grove 0:9d1e3a344e4f 161
sam_grove 0:9d1e3a344e4f 162 void MMA845x::registerDump(void) const
sam_grove 0:9d1e3a344e4f 163 {
sam_grove 0:9d1e3a344e4f 164 uint8_t reg_val = 0;
sam_grove 0:9d1e3a344e4f 165
sam_grove 0:9d1e3a344e4f 166 for(int i=0; i<0x80; i++)
sam_grove 0:9d1e3a344e4f 167 {
sam_grove 0:9d1e3a344e4f 168 reg_val = MMA845x::readRegister(i);
sam_grove 0:9d1e3a344e4f 169 printf("Reg 0x%02x: 0x%02x \n", i, reg_val);
sam_grove 0:9d1e3a344e4f 170 }
sam_grove 0:9d1e3a344e4f 171
sam_grove 0:9d1e3a344e4f 172 return;
sam_grove 0:9d1e3a344e4f 173 }
sam_grove 0:9d1e3a344e4f 174