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@15:eb8aac252eba, 2015-02-24 (annotated)
- Committer:
- lemming
- Date:
- Tue Feb 24 05:25:41 2015 +0000
- Revision:
- 15:eb8aac252eba
- Parent:
- 5:a70c0bce770d
Adjusted pinscape to work with a cheap linear potentiometer instead of a CCD array
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 | 5:a70c0bce770d | 69 | // initialize parameters |
mjr | 5:a70c0bce770d | 70 | init(); |
mjr | 5:a70c0bce770d | 71 | } |
mjr | 5:a70c0bce770d | 72 | |
mjr | 5:a70c0bce770d | 73 | // reset the accelerometer and set our parameters |
mjr | 5:a70c0bce770d | 74 | void MMA8451Q::init() |
mjr | 5:a70c0bce770d | 75 | { |
mjr | 3:3514575d4f86 | 76 | // reset all registers to power-on reset values |
mjr | 3:3514575d4f86 | 77 | uint8_t d0[2] = { REG_CTRL_REG_2, 0x40 }; |
mjr | 3:3514575d4f86 | 78 | writeRegs(d0,2 ); |
mjr | 3:3514575d4f86 | 79 | |
mjr | 3:3514575d4f86 | 80 | // wait for the reset bit to clear |
mjr | 3:3514575d4f86 | 81 | do { |
mjr | 3:3514575d4f86 | 82 | readRegs(REG_CTRL_REG_2, d0, 1); |
mjr | 3:3514575d4f86 | 83 | } while ((d0[0] & 0x40) != 0); |
mjr | 5:a70c0bce770d | 84 | |
mjr | 5:a70c0bce770d | 85 | // go to standby mode |
mjr | 5:a70c0bce770d | 86 | standby(); |
mjr | 3:3514575d4f86 | 87 | |
mjr | 1:d913e0afb2ac | 88 | // read the curent config register |
mjr | 1:d913e0afb2ac | 89 | uint8_t d1[1]; |
mjr | 1:d913e0afb2ac | 90 | readRegs(XYZ_DATA_CFG_REG, d1, 1); |
mjr | 1:d913e0afb2ac | 91 | |
mjr | 1:d913e0afb2ac | 92 | // set 2g mode |
mjr | 1:d913e0afb2ac | 93 | uint8_t d2[2] = { XYZ_DATA_CFG_REG, (d1[0] & ~FS_MASK) | FS_2G }; |
mjr | 1:d913e0afb2ac | 94 | writeRegs(d2, 2); |
mjr | 1:d913e0afb2ac | 95 | |
mjr | 1:d913e0afb2ac | 96 | // read the ctl2 register |
mjr | 1:d913e0afb2ac | 97 | uint8_t d3[1]; |
mjr | 1:d913e0afb2ac | 98 | readRegs(REG_CTRL_REG_2, d3, 1); |
mjr | 1:d913e0afb2ac | 99 | |
mjr | 1:d913e0afb2ac | 100 | // set the high resolution mode |
mjr | 1:d913e0afb2ac | 101 | uint8_t d4[2] = {REG_CTRL_REG_2, (d3[0] & ~MODS_MASK) | MODS1_MASK}; |
mjr | 1:d913e0afb2ac | 102 | writeRegs(d4, 2); |
mjr | 1:d913e0afb2ac | 103 | |
mjr | 3:3514575d4f86 | 104 | // set 800 Hz mode |
mjr | 1:d913e0afb2ac | 105 | uint8_t d5[1]; |
mjr | 1:d913e0afb2ac | 106 | readRegs(REG_CTRL_REG_1, d5, 1); |
mjr | 3:3514575d4f86 | 107 | uint8_t d6[2] = {REG_CTRL_REG_1, (d5[0] & ~DR_MASK) | DR_800_HZ}; |
mjr | 1:d913e0afb2ac | 108 | writeRegs(d6, 2); |
mjr | 1:d913e0afb2ac | 109 | |
mjr | 1:d913e0afb2ac | 110 | // enter active mode |
mjr | 1:d913e0afb2ac | 111 | active(); |
mjr | 1:d913e0afb2ac | 112 | } |
mjr | 1:d913e0afb2ac | 113 | |
mjr | 1:d913e0afb2ac | 114 | MMA8451Q::~MMA8451Q() { } |
mjr | 1:d913e0afb2ac | 115 | |
mjr | 3:3514575d4f86 | 116 | void MMA8451Q::setInterruptMode(int pin) |
mjr | 3:3514575d4f86 | 117 | { |
mjr | 3:3514575d4f86 | 118 | // go to standby mode |
mjr | 3:3514575d4f86 | 119 | standby(); |
mjr | 3:3514575d4f86 | 120 | |
mjr | 3:3514575d4f86 | 121 | // set IRQ push/pull and active high |
mjr | 3:3514575d4f86 | 122 | uint8_t d1[1]; |
mjr | 3:3514575d4f86 | 123 | readRegs(REG_CTRL_REG_3, d1, 1); |
mjr | 3:3514575d4f86 | 124 | uint8_t d2[2] = { |
mjr | 3:3514575d4f86 | 125 | REG_CTRL_REG_3, |
mjr | 3:3514575d4f86 | 126 | (d1[0] & ~CTRL_REG3_PPOD_MASK) | CTRL_REG3_IPOL_MASK |
mjr | 3:3514575d4f86 | 127 | }; |
mjr | 3:3514575d4f86 | 128 | writeRegs(d2, 2); |
mjr | 3:3514575d4f86 | 129 | |
mjr | 3:3514575d4f86 | 130 | // set pin 2 or pin 1 |
mjr | 3:3514575d4f86 | 131 | readRegs(REG_CTRL_REG_5, d1, 1); |
mjr | 3:3514575d4f86 | 132 | uint8_t d3[2] = { |
mjr | 3:3514575d4f86 | 133 | REG_CTRL_REG_5, |
mjr | 3:3514575d4f86 | 134 | (d1[0] & ~INT_CFG_DRDY) | (pin == 1 ? INT_CFG_DRDY : 0) |
mjr | 3:3514575d4f86 | 135 | }; |
mjr | 3:3514575d4f86 | 136 | writeRegs(d3, 2); |
mjr | 3:3514575d4f86 | 137 | |
mjr | 3:3514575d4f86 | 138 | // enable data ready interrupt |
mjr | 3:3514575d4f86 | 139 | readRegs(REG_CTRL_REG_4, d1, 1); |
mjr | 3:3514575d4f86 | 140 | uint8_t d4[2] = { REG_CTRL_REG_4, d1[0] | INT_EN_DRDY }; |
mjr | 3:3514575d4f86 | 141 | writeRegs(d4, 2); |
mjr | 3:3514575d4f86 | 142 | |
mjr | 3:3514575d4f86 | 143 | // enter active mode |
mjr | 3:3514575d4f86 | 144 | active(); |
mjr | 3:3514575d4f86 | 145 | } |
mjr | 3:3514575d4f86 | 146 | |
mjr | 1:d913e0afb2ac | 147 | void MMA8451Q::standby() |
mjr | 1:d913e0afb2ac | 148 | { |
mjr | 1:d913e0afb2ac | 149 | // read the current control register |
mjr | 1:d913e0afb2ac | 150 | uint8_t d1[1]; |
mjr | 1:d913e0afb2ac | 151 | readRegs(REG_CTRL_REG_1, d1, 1); |
mjr | 1:d913e0afb2ac | 152 | |
mjr | 5:a70c0bce770d | 153 | // wait for standby mode |
mjr | 5:a70c0bce770d | 154 | do { |
mjr | 5:a70c0bce770d | 155 | // write it back with the Active bit cleared |
mjr | 5:a70c0bce770d | 156 | uint8_t d2[2] = { REG_CTRL_REG_1, d1[0] & ~CTL_ACTIVE }; |
mjr | 5:a70c0bce770d | 157 | writeRegs(d2, 2); |
mjr | 5:a70c0bce770d | 158 | |
mjr | 5:a70c0bce770d | 159 | readRegs(REG_CTRL_REG_1, d1, 1); |
mjr | 5:a70c0bce770d | 160 | } while (d1[0] & CTL_ACTIVE); |
mjr | 1:d913e0afb2ac | 161 | } |
mjr | 1:d913e0afb2ac | 162 | |
mjr | 1:d913e0afb2ac | 163 | void MMA8451Q::active() |
mjr | 1:d913e0afb2ac | 164 | { |
mjr | 1:d913e0afb2ac | 165 | // read the current control register |
mjr | 1:d913e0afb2ac | 166 | uint8_t d1[1]; |
mjr | 1:d913e0afb2ac | 167 | readRegs(REG_CTRL_REG_1, d1, 1); |
mjr | 1:d913e0afb2ac | 168 | |
mjr | 1:d913e0afb2ac | 169 | // write it back out with the Active bit set |
mjr | 1:d913e0afb2ac | 170 | uint8_t d2[2] = { REG_CTRL_REG_1, d1[0] | CTL_ACTIVE }; |
mjr | 1:d913e0afb2ac | 171 | writeRegs(d2, 2); |
mjr | 1:d913e0afb2ac | 172 | } |
mjr | 1:d913e0afb2ac | 173 | |
mjr | 1:d913e0afb2ac | 174 | uint8_t MMA8451Q::getWhoAmI() { |
mjr | 1:d913e0afb2ac | 175 | uint8_t who_am_i = 0; |
mjr | 1:d913e0afb2ac | 176 | readRegs(REG_WHO_AM_I, &who_am_i, 1); |
mjr | 1:d913e0afb2ac | 177 | return who_am_i; |
mjr | 1:d913e0afb2ac | 178 | } |
mjr | 1:d913e0afb2ac | 179 | |
mjr | 1:d913e0afb2ac | 180 | float MMA8451Q::getAccX() { |
mjr | 1:d913e0afb2ac | 181 | return (float(getAccAxis(REG_OUT_X_MSB))/4096.0); |
mjr | 1:d913e0afb2ac | 182 | } |
mjr | 1:d913e0afb2ac | 183 | |
mjr | 1:d913e0afb2ac | 184 | void MMA8451Q::getAccXY(float &x, float &y) |
mjr | 1:d913e0afb2ac | 185 | { |
mjr | 1:d913e0afb2ac | 186 | // read the X and Y output registers |
mjr | 1:d913e0afb2ac | 187 | uint8_t res[4]; |
mjr | 1:d913e0afb2ac | 188 | readRegs(REG_OUT_X_MSB, res, 4); |
mjr | 1:d913e0afb2ac | 189 | |
mjr | 1:d913e0afb2ac | 190 | // translate the x value |
mjr | 1:d913e0afb2ac | 191 | uint16_t acc = (res[0] << 8) | (res[1]); |
mjr | 1:d913e0afb2ac | 192 | x = int16_t(acc)/(4*4096.0); |
mjr | 1:d913e0afb2ac | 193 | |
mjr | 1:d913e0afb2ac | 194 | // translate the y value |
mjr | 1:d913e0afb2ac | 195 | acc = (res[2] << 9) | (res[3]); |
mjr | 1:d913e0afb2ac | 196 | y = int16_t(acc)/(4*4096.0); |
mjr | 1:d913e0afb2ac | 197 | } |
mjr | 1:d913e0afb2ac | 198 | |
mjr | 3:3514575d4f86 | 199 | void MMA8451Q::getAccXYZ(float &x, float &y, float &z) |
mjr | 3:3514575d4f86 | 200 | { |
mjr | 3:3514575d4f86 | 201 | // read the X, Y, and Z output registers |
mjr | 3:3514575d4f86 | 202 | uint8_t res[6]; |
mjr | 3:3514575d4f86 | 203 | readRegs(REG_OUT_X_MSB, res, 6); |
mjr | 3:3514575d4f86 | 204 | |
mjr | 3:3514575d4f86 | 205 | // translate the x value |
mjr | 3:3514575d4f86 | 206 | uint16_t acc = (res[0] << 8) | (res[1]); |
mjr | 3:3514575d4f86 | 207 | x = int16_t(acc)/(4*4096.0); |
mjr | 3:3514575d4f86 | 208 | |
mjr | 3:3514575d4f86 | 209 | // translate the y value |
mjr | 3:3514575d4f86 | 210 | acc = (res[2] << 8) | (res[3]); |
mjr | 3:3514575d4f86 | 211 | y = int16_t(acc)/(4*4096.0); |
mjr | 3:3514575d4f86 | 212 | |
mjr | 3:3514575d4f86 | 213 | // translate the z value |
mjr | 3:3514575d4f86 | 214 | acc = (res[4] << 8) | (res[5]); |
mjr | 3:3514575d4f86 | 215 | z = int16_t(acc)/(4*4096.0); |
mjr | 3:3514575d4f86 | 216 | } |
mjr | 3:3514575d4f86 | 217 | |
mjr | 1:d913e0afb2ac | 218 | float MMA8451Q::getAccY() { |
mjr | 1:d913e0afb2ac | 219 | return (float(getAccAxis(REG_OUT_Y_MSB))/4096.0); |
mjr | 1:d913e0afb2ac | 220 | } |
mjr | 1:d913e0afb2ac | 221 | |
mjr | 1:d913e0afb2ac | 222 | float MMA8451Q::getAccZ() { |
mjr | 1:d913e0afb2ac | 223 | return (float(getAccAxis(REG_OUT_Z_MSB))/4096.0); |
mjr | 1:d913e0afb2ac | 224 | } |
mjr | 1:d913e0afb2ac | 225 | |
mjr | 1:d913e0afb2ac | 226 | void MMA8451Q::getAccAllAxis(float * res) { |
mjr | 1:d913e0afb2ac | 227 | res[0] = getAccX(); |
mjr | 1:d913e0afb2ac | 228 | res[1] = getAccY(); |
mjr | 1:d913e0afb2ac | 229 | res[2] = getAccZ(); |
mjr | 1:d913e0afb2ac | 230 | } |
mjr | 1:d913e0afb2ac | 231 | |
mjr | 1:d913e0afb2ac | 232 | int16_t MMA8451Q::getAccAxis(uint8_t addr) { |
mjr | 1:d913e0afb2ac | 233 | int16_t acc; |
mjr | 1:d913e0afb2ac | 234 | uint8_t res[2]; |
mjr | 1:d913e0afb2ac | 235 | readRegs(addr, res, 2); |
mjr | 1:d913e0afb2ac | 236 | |
mjr | 1:d913e0afb2ac | 237 | acc = (res[0] << 6) | (res[1] >> 2); |
mjr | 1:d913e0afb2ac | 238 | if (acc > UINT14_MAX/2) |
mjr | 1:d913e0afb2ac | 239 | acc -= UINT14_MAX; |
mjr | 1:d913e0afb2ac | 240 | |
mjr | 1:d913e0afb2ac | 241 | return acc; |
mjr | 1:d913e0afb2ac | 242 | } |
mjr | 1:d913e0afb2ac | 243 | |
mjr | 1:d913e0afb2ac | 244 | void MMA8451Q::readRegs(int addr, uint8_t * data, int len) { |
mjr | 1:d913e0afb2ac | 245 | char t[1] = {addr}; |
mjr | 1:d913e0afb2ac | 246 | m_i2c.write(m_addr, t, 1, true); |
mjr | 1:d913e0afb2ac | 247 | m_i2c.read(m_addr, (char *)data, len); |
mjr | 1:d913e0afb2ac | 248 | } |
mjr | 1:d913e0afb2ac | 249 | |
mjr | 1:d913e0afb2ac | 250 | void MMA8451Q::writeRegs(uint8_t * data, int len) { |
mjr | 1:d913e0afb2ac | 251 | m_i2c.write(m_addr, (char *)data, len); |
mjr | 1:d913e0afb2ac | 252 | } |