Added code to manage Orientation, FreeFall and Motion Detection. Data is also available via IRQ.

Dependents:   Test_FRDM_MMA8451Q AccelTest FRDM-KL46-Template KL25Z_Demo ... more

Fork of MMA8451Q by Emilio Monti

Revision:
5:695063448f2a
Parent:
3:db7126dbd63f
Child:
6:c52175d13e0a
--- a/MMA8451Q.cpp	Fri Oct 12 11:35:07 2012 +0000
+++ b/MMA8451Q.cpp	Tue May 28 04:39:42 2013 +0000
@@ -20,19 +20,187 @@
 
 #define REG_WHO_AM_I      0x0D
 #define REG_CTRL_REG_1    0x2A
+#define REG_CTRL_REG_4    0x2D
+#define REG_CTRL_REG_5    0x2E
+#define REG_INT_SRC       0x0C
+#define REG_FF_MT_CFG     0x15
+#define REG_FF_MT_SRC     0x16
+#define REG_FF_MT_THS     0x17
+#define REG_FF_MT_CNT     0x18
+//
 #define REG_OUT_X_MSB     0x01
 #define REG_OUT_Y_MSB     0x03
 #define REG_OUT_Z_MSB     0x05
 
 #define UINT14_MAX        16383
 
+void (*fall_fptr)(void);
+void (*motion_fptr)(void);
+
+//
+InterruptIn MMA8451Q_Int1( PTA14);
+InterruptIn MMA8451Q_Int2( PTA15);
+
 MMA8451Q::MMA8451Q(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr) {
     // activate the peripheral
     uint8_t data[2] = {REG_CTRL_REG_1, 0x01};
     writeRegs(data, 2);
 }
 
