Device driver for the Freescale MMA845x family of accelerometers.
Dependents: MMA845x_test KL05_accel-test
Work in Progress
MMA845x.cpp@0:9d1e3a344e4f, 2013-03-29 (annotated)
- Committer:
- sam_grove
- Date:
- Fri Mar 29 21:51:11 2013 +0000
- Revision:
- 0:9d1e3a344e4f
Work in progress
Who changed what in which revision?
User | Revision | Line number | New 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 |