Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
mjr
Date:
Wed Jul 23 17:53:28 2014 +0000
Revision:
3:3514575d4f86
Parent:
2:c174f9ee414a
Child:
5:a70c0bce770d
Conversion to interrupt-based sampling of the accelerometer working

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 1:d913e0afb2ac 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
mjr 1:d913e0afb2ac 2 *
mjr 1:d913e0afb2ac 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
mjr 1:d913e0afb2ac 4 * and associated documentation files (the "Software"), to deal in the Software without
mjr 1:d913e0afb2ac 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
mjr 1:d913e0afb2ac 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
mjr 1:d913e0afb2ac 7 * Software is furnished to do so, subject to the following conditions:
mjr 1:d913e0afb2ac 8 *
mjr 1:d913e0afb2ac 9 * The above copyright notice and this permission notice shall be included in all copies or
mjr 1:d913e0afb2ac 10 * substantial portions of the Software.
mjr 1:d913e0afb2ac 11 *
mjr 1:d913e0afb2ac 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
mjr 1:d913e0afb2ac 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
mjr 1:d913e0afb2ac 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
mjr 1:d913e0afb2ac 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
mjr 1:d913e0afb2ac 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
mjr 1:d913e0afb2ac 17 */
mjr 1:d913e0afb2ac 18
mjr 1:d913e0afb2ac 19 #include "MMA8451Q.h"
mjr 1:d913e0afb2ac 20
mjr 1:d913e0afb2ac 21 #define REG_WHO_AM_I 0x0D
mjr 1:d913e0afb2ac 22 #define REG_CTRL_REG_1 0x2A
mjr 1:d913e0afb2ac 23 #define REG_CTRL_REG_2 0x2B
mjr 1:d913e0afb2ac 24 #define REG_CTRL_REG_3 0x2c
mjr 1:d913e0afb2ac 25 #define REG_CTRL_REG_4 0x2D
mjr 1:d913e0afb2ac 26 #define REG_CTRL_REG_5 0x2E
mjr 1:d913e0afb2ac 27 #define REG_OFF_X 0x2F
mjr 1:d913e0afb2ac 28 #define REG_OFF_Y 0x30
mjr 1:d913e0afb2ac 29 #define REG_OFF_Z 0x31
mjr 1:d913e0afb2ac 30 #define XYZ_DATA_CFG_REG 0x0E
mjr 1:d913e0afb2ac 31 #define REG_OUT_X_MSB 0x01
mjr 1:d913e0afb2ac 32 #define REG_OUT_Y_MSB 0x03
mjr 1:d913e0afb2ac 33 #define REG_OUT_Z_MSB 0x05
mjr 1:d913e0afb2ac 34
mjr 1:d913e0afb2ac 35 #define UINT14_MAX 16383
mjr 1:d913e0afb2ac 36
mjr 1:d913e0afb2ac 37 #define CTL_ACTIVE 0x01
mjr 1:d913e0afb2ac 38 #define FS_MASK 0x03
mjr 1:d913e0afb2ac 39 #define FS_2G 0x00
mjr 1:d913e0afb2ac 40 #define FS_4G 0x01
mjr 1:d913e0afb2ac 41 #define FS_8G 0x02
mjr 1:d913e0afb2ac 42
mjr 1:d913e0afb2ac 43 #define HPF_OUT_MASK 0x10
mjr 1:d913e0afb2ac 44
mjr 1:d913e0afb2ac 45 #define MODS1_MASK 0x02
mjr 1:d913e0afb2ac 46 #define MODS0_MASK 0x01
mjr 1:d913e0afb2ac 47 #define SMODS_MASK 0x18
mjr 1:d913e0afb2ac 48 #define MODS_MASK 0x03
mjr 1:d913e0afb2ac 49
mjr 1:d913e0afb2ac 50 #define DR_MASK 0x38
mjr 1:d913e0afb2ac 51 #define DR_800_HZ 0x00
mjr 1:d913e0afb2ac 52 #define DR_400_HZ 0x08
mjr 1:d913e0afb2ac 53 #define DR_200_HZ 0x10
mjr 1:d913e0afb2ac 54 #define DR_100_HZ 0x18
mjr 1:d913e0afb2ac 55 #define DR_50_HZ 0x20
mjr 1:d913e0afb2ac 56 #define DR_12_HZ 0x28
mjr 1:d913e0afb2ac 57 #define DR_6_HZ 0x30
mjr 1:d913e0afb2ac 58 #define DR_1_HZ 0x38
mjr 1:d913e0afb2ac 59
mjr 3:3514575d4f86 60 #define CTRL_REG3_IPOL_MASK 0x02
mjr 3:3514575d4f86 61 #define CTRL_REG3_PPOD_MASK 0x01
mjr 3:3514575d4f86 62
mjr 3:3514575d4f86 63 #define INT_EN_DRDY 0x01
mjr 3:3514575d4f86 64 #define INT_CFG_DRDY 0x01
mjr 3:3514575d4f86 65
mjr 1:d913e0afb2ac 66
mjr 1:d913e0afb2ac 67 MMA8451Q::MMA8451Q(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr)
mjr 1:d913e0afb2ac 68 {
mjr 1:d913e0afb2ac 69 // go to standby mode
mjr 1:d913e0afb2ac 70 standby();
mjr 1:d913e0afb2ac 71
mjr 3:3514575d4f86 72 #if 0
mjr 3:3514575d4f86 73 // reset all registers to power-on reset values
mjr 3:3514575d4f86 74 uint8_t d0[2] = { REG_CTRL_REG_2, 0x40 };
mjr 3:3514575d4f86 75 writeRegs(d0,2 );
mjr 3:3514575d4f86 76
mjr 3:3514575d4f86 77 // wait for the reset bit to clear
mjr 3:3514575d4f86 78 do {
mjr 3:3514575d4f86 79 readRegs(REG_CTRL_REG_2, d0, 1);
mjr 3:3514575d4f86 80 } while ((d0[0] & 0x40) != 0);
mjr 3:3514575d4f86 81 #endif
mjr 3:3514575d4f86 82
mjr 1:d913e0afb2ac 83 // read the curent config register
mjr 1:d913e0afb2ac 84 uint8_t d1[1];
mjr 1:d913e0afb2ac 85 readRegs(XYZ_DATA_CFG_REG, d1, 1);
mjr 1:d913e0afb2ac 86
mjr 1:d913e0afb2ac 87 // set 2g mode
mjr 1:d913e0afb2ac 88 uint8_t d2[2] = { XYZ_DATA_CFG_REG, (d1[0] & ~FS_MASK) | FS_2G };
mjr 1:d913e0afb2ac 89 writeRegs(d2, 2);
mjr 1:d913e0afb2ac 90
mjr 1:d913e0afb2ac 91 // read the ctl2 register
mjr 1:d913e0afb2ac 92 uint8_t d3[1];
mjr 1:d913e0afb2ac 93 readRegs(REG_CTRL_REG_2, d3, 1);
mjr 1:d913e0afb2ac 94
mjr 1:d913e0afb2ac 95 // set the high resolution mode
mjr 1:d913e0afb2ac 96 uint8_t d4[2] = {REG_CTRL_REG_2, (d3[0] & ~MODS_MASK) | MODS1_MASK};
mjr 1:d913e0afb2ac 97 writeRegs(d4, 2);
mjr 1:d913e0afb2ac 98
mjr 3:3514575d4f86 99 // set 800 Hz mode
mjr 1:d913e0afb2ac 100 uint8_t d5[1];
mjr 1:d913e0afb2ac 101 readRegs(REG_CTRL_REG_1, d5, 1);
mjr 3:3514575d4f86 102 uint8_t d6[2] = {REG_CTRL_REG_1, (d5[0] & ~DR_MASK) | DR_800_HZ};
mjr 1:d913e0afb2ac 103 writeRegs(d6, 2);
mjr 1:d913e0afb2ac 104
mjr 1:d913e0afb2ac 105 // enter active mode
mjr 1:d913e0afb2ac 106 active();
mjr 1:d913e0afb2ac 107 }
mjr 1:d913e0afb2ac 108
mjr 1:d913e0afb2ac 109 MMA8451Q::~MMA8451Q() { }
mjr 1:d913e0afb2ac 110
mjr 3:3514575d4f86 111 void MMA8451Q::setInterruptMode(int pin)
mjr 3:3514575d4f86 112 {
mjr 3:3514575d4f86 113 // go to standby mode
mjr 3:3514575d4f86 114 standby();
mjr 3:3514575d4f86 115
mjr 3:3514575d4f86 116 // set IRQ push/pull and active high
mjr 3:3514575d4f86 117 uint8_t d1[1];
mjr 3:3514575d4f86 118 readRegs(REG_CTRL_REG_3, d1, 1);
mjr 3:3514575d4f86 119 uint8_t d2[2] = {
mjr 3:3514575d4f86 120 REG_CTRL_REG_3,
mjr 3:3514575d4f86 121 (d1[0] & ~CTRL_REG3_PPOD_MASK) | CTRL_REG3_IPOL_MASK
mjr 3:3514575d4f86 122 };
mjr 3:3514575d4f86 123 writeRegs(d2, 2);
mjr 3:3514575d4f86 124
mjr 3:3514575d4f86 125 // set pin 2 or pin 1
mjr 3:3514575d4f86 126 readRegs(REG_CTRL_REG_5, d1, 1);
mjr 3:3514575d4f86 127 uint8_t d3[2] = {
mjr 3:3514575d4f86 128 REG_CTRL_REG_5,
mjr 3:3514575d4f86 129 (d1[0] & ~INT_CFG_DRDY) | (pin == 1 ? INT_CFG_DRDY : 0)
mjr 3:3514575d4f86 130 };
mjr 3:3514575d4f86 131 writeRegs(d3, 2);
mjr 3:3514575d4f86 132
mjr 3:3514575d4f86 133 // enable data ready interrupt
mjr 3:3514575d4f86 134 readRegs(REG_CTRL_REG_4, d1, 1);
mjr 3:3514575d4f86 135 uint8_t d4[2] = { REG_CTRL_REG_4, d1[0] | INT_EN_DRDY };
mjr 3:3514575d4f86 136 writeRegs(d4, 2);
mjr 3:3514575d4f86 137
mjr 3:3514575d4f86 138 // enter active mode
mjr 3:3514575d4f86 139 active();
mjr 3:3514575d4f86 140 }
mjr 3:3514575d4f86 141
mjr 1:d913e0afb2ac 142 void MMA8451Q::standby()
mjr 1:d913e0afb2ac 143 {
mjr 1:d913e0afb2ac 144 // read the current control register
mjr 1:d913e0afb2ac 145 uint8_t d1[1];
mjr 1:d913e0afb2ac 146 readRegs(REG_CTRL_REG_1, d1, 1);
mjr 1:d913e0afb2ac 147
mjr 1:d913e0afb2ac 148 // write it back witht he Active bit cleared
mjr 1:d913e0afb2ac 149 uint8_t d2[2] = { REG_CTRL_REG_1, d1[0] & ~CTL_ACTIVE };
mjr 1:d913e0afb2ac 150 writeRegs(d2, 2);
mjr 1:d913e0afb2ac 151 }
mjr 1:d913e0afb2ac 152
mjr 1:d913e0afb2ac 153 void MMA8451Q::active()
mjr 1:d913e0afb2ac 154 {
mjr 1:d913e0afb2ac 155 // read the current control register
mjr 1:d913e0afb2ac 156 uint8_t d1[1];
mjr 1:d913e0afb2ac 157 readRegs(REG_CTRL_REG_1, d1, 1);
mjr 1:d913e0afb2ac 158
mjr 1:d913e0afb2ac 159 // write it back out with the Active bit set
mjr 1:d913e0afb2ac 160 uint8_t d2[2] = { REG_CTRL_REG_1, d1[0] | CTL_ACTIVE };
mjr 1:d913e0afb2ac 161 writeRegs(d2, 2);
mjr 1:d913e0afb2ac 162 }
mjr 1:d913e0afb2ac 163
mjr 1:d913e0afb2ac 164 uint8_t MMA8451Q::getWhoAmI() {
mjr 1:d913e0afb2ac 165 uint8_t who_am_i = 0;
mjr 1:d913e0afb2ac 166 readRegs(REG_WHO_AM_I, &who_am_i, 1);
mjr 1:d913e0afb2ac 167 return who_am_i;
mjr 1:d913e0afb2ac 168 }
mjr 1:d913e0afb2ac 169
mjr 1:d913e0afb2ac 170 float MMA8451Q::getAccX() {
mjr 1:d913e0afb2ac 171 return (float(getAccAxis(REG_OUT_X_MSB))/4096.0);
mjr 1:d913e0afb2ac 172 }
mjr 1:d913e0afb2ac 173
mjr 1:d913e0afb2ac 174 void MMA8451Q::getAccXY(float &x, float &y)
mjr 1:d913e0afb2ac 175 {
mjr 1:d913e0afb2ac 176 // read the X and Y output registers
mjr 1:d913e0afb2ac 177 uint8_t res[4];
mjr 1:d913e0afb2ac 178 readRegs(REG_OUT_X_MSB, res, 4);
mjr 1:d913e0afb2ac 179
mjr 1:d913e0afb2ac 180 // translate the x value
mjr 1:d913e0afb2ac 181 uint16_t acc = (res[0] << 8) | (res[1]);
mjr 1:d913e0afb2ac 182 x = int16_t(acc)/(4*4096.0);
mjr 1:d913e0afb2ac 183
mjr 1:d913e0afb2ac 184 // translate the y value
mjr 1:d913e0afb2ac 185 acc = (res[2] << 9) | (res[3]);
mjr 1:d913e0afb2ac 186 y = int16_t(acc)/(4*4096.0);
mjr 1:d913e0afb2ac 187 }
mjr 1:d913e0afb2ac 188
mjr 3:3514575d4f86 189 void MMA8451Q::getAccXYZ(float &x, float &y, float &z)
mjr 3:3514575d4f86 190 {
mjr 3:3514575d4f86 191 // read the X, Y, and Z output registers
mjr 3:3514575d4f86 192 uint8_t res[6];
mjr 3:3514575d4f86 193 readRegs(REG_OUT_X_MSB, res, 6);
mjr 3:3514575d4f86 194
mjr 3:3514575d4f86 195 // translate the x value
mjr 3:3514575d4f86 196 uint16_t acc = (res[0] << 8) | (res[1]);
mjr 3:3514575d4f86 197 x = int16_t(acc)/(4*4096.0);
mjr 3:3514575d4f86 198
mjr 3:3514575d4f86 199 // translate the y value
mjr 3:3514575d4f86 200 acc = (res[2] << 8) | (res[3]);
mjr 3:3514575d4f86 201 y = int16_t(acc)/(4*4096.0);
mjr 3:3514575d4f86 202
mjr 3:3514575d4f86 203 // translate the z value
mjr 3:3514575d4f86 204 acc = (res[4] << 8) | (res[5]);
mjr 3:3514575d4f86 205 z = int16_t(acc)/(4*4096.0);
mjr 3:3514575d4f86 206 }
mjr 3:3514575d4f86 207
mjr 1:d913e0afb2ac 208 float MMA8451Q::getAccY() {
mjr 1:d913e0afb2ac 209 return (float(getAccAxis(REG_OUT_Y_MSB))/4096.0);
mjr 1:d913e0afb2ac 210 }
mjr 1:d913e0afb2ac 211
mjr 1:d913e0afb2ac 212 float MMA8451Q::getAccZ() {
mjr 1:d913e0afb2ac 213 return (float(getAccAxis(REG_OUT_Z_MSB))/4096.0);
mjr 1:d913e0afb2ac 214 }
mjr 1:d913e0afb2ac 215
mjr 1:d913e0afb2ac 216 void MMA8451Q::getAccAllAxis(float * res) {
mjr 1:d913e0afb2ac 217 res[0] = getAccX();
mjr 1:d913e0afb2ac 218 res[1] = getAccY();
mjr 1:d913e0afb2ac 219 res[2] = getAccZ();
mjr 1:d913e0afb2ac 220 }
mjr 1:d913e0afb2ac 221
mjr 1:d913e0afb2ac 222 int16_t MMA8451Q::getAccAxis(uint8_t addr) {
mjr 1:d913e0afb2ac 223 int16_t acc;
mjr 1:d913e0afb2ac 224 uint8_t res[2];
mjr 1:d913e0afb2ac 225 readRegs(addr, res, 2);
mjr 1:d913e0afb2ac 226
mjr 1:d913e0afb2ac 227 acc = (res[0] << 6) | (res[1] >> 2);
mjr 1:d913e0afb2ac 228 if (acc > UINT14_MAX/2)
mjr 1:d913e0afb2ac 229 acc -= UINT14_MAX;
mjr 1:d913e0afb2ac 230
mjr 1:d913e0afb2ac 231 return acc;
mjr 1:d913e0afb2ac 232 }
mjr 1:d913e0afb2ac 233
mjr 1:d913e0afb2ac 234 void MMA8451Q::readRegs(int addr, uint8_t * data, int len) {
mjr 1:d913e0afb2ac 235 char t[1] = {addr};
mjr 1:d913e0afb2ac 236 m_i2c.write(m_addr, t, 1, true);
mjr 1:d913e0afb2ac 237 m_i2c.read(m_addr, (char *)data, len);
mjr 1:d913e0afb2ac 238 }
mjr 1:d913e0afb2ac 239
mjr 1:d913e0afb2ac 240 void MMA8451Q::writeRegs(uint8_t * data, int len) {
mjr 1:d913e0afb2ac 241 m_i2c.write(m_addr, (char *)data, len);
mjr 1:d913e0afb2ac 242 }