-MMA8451Q::~MMA8451Q() { }
+MMA8451Q::~MMA8451Q() 
+{
+     MMA8451Q_Int1.fall( NULL);
+     MMA8451Q_Int2.fall( NULL);
+     fall_fptr = NULL;
+     motion_fptr = NULL;
+}
+
+void MMA8451Q::FreFallDetection( void(*fptr)(void))
+{
+    // Example Steps for Configuring Linear Freefall Detection
+    // X AND Y AND Z < 0.2g using MFF Function, 50 Hz ODR
+    // Step 1: Put the device in Standby Mode: Register 0x2A CTRL_REG1
+    unsigned char data[2] = {REG_CTRL_REG_1, 0x20};
+    writeRegs(data, 2);
+    
+    // Step 2: Configuration Register set for Freefall Detection enabling “AND” condition, OAE = 0, Enabling X,
+    // Y, Z and the Latch
+    data[0] = REG_FF_MT_CFG;
+    data[1] = 0x01;
+    writeRegs(data, 2);
+
+    // Step 3: Threshold Setting Value for the resulting acceleration < 0.2g
+    // Note: The step count is 0.063g/count
+    // • 0.2g/0.063g = 3.17 counts //Round to 3 counts
+    data[0] = REG_FF_MT_THS;
+    data[1] = 0x03;
+    writeRegs(data, 2);
+
+    // Step 4: Set the debounce counter to eliminate false positive readings for 50Hz sample rate with a
+    // requirement of 120 ms timer, assuming Normal Mode.
+    // Note: 120 ms/20 ms (steps) = 6 counts
+    data[0] = REG_FF_MT_CNT;
+    data[1] = 0x06;
+    writeRegs(data, 2);
+
+    // Step 5: Enable Motion/Freefall Interrupt Function in the System (CTRL_REG4)
+    data[0] = REG_CTRL_REG_4;
+    data[1] = 0x04;
+    writeRegs(data, 2);
+
+    // Step 6: Route the Motion/Freefall Interrupt Function to INT2 hardware pin (CTRL_REG5)
+    data[0] = REG_CTRL_REG_5;
+    data[1] = 0x00;
+    writeRegs(data, 2);
+    
+    // Step 7: Put the device in Active Mode, 50 Hz
+    data[0] = REG_CTRL_REG_1;
+    data[1] = 0x21;
+    writeRegs(data, 2);
+    
+    fall_fptr = fptr;
+    MMA8451Q_Int2.fall( this, &MMA8451Q::Fall_IRQ);
+}
+
+void MMA8451Q::Fall_IRQ( void)
+{
+    unsigned char t;
+    
+    // Determine source of the interrupt by first reading the system interrupt
+    readRegs( REG_INT_SRC, &t, 1);
+    //
+    if ( (t & 0x04) == 0x04) {
+        // Read the Motion/Freefall Function to clear the interrupt
+        readRegs( REG_FF_MT_SRC, &t, 1);
+        // Run the user supplied function
+        fall_fptr();
+    }
+}
+
+void MMA8451Q::MotionDetection( void(*fptr)(void))
+{
+
+    // 6.1 Example Steps for Configuring Motion Detection
+    // X or Y > 3g using MFF Function 4g, 100 Hz ODR, Normal Mode
+    // Step 1: Put the device into Standby Mode: Register 0x2A CTRL_REG1
+    unsigned char data[2] = {REG_CTRL_REG_1, 0x18}; // Set the device in 100 Hz ODR, Standby
+    writeRegs(data, 2);
+
+    
+    // Step 2: Set Configuration Register for Motion Detection by setting the “OR” condition OAE = 1, enabling
+    // X, Y, and the latch
+    data[0] = REG_FF_MT_CFG;
+    data[1] = 0xD8;
+    writeRegs(data, 2);
+
+    // Step 3: Threshold Setting Value for the Motion detection of > 2g
+    // Note: The step count is 0.063g/ count
+    // • 2g/0.063g = 31.7; //Round up to 32
+    data[0] = REG_FF_MT_THS;
+    data[1] = 0x20;
+    writeRegs(data, 2);
+    
+    // Step 4: Set the debounce counter to eliminate false readings for 100 Hz sample rate with a requirement
+    // of 100 ms timer.
+    // Note: 100 ms/10 ms (steps) = 10 counts
+    data[0] = REG_FF_MT_CNT;
+    data[1] = 0x0A;
+    writeRegs(data, 2);
+    
+    // Step 5: Enable Motion/Freefall Interrupt Function in the System (CTRL_REG4)
+    data[0] = REG_CTRL_REG_4;
+    data[1] = 0x04;
+    writeRegs(data, 2);
+    
+    // Step 6: Route the Motion/Freefall Interrupt Function to INT1 hardware pin (CTRL_REG5)
+    data[0] = REG_CTRL_REG_5;
+    data[1] = 0x04;
+    writeRegs(data, 2);
+    
+    // Step 7: Put the device in Active Mode
+    data[0] = REG_CTRL_REG_1;
+    data[1] = 0x19;
+    writeRegs(data, 2);
+
+    motion_fptr = fptr;
+    MMA8451Q_Int1.fall( this, &MMA8451Q::Motion_IRQ);
+
+}
+
+void MMA8451Q::Motion_IRQ( void)
+{
+    unsigned char t;
+    
+    // Determine source of the interrupt by first reading the system interrupt
+    readRegs( REG_INT_SRC, &t, 1);
+    //
+    if ( (t & 0x04) == 0x04) {
+        // Read the Motion/Freefall Function to clear the interrupt
+        readRegs( REG_FF_MT_SRC, &t, 1);
+        // Run the user supplied function
+        motion_fptr();
+    }
+}
+
+void MMA8451Q::Active( void)
+{
+    unsigned char t;
+    
+    // Activate the peripheral
+    readRegs(REG_CTRL_REG_1, &t, 1);
+    unsigned char data[2] = {REG_CTRL_REG_1, t|0x01};
+    writeRegs(data, 2);
+}
+
+void MMA8451Q::Standby( void)
+{
+    unsigned char t;
+    
+    // Standby
+    readRegs(REG_CTRL_REG_1, &t, 1);
+    unsigned char data[2] = {REG_CTRL_REG_1, t&0xFE};
+    writeRegs(data, 2);
+}
 
 uint8_t MMA8451Q::getWhoAmI() {
     uint8_t who_am_i = 0;