Benedikt Kičin
/
kicin2vytah
Benedikt Kicin, vytah semestralka
MMA8451Q.cpp@0:2574b54351ed, 2018-01-24 (annotated)
- Committer:
- kicin2
- Date:
- Wed Jan 24 07:55:50 2018 +0000
- Revision:
- 0:2574b54351ed
kicin2 vytah
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kicin2 | 0:2574b54351ed | 1 | /* Copyright (c) 2010-2011 mbed.org, MIT License |
kicin2 | 0:2574b54351ed | 2 | * |
kicin2 | 0:2574b54351ed | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
kicin2 | 0:2574b54351ed | 4 | * and associated documentation files (the "Software"), to deal in the Software without |
kicin2 | 0:2574b54351ed | 5 | * restriction, including without limitation the rights to use, copy, modify, merge, publish, |
kicin2 | 0:2574b54351ed | 6 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the |
kicin2 | 0:2574b54351ed | 7 | * Software is furnished to do so, subject to the following conditions: |
kicin2 | 0:2574b54351ed | 8 | * |
kicin2 | 0:2574b54351ed | 9 | * The above copyright notice and this permission notice shall be included in all copies or |
kicin2 | 0:2574b54351ed | 10 | * substantial portions of the Software. |
kicin2 | 0:2574b54351ed | 11 | * |
kicin2 | 0:2574b54351ed | 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
kicin2 | 0:2574b54351ed | 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
kicin2 | 0:2574b54351ed | 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
kicin2 | 0:2574b54351ed | 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
kicin2 | 0:2574b54351ed | 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
kicin2 | 0:2574b54351ed | 17 | */ |
kicin2 | 0:2574b54351ed | 18 | |
kicin2 | 0:2574b54351ed | 19 | #include "MMA8451Q.h" |
kicin2 | 0:2574b54351ed | 20 | |
kicin2 | 0:2574b54351ed | 21 | #define REG_STATUS 0x00 |
kicin2 | 0:2574b54351ed | 22 | #define REG_WHO_AM_I 0x0D |
kicin2 | 0:2574b54351ed | 23 | #define REG_CTRL_REG_1 0x2A |
kicin2 | 0:2574b54351ed | 24 | #define REG_CTRL_REG_2 0x2B |
kicin2 | 0:2574b54351ed | 25 | #define REG_CTRL_REG_4 0x2D |
kicin2 | 0:2574b54351ed | 26 | #define REG_CTRL_REG_5 0x2E |
kicin2 | 0:2574b54351ed | 27 | #define REG_INT_SRC 0x0C |
kicin2 | 0:2574b54351ed | 28 | #define REG_FF_MT_CFG 0x15 |
kicin2 | 0:2574b54351ed | 29 | #define REG_FF_MT_SRC 0x16 |
kicin2 | 0:2574b54351ed | 30 | #define REG_FF_MT_THS 0x17 |
kicin2 | 0:2574b54351ed | 31 | #define REG_FF_MT_CNT 0x18 |
kicin2 | 0:2574b54351ed | 32 | #define REG_DBCNTM 0x11 |
kicin2 | 0:2574b54351ed | 33 | #define REG_DBNCE 0x12 |
kicin2 | 0:2574b54351ed | 34 | #define REG_BKFR 0x13 |
kicin2 | 0:2574b54351ed | 35 | #define REG_P_L_THS 0x14 |
kicin2 | 0:2574b54351ed | 36 | #define REG_PL_STATUS 0x10 |
kicin2 | 0:2574b54351ed | 37 | |
kicin2 | 0:2574b54351ed | 38 | // |
kicin2 | 0:2574b54351ed | 39 | #define REG_OUT_X_MSB 0x01 |
kicin2 | 0:2574b54351ed | 40 | #define REG_OUT_Y_MSB 0x03 |
kicin2 | 0:2574b54351ed | 41 | #define REG_OUT_Z_MSB 0x05 |
kicin2 | 0:2574b54351ed | 42 | |
kicin2 | 0:2574b54351ed | 43 | #define UINT14_MAX 16383 |
kicin2 | 0:2574b54351ed | 44 | |
kicin2 | 0:2574b54351ed | 45 | // |
kicin2 | 0:2574b54351ed | 46 | #define ZYXDR 0x08 |
kicin2 | 0:2574b54351ed | 47 | #define ZDR 0x04 |
kicin2 | 0:2574b54351ed | 48 | #define YDR 0x02 |
kicin2 | 0:2574b54351ed | 49 | #define XDR 0x01 |
kicin2 | 0:2574b54351ed | 50 | |
kicin2 | 0:2574b54351ed | 51 | /** |
kicin2 | 0:2574b54351ed | 52 | *Interrupt schema |
kicin2 | 0:2574b54351ed | 53 | */ |
kicin2 | 0:2574b54351ed | 54 | void (*MMA8451Q_usr2_fptr)(void); // Pointers to user function called after |
kicin2 | 0:2574b54351ed | 55 | void (*MMA8451Q_usr1_fptr)(void); // IRQ assertion. |
kicin2 | 0:2574b54351ed | 56 | |
kicin2 | 0:2574b54351ed | 57 | // |
kicin2 | 0:2574b54351ed | 58 | InterruptIn MMA8451Q_Int1( PTC5); // INTERRUPT1 |
kicin2 | 0:2574b54351ed | 59 | InterruptIn MMA8451Q_Int2( PTD1); // INTERRUPT2 |
kicin2 | 0:2574b54351ed | 60 | |
kicin2 | 0:2574b54351ed | 61 | // Constructor with features |
kicin2 | 0:2574b54351ed | 62 | MMA8451Q::MMA8451Q(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr) { |
kicin2 | 0:2574b54351ed | 63 | |
kicin2 | 0:2574b54351ed | 64 | MMA8451Q_Int1.fall( NULL); |
kicin2 | 0:2574b54351ed | 65 | MMA8451Q_Int2.fall( NULL); |
kicin2 | 0:2574b54351ed | 66 | MMA8451Q_usr2_fptr = NULL; |
kicin2 | 0:2574b54351ed | 67 | MMA8451Q_usr1_fptr = NULL; |
kicin2 | 0:2574b54351ed | 68 | |
kicin2 | 0:2574b54351ed | 69 | Reset(); |
kicin2 | 0:2574b54351ed | 70 | Active(); |
kicin2 | 0:2574b54351ed | 71 | } |
kicin2 | 0:2574b54351ed | 72 | |
kicin2 | 0:2574b54351ed | 73 | // Constructor |
kicin2 | 0:2574b54351ed | 74 | MMA8451Q::~MMA8451Q() |
kicin2 | 0:2574b54351ed | 75 | { |
kicin2 | 0:2574b54351ed | 76 | MMA8451Q_Int1.fall( NULL); |
kicin2 | 0:2574b54351ed | 77 | MMA8451Q_Int2.fall( NULL); |
kicin2 | 0:2574b54351ed | 78 | MMA8451Q_usr2_fptr = NULL; |
kicin2 | 0:2574b54351ed | 79 | MMA8451Q_usr1_fptr = NULL; |
kicin2 | 0:2574b54351ed | 80 | } |
kicin2 | 0:2574b54351ed | 81 | |
kicin2 | 0:2574b54351ed | 82 | void MMA8451Q::Reset( void) |
kicin2 | 0:2574b54351ed | 83 | { |
kicin2 | 0:2574b54351ed | 84 | // Soft reset |
kicin2 | 0:2574b54351ed | 85 | uint8_t data[2] = {REG_CTRL_REG_2, 0x40}; |
kicin2 | 0:2574b54351ed | 86 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 87 | wait( 0.1); |
kicin2 | 0:2574b54351ed | 88 | } |
kicin2 | 0:2574b54351ed | 89 | |
kicin2 | 0:2574b54351ed | 90 | void MMA8451Q::MotionDetection( void(*fptr)(void)) |
kicin2 | 0:2574b54351ed | 91 | { |
kicin2 | 0:2574b54351ed | 92 | Reset(); |
kicin2 | 0:2574b54351ed | 93 | |
kicin2 | 0:2574b54351ed | 94 | // Step 1: |
kicin2 | 0:2574b54351ed | 95 | unsigned char data[2] = {REG_CTRL_REG_1, 0x18}; |
kicin2 | 0:2574b54351ed | 96 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 97 | |
kicin2 | 0:2574b54351ed | 98 | // Step 2: |
kicin2 | 0:2574b54351ed | 99 | data[0] = REG_FF_MT_CFG; |
kicin2 | 0:2574b54351ed | 100 | data[1] = 0xD8; |
kicin2 | 0:2574b54351ed | 101 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 102 | |
kicin2 | 0:2574b54351ed | 103 | // Step 3: |
kicin2 | 0:2574b54351ed | 104 | data[0] = REG_FF_MT_THS; |
kicin2 | 0:2574b54351ed | 105 | data[1] = 0x10; |
kicin2 | 0:2574b54351ed | 106 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 107 | |
kicin2 | 0:2574b54351ed | 108 | // Step 4: |
kicin2 | 0:2574b54351ed | 109 | data[0] = REG_FF_MT_CNT; |
kicin2 | 0:2574b54351ed | 110 | data[1] = 0x0A; |
kicin2 | 0:2574b54351ed | 111 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 112 | |
kicin2 | 0:2574b54351ed | 113 | // Step 5: |
kicin2 | 0:2574b54351ed | 114 | data[0] = REG_CTRL_REG_4; |
kicin2 | 0:2574b54351ed | 115 | data[1] = 0x04; |
kicin2 | 0:2574b54351ed | 116 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 117 | |
kicin2 | 0:2574b54351ed | 118 | // Step 6: |
kicin2 | 0:2574b54351ed | 119 | data[0] = REG_CTRL_REG_5; |
kicin2 | 0:2574b54351ed | 120 | data[1] = 0x00; |
kicin2 | 0:2574b54351ed | 121 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 122 | |
kicin2 | 0:2574b54351ed | 123 | // Step 7: |
kicin2 | 0:2574b54351ed | 124 | data[0] = REG_CTRL_REG_1; |
kicin2 | 0:2574b54351ed | 125 | data[1] = 0x19; |
kicin2 | 0:2574b54351ed | 126 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 127 | |
kicin2 | 0:2574b54351ed | 128 | MMA8451Q_usr2_fptr = fptr; |
kicin2 | 0:2574b54351ed | 129 | MMA8451Q_Int2.fall( this, &MMA8451Q::Motion_IRQ); |
kicin2 | 0:2574b54351ed | 130 | |
kicin2 | 0:2574b54351ed | 131 | } |
kicin2 | 0:2574b54351ed | 132 | |
kicin2 | 0:2574b54351ed | 133 | void MMA8451Q::Motion_IRQ( void) |
kicin2 | 0:2574b54351ed | 134 | { |
kicin2 | 0:2574b54351ed | 135 | unsigned char t; |
kicin2 | 0:2574b54351ed | 136 | |
kicin2 | 0:2574b54351ed | 137 | // Determine source of the interrupt by first reading the system interrupt |
kicin2 | 0:2574b54351ed | 138 | readRegs( REG_INT_SRC, &t, 1); |
kicin2 | 0:2574b54351ed | 139 | // |
kicin2 | 0:2574b54351ed | 140 | if ( (t & 0x04) == 0x04) { |
kicin2 | 0:2574b54351ed | 141 | // Read the Motion/Freefall Function to clear the interrupt |
kicin2 | 0:2574b54351ed | 142 | readRegs( REG_FF_MT_SRC, &t, 1); |
kicin2 | 0:2574b54351ed | 143 | // Run the user supplied function |
kicin2 | 0:2574b54351ed | 144 | MMA8451Q_usr2_fptr(); |
kicin2 | 0:2574b54351ed | 145 | } |
kicin2 | 0:2574b54351ed | 146 | } |
kicin2 | 0:2574b54351ed | 147 | |
kicin2 | 0:2574b54351ed | 148 | |
kicin2 | 0:2574b54351ed | 149 | void MMA8451Q::Active( void) |
kicin2 | 0:2574b54351ed | 150 | { |
kicin2 | 0:2574b54351ed | 151 | unsigned char t; |
kicin2 | 0:2574b54351ed | 152 | |
kicin2 | 0:2574b54351ed | 153 | // Activate the peripheral |
kicin2 | 0:2574b54351ed | 154 | readRegs(REG_CTRL_REG_1, &t, 1); |
kicin2 | 0:2574b54351ed | 155 | unsigned char data[2] = {REG_CTRL_REG_1, t|0x01}; |
kicin2 | 0:2574b54351ed | 156 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 157 | } |
kicin2 | 0:2574b54351ed | 158 | |
kicin2 | 0:2574b54351ed | 159 | void MMA8451Q::Standby( void) |
kicin2 | 0:2574b54351ed | 160 | { |
kicin2 | 0:2574b54351ed | 161 | unsigned char t; |
kicin2 | 0:2574b54351ed | 162 | |
kicin2 | 0:2574b54351ed | 163 | // Standby |
kicin2 | 0:2574b54351ed | 164 | readRegs(REG_CTRL_REG_1, &t, 1); |
kicin2 | 0:2574b54351ed | 165 | unsigned char data[2] = {REG_CTRL_REG_1, t&0xFE}; |
kicin2 | 0:2574b54351ed | 166 | writeRegs(data, 2); |
kicin2 | 0:2574b54351ed | 167 | } |
kicin2 | 0:2574b54351ed | 168 | |
kicin2 | 0:2574b54351ed | 169 | uint8_t MMA8451Q::getWhoAmI() { |
kicin2 | 0:2574b54351ed | 170 | uint8_t who_am_i = 0; |
kicin2 | 0:2574b54351ed | 171 | readRegs(REG_WHO_AM_I, &who_am_i, 1); |
kicin2 | 0:2574b54351ed | 172 | return who_am_i; |
kicin2 | 0:2574b54351ed | 173 | } |
kicin2 | 0:2574b54351ed | 174 | |
kicin2 | 0:2574b54351ed | 175 | float MMA8451Q::getAccX() { |
kicin2 | 0:2574b54351ed | 176 | return (float(getAccAxis(REG_OUT_X_MSB))/4096.0); |
kicin2 | 0:2574b54351ed | 177 | } |
kicin2 | 0:2574b54351ed | 178 | |
kicin2 | 0:2574b54351ed | 179 | float MMA8451Q::getAccY() { |
kicin2 | 0:2574b54351ed | 180 | return (float(getAccAxis(REG_OUT_Y_MSB))/4096.0); |
kicin2 | 0:2574b54351ed | 181 | } |
kicin2 | 0:2574b54351ed | 182 | |
kicin2 | 0:2574b54351ed | 183 | float MMA8451Q::getAccZ() { |
kicin2 | 0:2574b54351ed | 184 | return (float(getAccAxis(REG_OUT_Z_MSB))/4096.0); |
kicin2 | 0:2574b54351ed | 185 | } |
kicin2 | 0:2574b54351ed | 186 | |
kicin2 | 0:2574b54351ed | 187 | void MMA8451Q::getAccAllAxis(float * res) { |
kicin2 | 0:2574b54351ed | 188 | res[0] = getAccX(); |
kicin2 | 0:2574b54351ed | 189 | res[1] = getAccY(); |
kicin2 | 0:2574b54351ed | 190 | res[2] = getAccZ(); |
kicin2 | 0:2574b54351ed | 191 | } |
kicin2 | 0:2574b54351ed | 192 | |
kicin2 | 0:2574b54351ed | 193 | int16_t MMA8451Q::getAccAxis(uint8_t addr) { |
kicin2 | 0:2574b54351ed | 194 | int16_t acc; |
kicin2 | 0:2574b54351ed | 195 | uint8_t res[2]; |
kicin2 | 0:2574b54351ed | 196 | readRegs(addr, res, 2); |
kicin2 | 0:2574b54351ed | 197 | |
kicin2 | 0:2574b54351ed | 198 | acc = (res[0] << 6) | (res[1] >> 2); |
kicin2 | 0:2574b54351ed | 199 | if (acc > UINT14_MAX/2) |
kicin2 | 0:2574b54351ed | 200 | acc -= UINT14_MAX; |
kicin2 | 0:2574b54351ed | 201 | |
kicin2 | 0:2574b54351ed | 202 | return acc; |
kicin2 | 0:2574b54351ed | 203 | } |
kicin2 | 0:2574b54351ed | 204 | |
kicin2 | 0:2574b54351ed | 205 | unsigned int MMA8451Q::getAccRawAllAxis( int16_t * res) |
kicin2 | 0:2574b54351ed | 206 | { |
kicin2 | 0:2574b54351ed | 207 | if ( isDataAvailable() & ZYXDR) |
kicin2 | 0:2574b54351ed | 208 | { |
kicin2 | 0:2574b54351ed | 209 | getAccRawX( &res[0]); |
kicin2 | 0:2574b54351ed | 210 | getAccRawY( &res[1]); |
kicin2 | 0:2574b54351ed | 211 | getAccRawZ( &res[2]); |
kicin2 | 0:2574b54351ed | 212 | return 1; |
kicin2 | 0:2574b54351ed | 213 | } else |
kicin2 | 0:2574b54351ed | 214 | return 0; |
kicin2 | 0:2574b54351ed | 215 | } |
kicin2 | 0:2574b54351ed | 216 | |
kicin2 | 0:2574b54351ed | 217 | int16_t MMA8451Q::getAccRawX( int16_t * res) |
kicin2 | 0:2574b54351ed | 218 | { |
kicin2 | 0:2574b54351ed | 219 | if ( isDataAvailable() & XDR) |
kicin2 | 0:2574b54351ed | 220 | { |
kicin2 | 0:2574b54351ed | 221 | *res = getAccAxis(REG_OUT_X_MSB); |
kicin2 | 0:2574b54351ed | 222 | return 1; |
kicin2 | 0:2574b54351ed | 223 | } else |
kicin2 | 0:2574b54351ed | 224 | return 0; |
kicin2 | 0:2574b54351ed | 225 | } |
kicin2 | 0:2574b54351ed | 226 | |
kicin2 | 0:2574b54351ed | 227 | int16_t MMA8451Q::getAccRawY( int16_t * res) |
kicin2 | 0:2574b54351ed | 228 | { |
kicin2 | 0:2574b54351ed | 229 | if ( isDataAvailable() & YDR) |
kicin2 | 0:2574b54351ed | 230 | { |
kicin2 | 0:2574b54351ed | 231 | *res = getAccAxis(REG_OUT_Y_MSB); |
kicin2 | 0:2574b54351ed | 232 | return 1; |
kicin2 | 0:2574b54351ed | 233 | } else |
kicin2 | 0:2574b54351ed | 234 | return 0; |
kicin2 | 0:2574b54351ed | 235 | } |
kicin2 | 0:2574b54351ed | 236 | |
kicin2 | 0:2574b54351ed | 237 | int16_t MMA8451Q::getAccRawZ( int16_t * res) |
kicin2 | 0:2574b54351ed | 238 | { |
kicin2 | 0:2574b54351ed | 239 | if ( isDataAvailable() & ZDR) |
kicin2 | 0:2574b54351ed | 240 | { |
kicin2 | 0:2574b54351ed | 241 | *res = getAccAxis(REG_OUT_Z_MSB); |
kicin2 | 0:2574b54351ed | 242 | return 1; |
kicin2 | 0:2574b54351ed | 243 | } else |
kicin2 | 0:2574b54351ed | 244 | return 0; |
kicin2 | 0:2574b54351ed | 245 | } |
kicin2 | 0:2574b54351ed | 246 | |
kicin2 | 0:2574b54351ed | 247 | unsigned int MMA8451Q::isDataAvailable( void) |
kicin2 | 0:2574b54351ed | 248 | { |
kicin2 | 0:2574b54351ed | 249 | unsigned char status; |
kicin2 | 0:2574b54351ed | 250 | |
kicin2 | 0:2574b54351ed | 251 | readRegs( REG_STATUS, &status, 1); |
kicin2 | 0:2574b54351ed | 252 | |
kicin2 | 0:2574b54351ed | 253 | return (status); |
kicin2 | 0:2574b54351ed | 254 | |
kicin2 | 0:2574b54351ed | 255 | } |
kicin2 | 0:2574b54351ed | 256 | |
kicin2 | 0:2574b54351ed | 257 | void MMA8451Q::readRegs(int addr, uint8_t * data, int len) { |
kicin2 | 0:2574b54351ed | 258 | char t[1] = {addr}; |
kicin2 | 0:2574b54351ed | 259 | m_i2c.write(m_addr, t, 1, true); |
kicin2 | 0:2574b54351ed | 260 | m_i2c.read(m_addr, (char *)data, len); |
kicin2 | 0:2574b54351ed | 261 | } |
kicin2 | 0:2574b54351ed | 262 | |
kicin2 | 0:2574b54351ed | 263 | void MMA8451Q::writeRegs(uint8_t * data, int len) { |
kicin2 | 0:2574b54351ed | 264 | m_i2c.write(m_addr, (char *)data, len); |
kicin2 | 0:2574b54351ed | 265 | } |