Adjusts the great pinscape controller to work with a cheap linear potentiometer instead of the expensive CCD array
Fork of Pinscape_Controller by
MMA8451Q/MMA8451Q.cpp@3:3514575d4f86, 2014-07-23 (annotated)
- 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?
User | Revision | Line number | New 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 | } |