Axeda Ready Demo for Freescale FRDM-KL46Z as accident alert system

Dependencies:   FRDM_MMA8451Q KL46Z-USBHost MAG3110 SocketModem TSI mbed FATFileSystem

Fork of AxedaGo-Freescal_FRDM-KL46Z by Axeda Corp

Committer:
AxedaCorp
Date:
Wed Jul 02 19:57:37 2014 +0000
Revision:
2:2f9019c5a9fc
Parent:
0:65004368569c
ip switch

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AxedaCorp 0:65004368569c 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
AxedaCorp 0:65004368569c 2 *
AxedaCorp 0:65004368569c 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
AxedaCorp 0:65004368569c 4 * and associated documentation files (the "Software"), to deal in the Software without
AxedaCorp 0:65004368569c 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
AxedaCorp 0:65004368569c 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
AxedaCorp 0:65004368569c 7 * Software is furnished to do so, subject to the following conditions:
AxedaCorp 0:65004368569c 8 *
AxedaCorp 0:65004368569c 9 * The above copyright notice and this permission notice shall be included in all copies or
AxedaCorp 0:65004368569c 10 * substantial portions of the Software.
AxedaCorp 0:65004368569c 11 *
AxedaCorp 0:65004368569c 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
AxedaCorp 0:65004368569c 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
AxedaCorp 0:65004368569c 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
AxedaCorp 0:65004368569c 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
AxedaCorp 0:65004368569c 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
AxedaCorp 0:65004368569c 17 */
AxedaCorp 0:65004368569c 18
AxedaCorp 0:65004368569c 19 #include "MMA8451Q.h"
AxedaCorp 0:65004368569c 20
AxedaCorp 0:65004368569c 21 #define REG_STATUS 0x00
AxedaCorp 0:65004368569c 22 #define REG_WHO_AM_I 0x0D
AxedaCorp 0:65004368569c 23 #define REG_CTRL_REG_1 0x2A
AxedaCorp 0:65004368569c 24 #define REG_CTRL_REG_2 0x2B
AxedaCorp 0:65004368569c 25 #define REG_CTRL_REG_4 0x2D
AxedaCorp 0:65004368569c 26 #define REG_CTRL_REG_5 0x2E
AxedaCorp 0:65004368569c 27 #define REG_INT_SRC 0x0C
AxedaCorp 0:65004368569c 28 #define REG_FF_MT_CFG 0x15
AxedaCorp 0:65004368569c 29 #define REG_FF_MT_SRC 0x16
AxedaCorp 0:65004368569c 30 #define REG_FF_MT_THS 0x17
AxedaCorp 0:65004368569c 31 #define REG_FF_MT_CNT 0x18
AxedaCorp 0:65004368569c 32 #define REG_DBCNTM 0x11
AxedaCorp 0:65004368569c 33 #define REG_DBNCE 0x12
AxedaCorp 0:65004368569c 34 #define REG_BKFR 0x13
AxedaCorp 0:65004368569c 35 #define REG_P_L_THS 0x14
AxedaCorp 0:65004368569c 36 #define REG_PL_STATUS 0x10
AxedaCorp 0:65004368569c 37
AxedaCorp 0:65004368569c 38 //
AxedaCorp 0:65004368569c 39 #define REG_OUT_X_MSB 0x01
AxedaCorp 0:65004368569c 40 #define REG_OUT_Y_MSB 0x03
AxedaCorp 0:65004368569c 41 #define REG_OUT_Z_MSB 0x05
AxedaCorp 0:65004368569c 42
AxedaCorp 0:65004368569c 43 #define UINT14_MAX 16383
AxedaCorp 0:65004368569c 44
AxedaCorp 0:65004368569c 45 //
AxedaCorp 0:65004368569c 46 #define ZYXDR 0x08
AxedaCorp 0:65004368569c 47 #define ZDR 0x04
AxedaCorp 0:65004368569c 48 #define YDR 0x02
AxedaCorp 0:65004368569c 49 #define XDR 0x01
AxedaCorp 0:65004368569c 50
AxedaCorp 0:65004368569c 51 /** Interrupt schema
AxedaCorp 0:65004368569c 52 *
AxedaCorp 0:65004368569c 53 * :: The FreeFall and Motion detection share the same IRQ2.
AxedaCorp 0:65004368569c 54 *
AxedaCorp 0:65004368569c 55 * FreeFall --+ +-- Fall_IRQ -----+
AxedaCorp 0:65004368569c 56 * \ / \
AxedaCorp 0:65004368569c 57 * +-- MMA8451Q_Int2.fall ---+ +--- MMA8451Q_usr2_fptr
AxedaCorp 0:65004368569c 58 * / \ /
AxedaCorp 0:65004368569c 59 * Motion ----+ +-- Motion_IRQ ---+
AxedaCorp 0:65004368569c 60 *
AxedaCorp 0:65004368569c 61 * :: The Orientation Detect use the IRQ1
AxedaCorp 0:65004368569c 62 *
AxedaCorp 0:65004368569c 63 * Orientation Detect -- MMA8451Q_Int1.fall --- Orientation_IRQ --- MMA8451Q_usr1_fptr
AxedaCorp 0:65004368569c 64 *
AxedaCorp 0:65004368569c 65 *
AxedaCorp 0:65004368569c 66 * :: The data ready use the IRQ2
AxedaCorp 0:65004368569c 67 *
AxedaCorp 0:65004368569c 68 * Data Ready -- MMA8451Q_Int2.fall --- DataReady_IRQ --- usr2_fptr
AxedaCorp 0:65004368569c 69 *
AxedaCorp 0:65004368569c 70 */
AxedaCorp 0:65004368569c 71 void (*MMA8451Q_usr2_fptr)(void); // Pointers to user function called after
AxedaCorp 0:65004368569c 72 void (*MMA8451Q_usr1_fptr)(void); // IRQ assertion.
AxedaCorp 0:65004368569c 73
AxedaCorp 0:65004368569c 74 //
AxedaCorp 0:65004368569c 75 InterruptIn MMA8451Q_Int1( PTA14); // INT1
AxedaCorp 0:65004368569c 76 InterruptIn MMA8451Q_Int2( PTA15); // INT2
AxedaCorp 0:65004368569c 77
AxedaCorp 0:65004368569c 78 MMA8451Q::MMA8451Q(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr) {
AxedaCorp 0:65004368569c 79
AxedaCorp 0:65004368569c 80 MMA8451Q_Int1.fall( NULL);
AxedaCorp 0:65004368569c 81 MMA8451Q_Int2.fall( NULL);
AxedaCorp 0:65004368569c 82 MMA8451Q_usr2_fptr = NULL;
AxedaCorp 0:65004368569c 83 MMA8451Q_usr1_fptr = NULL;
AxedaCorp 0:65004368569c 84
AxedaCorp 0:65004368569c 85 Reset();
AxedaCorp 0:65004368569c 86 Active();
AxedaCorp 0:65004368569c 87 }
AxedaCorp 0:65004368569c 88
AxedaCorp 0:65004368569c 89 MMA8451Q::~MMA8451Q()
AxedaCorp 0:65004368569c 90 {
AxedaCorp 0:65004368569c 91 MMA8451Q_Int1.fall( NULL);
AxedaCorp 0:65004368569c 92 MMA8451Q_Int2.fall( NULL);
AxedaCorp 0:65004368569c 93 MMA8451Q_usr2_fptr = NULL;
AxedaCorp 0:65004368569c 94 MMA8451Q_usr1_fptr = NULL;
AxedaCorp 0:65004368569c 95 }
AxedaCorp 0:65004368569c 96
AxedaCorp 0:65004368569c 97 void MMA8451Q::Reset( void)
AxedaCorp 0:65004368569c 98 {
AxedaCorp 0:65004368569c 99 // Soft reset
AxedaCorp 0:65004368569c 100 uint8_t data[2] = {REG_CTRL_REG_2, 0x40};
AxedaCorp 0:65004368569c 101 writeRegs(data, 2);
AxedaCorp 0:65004368569c 102 wait( 0.1);
AxedaCorp 0:65004368569c 103 }
AxedaCorp 0:65004368569c 104
AxedaCorp 0:65004368569c 105 void MMA8451Q::FreeFallDetection( void(*fptr)(void))
AxedaCorp 0:65004368569c 106 {
AxedaCorp 0:65004368569c 107 // Soft Reset
AxedaCorp 0:65004368569c 108 Reset();
AxedaCorp 0:65004368569c 109
AxedaCorp 0:65004368569c 110 // Example Steps for Configuring Linear Freefall Detection
AxedaCorp 0:65004368569c 111 // X AND Y AND Z < 0.2g using MFF Function, 50 Hz ODR
AxedaCorp 0:65004368569c 112 // Step 1: Put the device in Standby Mode: Register 0x2A CTRL_REG1
AxedaCorp 0:65004368569c 113 unsigned char data[2] = {REG_CTRL_REG_1, 0x20};
AxedaCorp 0:65004368569c 114 writeRegs(data, 2);
AxedaCorp 0:65004368569c 115
AxedaCorp 0:65004368569c 116 // Step 2: Configuration Register set for Freefall Detection enabling “AND” condition, OAE = 0, Enabling X,
AxedaCorp 0:65004368569c 117 // Y, Z and the Latch
AxedaCorp 0:65004368569c 118 data[0] = REG_FF_MT_CFG;
AxedaCorp 0:65004368569c 119 data[1] = 0x01;
AxedaCorp 0:65004368569c 120 writeRegs(data, 2);
AxedaCorp 0:65004368569c 121
AxedaCorp 0:65004368569c 122 // Step 3: Threshold Setting Value for the resulting acceleration < 0.2g
AxedaCorp 0:65004368569c 123 // Note: The step count is 0.063g/count
AxedaCorp 0:65004368569c 124 // • 0.2g/0.063g = 3.17 counts //Round to 3 counts
AxedaCorp 0:65004368569c 125 data[0] = REG_FF_MT_THS;
AxedaCorp 0:65004368569c 126 data[1] = 0x03;
AxedaCorp 0:65004368569c 127 writeRegs(data, 2);
AxedaCorp 0:65004368569c 128
AxedaCorp 0:65004368569c 129 // Step 4: Set the debounce counter to eliminate false positive readings for 50Hz sample rate with a
AxedaCorp 0:65004368569c 130 // requirement of 120 ms timer, assuming Normal Mode.
AxedaCorp 0:65004368569c 131 // Note: 120 ms/20 ms (steps) = 6 counts
AxedaCorp 0:65004368569c 132 data[0] = REG_FF_MT_CNT;
AxedaCorp 0:65004368569c 133 data[1] = 0x06;
AxedaCorp 0:65004368569c 134 writeRegs(data, 2);
AxedaCorp 0:65004368569c 135
AxedaCorp 0:65004368569c 136 // Step 5: Enable Motion/Freefall Interrupt Function in the System (CTRL_REG4)
AxedaCorp 0:65004368569c 137 data[0] = REG_CTRL_REG_4;
AxedaCorp 0:65004368569c 138 data[1] = 0x04;
AxedaCorp 0:65004368569c 139 writeRegs(data, 2);
AxedaCorp 0:65004368569c 140
AxedaCorp 0:65004368569c 141 // Step 6: Route the Motion/Freefall Interrupt Function to INT2 hardware pin (CTRL_REG5)
AxedaCorp 0:65004368569c 142 data[0] = REG_CTRL_REG_5;
AxedaCorp 0:65004368569c 143 data[1] = 0x00;
AxedaCorp 0:65004368569c 144 writeRegs(data, 2);
AxedaCorp 0:65004368569c 145
AxedaCorp 0:65004368569c 146 // Step 7: Put the device in Active Mode, 50 Hz
AxedaCorp 0:65004368569c 147 data[0] = REG_CTRL_REG_1;
AxedaCorp 0:65004368569c 148 data[1] = 0x21;
AxedaCorp 0:65004368569c 149 writeRegs(data, 2);
AxedaCorp 0:65004368569c 150
AxedaCorp 0:65004368569c 151 MMA8451Q_usr2_fptr = fptr;
AxedaCorp 0:65004368569c 152 MMA8451Q_Int2.fall( this, &MMA8451Q::Fall_IRQ);
AxedaCorp 0:65004368569c 153 }
AxedaCorp 0:65004368569c 154
AxedaCorp 0:65004368569c 155 void MMA8451Q::Fall_IRQ( void)
AxedaCorp 0:65004368569c 156 {
AxedaCorp 0:65004368569c 157 unsigned char t;
AxedaCorp 0:65004368569c 158
AxedaCorp 0:65004368569c 159 // Determine source of the interrupt by first reading the system interrupt
AxedaCorp 0:65004368569c 160 readRegs( REG_INT_SRC, &t, 1);
AxedaCorp 0:65004368569c 161 //
AxedaCorp 0:65004368569c 162 if ( (t & 0x04) == 0x04) {
AxedaCorp 0:65004368569c 163 // Read the Motion/Freefall Function to clear the interrupt
AxedaCorp 0:65004368569c 164 readRegs( REG_FF_MT_SRC, &t, 1);
AxedaCorp 0:65004368569c 165 // Run the user supplied function
AxedaCorp 0:65004368569c 166 MMA8451Q_usr2_fptr();
AxedaCorp 0:65004368569c 167 }
AxedaCorp 0:65004368569c 168 }
AxedaCorp 0:65004368569c 169
AxedaCorp 0:65004368569c 170 void MMA8451Q::MotionDetection( void(*fptr)(void))
AxedaCorp 0:65004368569c 171 {
AxedaCorp 0:65004368569c 172 // Soft Reset
AxedaCorp 0:65004368569c 173 Reset();
AxedaCorp 0:65004368569c 174
AxedaCorp 0:65004368569c 175 // 6.1 Example Steps for Configuring Motion Detection
AxedaCorp 0:65004368569c 176 // X or Y > 3g using MFF Function 4g, 100 Hz ODR, Normal Mode
AxedaCorp 0:65004368569c 177 // Step 1: Put the device into Standby Mode: Register 0x2A CTRL_REG1
AxedaCorp 0:65004368569c 178 unsigned char data[2] = {REG_CTRL_REG_1, 0x18}; // Set the device in 100 Hz ODR, Standby
AxedaCorp 0:65004368569c 179 writeRegs(data, 2);
AxedaCorp 0:65004368569c 180
AxedaCorp 0:65004368569c 181
AxedaCorp 0:65004368569c 182 // Step 2: Set Configuration Register for Motion Detection by setting the “OR” condition OAE = 1, enabling
AxedaCorp 0:65004368569c 183 // X, Y, and the latch
AxedaCorp 0:65004368569c 184 data[0] = REG_FF_MT_CFG;
AxedaCorp 0:65004368569c 185 data[1] = 0xD8;
AxedaCorp 0:65004368569c 186 writeRegs(data, 2);
AxedaCorp 0:65004368569c 187
AxedaCorp 0:65004368569c 188 // Step 3: Threshold Setting Value for the Motion detection of > 2g
AxedaCorp 0:65004368569c 189 // Note: The step count is 0.063g/ count
AxedaCorp 0:65004368569c 190 // • 1g/0.063g = 15.8; //Round up to 16
AxedaCorp 0:65004368569c 191 data[0] = REG_FF_MT_THS;
AxedaCorp 0:65004368569c 192 data[1] = 0x10;
AxedaCorp 0:65004368569c 193 writeRegs(data, 2);
AxedaCorp 0:65004368569c 194
AxedaCorp 0:65004368569c 195 // Step 4: Set the debounce counter to eliminate false readings for 100 Hz sample rate with a requirement
AxedaCorp 0:65004368569c 196 // of 100 ms timer.
AxedaCorp 0:65004368569c 197 // Note: 100 ms/10 ms (steps) = 10 counts
AxedaCorp 0:65004368569c 198 data[0] = REG_FF_MT_CNT;
AxedaCorp 0:65004368569c 199 data[1] = 0x0A;
AxedaCorp 0:65004368569c 200 writeRegs(data, 2);
AxedaCorp 0:65004368569c 201
AxedaCorp 0:65004368569c 202 // Step 5: Enable Motion/Freefall Interrupt Function in the System (CTRL_REG4)
AxedaCorp 0:65004368569c 203 data[0] = REG_CTRL_REG_4;
AxedaCorp 0:65004368569c 204 data[1] = 0x04;
AxedaCorp 0:65004368569c 205 writeRegs(data, 2);
AxedaCorp 0:65004368569c 206
AxedaCorp 0:65004368569c 207 // Step 6: Route the Motion/Freefall Interrupt Function to INT2 hardware pin (CTRL_REG5)
AxedaCorp 0:65004368569c 208 data[0] = REG_CTRL_REG_5;
AxedaCorp 0:65004368569c 209 data[1] = 0x00;
AxedaCorp 0:65004368569c 210 writeRegs(data, 2);
AxedaCorp 0:65004368569c 211
AxedaCorp 0:65004368569c 212 // Step 7: Put the device in Active Mode
AxedaCorp 0:65004368569c 213 data[0] = REG_CTRL_REG_1;
AxedaCorp 0:65004368569c 214 data[1] = 0x19;
AxedaCorp 0:65004368569c 215 writeRegs(data, 2);
AxedaCorp 0:65004368569c 216
AxedaCorp 0:65004368569c 217 MMA8451Q_usr2_fptr = fptr;
AxedaCorp 0:65004368569c 218 MMA8451Q_Int2.fall( this, &MMA8451Q::Motion_IRQ);
AxedaCorp 0:65004368569c 219
AxedaCorp 0:65004368569c 220 }
AxedaCorp 0:65004368569c 221
AxedaCorp 0:65004368569c 222 void MMA8451Q::Motion_IRQ( void)
AxedaCorp 0:65004368569c 223 {
AxedaCorp 0:65004368569c 224 unsigned char t;
AxedaCorp 0:65004368569c 225
AxedaCorp 0:65004368569c 226 // Determine source of the interrupt by first reading the system interrupt
AxedaCorp 0:65004368569c 227 readRegs( REG_INT_SRC, &t, 1);
AxedaCorp 0:65004368569c 228 //
AxedaCorp 0:65004368569c 229 if ( (t & 0x04) == 0x04) {
AxedaCorp 0:65004368569c 230 // Read the Motion/Freefall Function to clear the interrupt
AxedaCorp 0:65004368569c 231 readRegs( REG_FF_MT_SRC, &t, 1);
AxedaCorp 0:65004368569c 232 // Run the user supplied function
AxedaCorp 0:65004368569c 233 MMA8451Q_usr2_fptr();
AxedaCorp 0:65004368569c 234 }
AxedaCorp 0:65004368569c 235 }
AxedaCorp 0:65004368569c 236
AxedaCorp 0:65004368569c 237 void MMA8451Q::OrientationDetect( void(*fptr)(void))
AxedaCorp 0:65004368569c 238 {
AxedaCorp 0:65004368569c 239 OrientationDetect( fptr, Z_LOCKOUT_14, Z_BKFR_80, PL_THS_15, PL_HYS_0);
AxedaCorp 0:65004368569c 240 }
AxedaCorp 0:65004368569c 241
AxedaCorp 0:65004368569c 242 void MMA8451Q::OrientationDetect( void(*fptr)(void), unsigned int Z_LockOut, unsigned int Z_BkFr, unsigned int PL_Thsld, unsigned int PL_Hyst)
AxedaCorp 0:65004368569c 243 {
AxedaCorp 0:65004368569c 244 unsigned char t;
AxedaCorp 0:65004368569c 245
AxedaCorp 0:65004368569c 246 // Soft Reset
AxedaCorp 0:65004368569c 247 Reset();
AxedaCorp 0:65004368569c 248
AxedaCorp 0:65004368569c 249 // Reset orientation value.
AxedaCorp 0:65004368569c 250 OrientationState = 0;
AxedaCorp 0:65004368569c 251 OrientationStateUpdated = 0;
AxedaCorp 0:65004368569c 252
AxedaCorp 0:65004368569c 253 // Step 1: Put the part into Standby Mode
AxedaCorp 0:65004368569c 254 Standby();
AxedaCorp 0:65004368569c 255
AxedaCorp 0:65004368569c 256 // Step 2: Set the data rate to 50 Hz (for example, but can choose any sample rate).
AxedaCorp 0:65004368569c 257 readRegs( REG_CTRL_REG_1, &t, 1); // Note: Can combine this step with above
AxedaCorp 0:65004368569c 258 t &= 0xC7; // Clear the sample rate bits
AxedaCorp 0:65004368569c 259 t |= 0x20; // Set the sample rate bits to 50 Hz
AxedaCorp 0:65004368569c 260 unsigned char data[2] = {REG_CTRL_REG_1, t};
AxedaCorp 0:65004368569c 261 writeRegs(data, 2); // Write updated value into the register.
AxedaCorp 0:65004368569c 262
AxedaCorp 0:65004368569c 263
AxedaCorp 0:65004368569c 264 // Step 3: Set the PL_EN bit in Register 0x11 PL_CFG. This will enable the orientation detection.
AxedaCorp 0:65004368569c 265 readRegs( REG_DBCNTM, &t, 1);
AxedaCorp 0:65004368569c 266 data[0] = REG_DBCNTM;
AxedaCorp 0:65004368569c 267 data[1] = t | 0x40;
AxedaCorp 0:65004368569c 268 writeRegs(data, 2);
AxedaCorp 0:65004368569c 269
AxedaCorp 0:65004368569c 270 // Step 4: Set the Back/Front Angle trip points in register 0x13 following the table in the data sheet.
AxedaCorp 0:65004368569c 271 // NOTE: This register is readable in all versions of MMA845xQ but it is only modifiable in the
AxedaCorp 0:65004368569c 272 // MMA8451Q.
AxedaCorp 0:65004368569c 273 readRegs( REG_BKFR, &t, 1);
AxedaCorp 0:65004368569c 274 t &= 0x3F; // Clear bit 7 and 6
AxedaCorp 0:65004368569c 275 data[0] = REG_BKFR;
AxedaCorp 0:65004368569c 276 data[1] = t | Z_BkFr;
AxedaCorp 0:65004368569c 277 writeRegs(data, 2); // Write in the updated Back/Front Angle
AxedaCorp 0:65004368569c 278
AxedaCorp 0:65004368569c 279 // Step 5: Set the Z-Lockout angle trip point in register 0x13 following the table in the data sheet.
AxedaCorp 0:65004368569c 280 // NOTE: This register is readable in all versions of MMA845xQ but it is only modifiable in the
AxedaCorp 0:65004368569c 281 // MMA8451Q.
AxedaCorp 0:65004368569c 282 readRegs( REG_BKFR, &t, 1);
AxedaCorp 0:65004368569c 283 t &= 0xF8; // Clear the last three bits of the register
AxedaCorp 0:65004368569c 284 data[0] = REG_BKFR;
AxedaCorp 0:65004368569c 285 data[1] = t | Z_LockOut;
AxedaCorp 0:65004368569c 286 writeRegs(data, 2); // Write in the updated Z-lockout angle
AxedaCorp 0:65004368569c 287
AxedaCorp 0:65004368569c 288 // Step 6: Set the Trip Threshold Angle
AxedaCorp 0:65004368569c 289 // NOTE: This register is readable in all versions of MMA845xQ but it is only modifiable in the
AxedaCorp 0:65004368569c 290 // MMA8451Q.
AxedaCorp 0:65004368569c 291 // Select the angle desired in the table, and,
AxedaCorp 0:65004368569c 292 // Enter in the values given in the table for the corresponding angle.
AxedaCorp 0:65004368569c 293 // Refer to Figure 7 for the reference frame of the trip angles.
AxedaCorp 0:65004368569c 294 readRegs( REG_P_L_THS, &t, 1);
AxedaCorp 0:65004368569c 295 t &= 0x07; // Clear the Threshold values
AxedaCorp 0:65004368569c 296 data[0] = REG_P_L_THS;
AxedaCorp 0:65004368569c 297 data[1] = t | (PL_Thsld<<3);
AxedaCorp 0:65004368569c 298 writeRegs(data, 2);
AxedaCorp 0:65004368569c 299
AxedaCorp 0:65004368569c 300 // Step 7: Set the Hysteresis Angle
AxedaCorp 0:65004368569c 301 // NOTE: This register is readable in all versions of MMA845xQ but it is only modifiable in the
AxedaCorp 0:65004368569c 302 // MMA8451Q.
AxedaCorp 0:65004368569c 303 // Select the hysteresis value based on the desired final trip points (threshold + hysteresis)
AxedaCorp 0:65004368569c 304 // Enter in the values given in the table for that corresponding angle.
AxedaCorp 0:65004368569c 305 // Note: Care must be taken. Review the final resulting angles. Make sure there isn’t a resulting trip value
AxedaCorp 0:65004368569c 306 // greater than 90 or less than 0.
AxedaCorp 0:65004368569c 307 // The following are the options for setting the hysteresis.
AxedaCorp 0:65004368569c 308 readRegs( REG_P_L_THS, &t, 1);
AxedaCorp 0:65004368569c 309 t &= 0xF8; // Clear the Hysteresis values
AxedaCorp 0:65004368569c 310 data[0] = REG_P_L_THS;
AxedaCorp 0:65004368569c 311 data[1] = t | PL_Hyst;
AxedaCorp 0:65004368569c 312 writeRegs(data, 2);
AxedaCorp 0:65004368569c 313
AxedaCorp 0:65004368569c 314 // Step 8: Register 0x2D, Control Register 4 configures all embedded features for interrupt
AxedaCorp 0:65004368569c 315 // detection.
AxedaCorp 0:65004368569c 316 // To set this device up to run an interrupt service routine:
AxedaCorp 0:65004368569c 317 // Program the Orientation Detection bit in Control Register 4.
AxedaCorp 0:65004368569c 318 // Set bit 4 to enable the orientation detection “INT_EN_LNDPRT”.
AxedaCorp 0:65004368569c 319 readRegs( REG_CTRL_REG_4, &t, 1);
AxedaCorp 0:65004368569c 320 data[0] = REG_CTRL_REG_4;
AxedaCorp 0:65004368569c 321 data[1] = t | 0x10; // Set bit 4
AxedaCorp 0:65004368569c 322 writeRegs(data, 2);
AxedaCorp 0:65004368569c 323
AxedaCorp 0:65004368569c 324 // Step 9: Register 0x2E is Control Register 5 which gives the option of routing the interrupt to
AxedaCorp 0:65004368569c 325 // either INT1 or INT2
AxedaCorp 0:65004368569c 326 // Depending on which interrupt pin is enabled and configured to the processor:
AxedaCorp 0:65004368569c 327 // Set bit 4 “INT_CFG_LNDPRT” to configure INT1, or,
AxedaCorp 0:65004368569c 328 // Leave the bit clear to configure INT2.
AxedaCorp 0:65004368569c 329 readRegs( REG_CTRL_REG_5, &t, 1);
AxedaCorp 0:65004368569c 330 data[0] = REG_CTRL_REG_5;
AxedaCorp 0:65004368569c 331 data[1] = t | 0x10; // Set bit 4 to choose the interrupt to route to INT1
AxedaCorp 0:65004368569c 332 writeRegs(data, 2);
AxedaCorp 0:65004368569c 333
AxedaCorp 0:65004368569c 334 // Step 10: Set the debounce counter in register 0x12
AxedaCorp 0:65004368569c 335 // This value will scale depending on the application-specific required ODR.
AxedaCorp 0:65004368569c 336 // If the device is set to go to sleep, reset the debounce counter before the device goes to sleep. This setting
AxedaCorp 0:65004368569c 337 // helps avoid long delays since the debounce will always scale with the current sample rate. The debounce
AxedaCorp 0:65004368569c 338 // can be set between 50 ms - 100 ms to avoid long delays.
AxedaCorp 0:65004368569c 339 data[0] = REG_DBNCE;
AxedaCorp 0:65004368569c 340 data[1] = 0x05; // This sets the debounce counter to 100 ms at 50 Hz
AxedaCorp 0:65004368569c 341 writeRegs(data, 2);
AxedaCorp 0:65004368569c 342
AxedaCorp 0:65004368569c 343 // Step 11: Put the device in Active Mode
AxedaCorp 0:65004368569c 344 Active();
AxedaCorp 0:65004368569c 345
AxedaCorp 0:65004368569c 346 MMA8451Q_usr1_fptr = fptr;
AxedaCorp 0:65004368569c 347 MMA8451Q_Int1.fall( this, &MMA8451Q::Orientation_IRQ);
AxedaCorp 0:65004368569c 348
AxedaCorp 0:65004368569c 349 }
AxedaCorp 0:65004368569c 350
AxedaCorp 0:65004368569c 351 void MMA8451Q::Orientation_IRQ( void)
AxedaCorp 0:65004368569c 352 {
AxedaCorp 0:65004368569c 353 unsigned char t;
AxedaCorp 0:65004368569c 354
AxedaCorp 0:65004368569c 355 // Determine source of the interrupt by first reading the system interrupt
AxedaCorp 0:65004368569c 356 readRegs( REG_INT_SRC, &t, 1);
AxedaCorp 0:65004368569c 357 //
AxedaCorp 0:65004368569c 358 if ( (t & 0x10) == 0x10) {
AxedaCorp 0:65004368569c 359 // Read the PL State from the Status Register, clear the interrupt
AxedaCorp 0:65004368569c 360 readRegs( REG_PL_STATUS, &t, 1);
AxedaCorp 0:65004368569c 361 // Set the orientation state variable
AxedaCorp 0:65004368569c 362 OrientationState = t;
AxedaCorp 0:65004368569c 363 OrientationStateUpdated = 1;
AxedaCorp 0:65004368569c 364 // Run the user supplied function
AxedaCorp 0:65004368569c 365 MMA8451Q_usr1_fptr();
AxedaCorp 0:65004368569c 366 }
AxedaCorp 0:65004368569c 367 }
AxedaCorp 0:65004368569c 368
AxedaCorp 0:65004368569c 369 unsigned char MMA8451Q::GetOrientationState( void)
AxedaCorp 0:65004368569c 370 {
AxedaCorp 0:65004368569c 371 if ( OrientationStateUpdated) {
AxedaCorp 0:65004368569c 372 OrientationStateUpdated = 0;
AxedaCorp 0:65004368569c 373 return OrientationState;
AxedaCorp 0:65004368569c 374 }
AxedaCorp 0:65004368569c 375 //
AxedaCorp 0:65004368569c 376 return 0;
AxedaCorp 0:65004368569c 377 }
AxedaCorp 0:65004368569c 378
AxedaCorp 0:65004368569c 379 void MMA8451Q::DataReady( void(*fptr)(void), unsigned char ODR)
AxedaCorp 0:65004368569c 380 {
AxedaCorp 0:65004368569c 381 // Soft Reset
AxedaCorp 0:65004368569c 382 Reset();
AxedaCorp 0:65004368569c 383
AxedaCorp 0:65004368569c 384 // Step 1: Put the device into Standby Mode: Register 0x2A CTRL_REG1
AxedaCorp 0:65004368569c 385 // Set the device ODR value and Standby
AxedaCorp 0:65004368569c 386 unsigned char data[2] = {REG_CTRL_REG_1, ((ODR<<3) & 0xFE)};
AxedaCorp 0:65004368569c 387 writeRegs(data, 2);
AxedaCorp 0:65004368569c 388
AxedaCorp 0:65004368569c 389 // Step 2: Enable Data Ready Interrupt Function in the System (CTRL_REG4)
AxedaCorp 0:65004368569c 390 data[0] = REG_CTRL_REG_4;
AxedaCorp 0:65004368569c 391 data[1] = 0x01;
AxedaCorp 0:65004368569c 392 writeRegs(data, 2);
AxedaCorp 0:65004368569c 393
AxedaCorp 0:65004368569c 394 // Step 6: Route the Data Ready Interrupt Function to INT2 hardware pin (CTRL_REG5)
AxedaCorp 0:65004368569c 395 data[0] = REG_CTRL_REG_5;
AxedaCorp 0:65004368569c 396 data[1] = 0x00;
AxedaCorp 0:65004368569c 397 writeRegs(data, 2);
AxedaCorp 0:65004368569c 398
AxedaCorp 0:65004368569c 399 // Step 7: Put the device in Active Mode
AxedaCorp 0:65004368569c 400 data[0] = REG_CTRL_REG_1;
AxedaCorp 0:65004368569c 401 data[1] = ((ODR<<3) | 0x01);
AxedaCorp 0:65004368569c 402 writeRegs(data, 2);
AxedaCorp 0:65004368569c 403
AxedaCorp 0:65004368569c 404 MMA8451Q_usr2_fptr = fptr;
AxedaCorp 0:65004368569c 405 MMA8451Q_Int2.fall( this, &MMA8451Q::DataReady_IRQ);
AxedaCorp 0:65004368569c 406
AxedaCorp 0:65004368569c 407 }
AxedaCorp 0:65004368569c 408
AxedaCorp 0:65004368569c 409 void MMA8451Q::DataReady_IRQ( void)
AxedaCorp 0:65004368569c 410 {
AxedaCorp 0:65004368569c 411 unsigned char t;
AxedaCorp 0:65004368569c 412
AxedaCorp 0:65004368569c 413 // Determine source of the interrupt by first reading the system interrupt
AxedaCorp 0:65004368569c 414 readRegs( REG_INT_SRC, &t, 1);
AxedaCorp 0:65004368569c 415 //
AxedaCorp 0:65004368569c 416 if ( (t & 0x01) == 0x01) {
AxedaCorp 0:65004368569c 417 // Read the DataReady_IRQ Function to clear the interrupt
AxedaCorp 0:65004368569c 418 readRegs( REG_FF_MT_SRC, &t, 1);
AxedaCorp 0:65004368569c 419 // Run the user supplied function
AxedaCorp 0:65004368569c 420 MMA8451Q_usr2_fptr();
AxedaCorp 0:65004368569c 421 }
AxedaCorp 0:65004368569c 422 }
AxedaCorp 0:65004368569c 423
AxedaCorp 0:65004368569c 424
AxedaCorp 0:65004368569c 425 void MMA8451Q::Active( void)
AxedaCorp 0:65004368569c 426 {
AxedaCorp 0:65004368569c 427 unsigned char t;
AxedaCorp 0:65004368569c 428
AxedaCorp 0:65004368569c 429 // Activate the peripheral
AxedaCorp 0:65004368569c 430 readRegs(REG_CTRL_REG_1, &t, 1);
AxedaCorp 0:65004368569c 431 unsigned char data[2] = {REG_CTRL_REG_1, t|0x01};
AxedaCorp 0:65004368569c 432 writeRegs(data, 2);
AxedaCorp 0:65004368569c 433 }
AxedaCorp 0:65004368569c 434
AxedaCorp 0:65004368569c 435 void MMA8451Q::Standby( void)
AxedaCorp 0:65004368569c 436 {
AxedaCorp 0:65004368569c 437 unsigned char t;
AxedaCorp 0:65004368569c 438
AxedaCorp 0:65004368569c 439 // Standby
AxedaCorp 0:65004368569c 440 readRegs(REG_CTRL_REG_1, &t, 1);
AxedaCorp 0:65004368569c 441 unsigned char data[2] = {REG_CTRL_REG_1, t&0xFE};
AxedaCorp 0:65004368569c 442 writeRegs(data, 2);
AxedaCorp 0:65004368569c 443 }
AxedaCorp 0:65004368569c 444
AxedaCorp 0:65004368569c 445 uint8_t MMA8451Q::getWhoAmI() {
AxedaCorp 0:65004368569c 446 uint8_t who_am_i = 0;
AxedaCorp 0:65004368569c 447 readRegs(REG_WHO_AM_I, &who_am_i, 1);
AxedaCorp 0:65004368569c 448 return who_am_i;
AxedaCorp 0:65004368569c 449 }
AxedaCorp 0:65004368569c 450
AxedaCorp 0:65004368569c 451 float MMA8451Q::getAccX() {
AxedaCorp 0:65004368569c 452 return (float(getAccAxis(REG_OUT_X_MSB))/4096.0);
AxedaCorp 0:65004368569c 453 }
AxedaCorp 0:65004368569c 454
AxedaCorp 0:65004368569c 455 float MMA8451Q::getAccY() {
AxedaCorp 0:65004368569c 456 return (float(getAccAxis(REG_OUT_Y_MSB))/4096.0);
AxedaCorp 0:65004368569c 457 }
AxedaCorp 0:65004368569c 458
AxedaCorp 0:65004368569c 459 float MMA8451Q::getAccZ() {
AxedaCorp 0:65004368569c 460 return (float(getAccAxis(REG_OUT_Z_MSB))/4096.0);
AxedaCorp 0:65004368569c 461 }
AxedaCorp 0:65004368569c 462
AxedaCorp 0:65004368569c 463 void MMA8451Q::getAccAllAxis(float * res) {
AxedaCorp 0:65004368569c 464 res[0] = getAccX();
AxedaCorp 0:65004368569c 465 res[1] = getAccY();
AxedaCorp 0:65004368569c 466 res[2] = getAccZ();
AxedaCorp 0:65004368569c 467 }
AxedaCorp 0:65004368569c 468
AxedaCorp 0:65004368569c 469 int16_t MMA8451Q::getAccAxis(uint8_t addr) {
AxedaCorp 0:65004368569c 470 int16_t acc;
AxedaCorp 0:65004368569c 471 uint8_t res[2];
AxedaCorp 0:65004368569c 472 readRegs(addr, res, 2);
AxedaCorp 0:65004368569c 473
AxedaCorp 0:65004368569c 474 acc = (res[0] << 6) | (res[1] >> 2);
AxedaCorp 0:65004368569c 475 if (acc > UINT14_MAX/2)
AxedaCorp 0:65004368569c 476 acc -= UINT14_MAX;
AxedaCorp 0:65004368569c 477
AxedaCorp 0:65004368569c 478 return acc;
AxedaCorp 0:65004368569c 479 }
AxedaCorp 0:65004368569c 480
AxedaCorp 0:65004368569c 481 unsigned int MMA8451Q::getAccRawAllAxis( int16_t * res)
AxedaCorp 0:65004368569c 482 {
AxedaCorp 0:65004368569c 483 if ( isDataAvailable() & ZYXDR)
AxedaCorp 0:65004368569c 484 {
AxedaCorp 0:65004368569c 485 getAccRawX( &res[0]);
AxedaCorp 0:65004368569c 486 getAccRawY( &res[1]);
AxedaCorp 0:65004368569c 487 getAccRawZ( &res[2]);
AxedaCorp 0:65004368569c 488 return 1;
AxedaCorp 0:65004368569c 489 } else
AxedaCorp 0:65004368569c 490 return 0;
AxedaCorp 0:65004368569c 491 }
AxedaCorp 0:65004368569c 492
AxedaCorp 0:65004368569c 493 int16_t MMA8451Q::getAccRawX( int16_t * res)
AxedaCorp 0:65004368569c 494 {
AxedaCorp 0:65004368569c 495 if ( isDataAvailable() & XDR)
AxedaCorp 0:65004368569c 496 {
AxedaCorp 0:65004368569c 497 *res = getAccAxis(REG_OUT_X_MSB);
AxedaCorp 0:65004368569c 498 return 1;
AxedaCorp 0:65004368569c 499 } else
AxedaCorp 0:65004368569c 500 return 0;
AxedaCorp 0:65004368569c 501 }
AxedaCorp 0:65004368569c 502
AxedaCorp 0:65004368569c 503 int16_t MMA8451Q::getAccRawY( int16_t * res)
AxedaCorp 0:65004368569c 504 {
AxedaCorp 0:65004368569c 505 if ( isDataAvailable() & YDR)
AxedaCorp 0:65004368569c 506 {
AxedaCorp 0:65004368569c 507 *res = getAccAxis(REG_OUT_Y_MSB);
AxedaCorp 0:65004368569c 508 return 1;
AxedaCorp 0:65004368569c 509 } else
AxedaCorp 0:65004368569c 510 return 0;
AxedaCorp 0:65004368569c 511 }
AxedaCorp 0:65004368569c 512
AxedaCorp 0:65004368569c 513 int16_t MMA8451Q::getAccRawZ( int16_t * res)
AxedaCorp 0:65004368569c 514 {
AxedaCorp 0:65004368569c 515 if ( isDataAvailable() & ZDR)
AxedaCorp 0:65004368569c 516 {
AxedaCorp 0:65004368569c 517 *res = getAccAxis(REG_OUT_Z_MSB);
AxedaCorp 0:65004368569c 518 return 1;
AxedaCorp 0:65004368569c 519 } else
AxedaCorp 0:65004368569c 520 return 0;
AxedaCorp 0:65004368569c 521 }
AxedaCorp 0:65004368569c 522
AxedaCorp 0:65004368569c 523 unsigned int MMA8451Q::isDataAvailable( void)
AxedaCorp 0:65004368569c 524 {
AxedaCorp 0:65004368569c 525 unsigned char status;
AxedaCorp 0:65004368569c 526
AxedaCorp 0:65004368569c 527 readRegs( REG_STATUS, &status, 1);
AxedaCorp 0:65004368569c 528
AxedaCorp 0:65004368569c 529 return (status);
AxedaCorp 0:65004368569c 530
AxedaCorp 0:65004368569c 531 }
AxedaCorp 0:65004368569c 532
AxedaCorp 0:65004368569c 533 void MMA8451Q::readRegs(int addr, uint8_t * data, int len) {
AxedaCorp 0:65004368569c 534 char t[1] = {addr};
AxedaCorp 0:65004368569c 535 m_i2c.write(m_addr, t, 1, true);
AxedaCorp 0:65004368569c 536 m_i2c.read(m_addr, (char *)data, len);
AxedaCorp 0:65004368569c 537 }
AxedaCorp 0:65004368569c 538
AxedaCorp 0:65004368569c 539 void MMA8451Q::writeRegs(uint8_t * data, int len) {
AxedaCorp 0:65004368569c 540 m_i2c.write(m_addr, (char *)data, len);
AxedaCorp 0:65004368569c 541 }