mma8451q driver with a few minor modifications

Dependents:   Senet NAMote

Fork of lib_mma8451q by wayne roberts

Revision:
6:828b08201d8b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mma8451q.cpp.orig	Fri Aug 12 14:13:17 2016 +0000
@@ -0,0 +1,312 @@
+#include "mma8451q.h"
+/* turn on: CTRL_REG1 active_bit = 1
+ * back to standby: CTRL_REG1 active_bit = 0
+ */
+
+/* STANDBY: SYSMOD = 00 */
+
+/*
+ * MMA8451 I2C address
+ */ 
+#define MMA8451_I2C_ADDRESS                          0x38 //0x1C
+
+MMA8451Q::MMA8451Q(I2C& r, DigitalIn& int_pin) : m_i2c(r), m_int_pin(int_pin)
+{
+    /* INT pins on this chip default to push-pull output */
+    write(MMA8451_CTRL_REG3, 0x01);    // set PP_OD
+    /* INT1 and INT2 are tied together */
+    
+}
+
+MMA8451Q::~MMA8451Q()
+{
+}
+
+void MMA8451Q::read(uint8_t addr, uint8_t *dst_buf, int length)
+{
+    char cmd[2];
+
+    cmd[0] = addr;
+    if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 1, true))
+        printf("MMA write-fail %02x\n", addr);
+    if (m_i2c.read(MMA8451_I2C_ADDRESS, (char *)dst_buf, length))
+        printf("MMA read-fail\n");
+}
+
+uint8_t MMA8451Q::read_single(uint8_t addr)
+{
+    char cmd[2];
+
+    cmd[0] = addr;
+    if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 1, true))
+        printf("MMA write-fail %02x\n", addr);
+    if (m_i2c.read(MMA8451_I2C_ADDRESS, cmd, 1))
+        printf("MMA read-fail\n");
+
+    return cmd[0];
+}
+
+void MMA8451Q::print_regs()
+{
+    printf("ID: %02x\r\n", read_single(MMA8451_ID));
+    printf("sysmod:%02x\r\n", read_single(MMA8451_SYSMOD));
+    ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1);
+    printf("ctrl_reg1:%02x\r\n", ctrl_reg1.octet);
+    printf("ctrl_reg2:%02x\r\n", read_single(MMA8451_CTRL_REG2));
+    printf("ctrl_reg3:%02x\r\n", read_single(MMA8451_CTRL_REG3)); /* TODO: PP_OD is bit 0 (1=open drain) */
+    printf("(int en) ctrl_reg4:%02x\r\n", read_single(MMA8451_CTRL_REG4));
+    printf("(int cfg) ctrl_reg5:%02x\r\n", read_single(MMA8451_CTRL_REG5));
+    printf("status:%02x\r\n", read_single(MMA8451_STATUS)); 
+    /* (interrupt status) int src at 0x0c (MMA8451_INT_SOURCE): data ready, motion/freefall, pulse, orientation, transient, auto sleep */
+    printf("INT_SOURCE:%02x\r\n", read_single(MMA8451_INT_SOURCE)); 
+}
+
+void MMA8451Q::write(uint8_t addr, uint8_t data)
+{
+    uint8_t cmd[2];
+    
+    cmd[0] = addr;
+    cmd[1] = data;
+
+    if (m_i2c.write(MMA8451_I2C_ADDRESS, (char *)cmd, 2))
+        printf("MMA write-fail %02x\n", addr);
+}
+
+void MMA8451Q::set_active(char arg)
+{
+    char cmd[2];
+    
+    cmd[0] = MMA8451_CTRL_REG1;
+    cmd[1] = arg;
+
+    if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 2))
+        printf("MMA write-fail %02x\n", cmd[0]);
+}
+
+bool MMA8451Q::get_active(void)
+{
+    uint8_t ret = read_single(MMA8451_CTRL_REG1);
+    //printf("CTRL_REG1: %x\n", ret);
+    if (ret & 1)
+        return true;
+    else
+        return false;
+}
+
+void MMA8451Q::orient_detect()
+{
+    uint8_t v;
+    
+    ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1);
+    /* AN4068 Sensors Freescale Semiconductor, Inc.    
+     * 4.1 Example Steps for Implementing the Embedded Orientation Detection */
+     
+     /* Step 1: Put the part into Standby Mode */
+    ctrl_reg1.bits.ACTIVE = 0;
+    write(MMA8451_CTRL_REG1, ctrl_reg1.octet);     
+     
+    /* Step 2: Set the data rate to 50 Hz (for example, but can choose any sample rate). */
+    ctrl_reg1.bits.DR = 4;
+    write(MMA8451_CTRL_REG1, ctrl_reg1.octet);
+    
+    /* Step 3: Set the PL_EN bit in Register 0x11 PL_CFG. This will enable the orientation detection. */
+    v = read_single(MMA8451_PL_CFG);
+    v |= 0x40;
+    write(MMA8451_PL_CFG, v);
+    
+    /* Step 4: Set the Back/Front Angle trip points in register 0x13 following the table in the data sheet. */
+    v = read_single(MMA8451_PL_BF_ZCOMP);
+    /*v &= 0x3f;
+    v |= 0xX0;
+    write(MMA8451_PL_BF_ZCOMP, v);*/
+    
+    /* Step 5: Set the Z-Lockout angle trip point in register 0x13 following the table in the data sheet. */
+    /* v &= 0xf8;
+    v |= 0x0X;
+    */
+    
+    /* Step 6: Set the Trip Threshold Angle */
+    v = read_single(MMA8451_PL_THS_REG);
+    /*v &= 0x07;
+    v |= 0x0X << 3;
+    write(MMA8451_PL_THS_REG. v);*/
+    
+    /* Step 7: Set the Hysteresis Angle */
+    v = read_single(MMA8451_PL_THS_REG);
+    /*v &= 0xf8;
+    v |= 0x0X;
+    write(MMA8451_PL_THS_REG. v);*/    
+    
+    /* Step 8: Register 0x2D, Control Register 4 configures all embedded features for interrupt */
+    ctrl_reg4.octet = 0;
+    ctrl_reg4.bits.INT_EN_LNDPRT = 1;
+    write(MMA8451_CTRL_REG4, ctrl_reg4.octet);
+    
+    /* Step 9: Register 0x2E is Control Register 5 which gives the option of routing the interrupt to either INT1 or INT2 */
+    ctrl_reg5.octet = 0;
+    ctrl_reg5.bits.INT_CFG_LNDPRT = 1;
+    write(MMA8451_CTRL_REG5, ctrl_reg5.octet);
+        
+    /* Step 10: Set the debounce counter in register 0x12 */
+    write(MMA8451_PL_COUNT, 5); // 5: debounce to 100ms at 50hz
+    
+    /* Step 11: Put the device in Active Mode */
+    ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1);
+    ctrl_reg1.bits.ACTIVE = 1;
+    write(MMA8451_CTRL_REG1, ctrl_reg1.octet);
+        
+    /* Step 12: in service() function */
+}
+
+
+void MMA8451Q::transient_detect()
+{
+    ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1);
+    /* AN4071 Sensors Freescale Semiconductor, Inc.
+     * 7.1 Example Steps for Configuring Transient Detection
+     * Change in X or Y > 0.5g for 50 ms at 100 Hz ODR, Normal mode */
+
+    /* Step 1: Put the device in Standby Mode: Register 0x2A CTRL_REG1 */
+    ctrl_reg1.bits.ACTIVE = 0;
+    write(MMA8451_CTRL_REG1, ctrl_reg1.octet);
+    ctrl_reg1.bits.DR = 3; //Set device in 100 Hz ODR, Standby
+    write(MMA8451_CTRL_REG1, ctrl_reg1.octet);
+
+    /* Step 2: Enable X and Y Axes and enable the latch: Register 0x1D Configuration Register */
+    transient_cfg.octet = 0;
+    transient_cfg.bits.ELE = 1; // enable latch
+    transient_cfg.bits.YTEFE = 1;   // enable Y
+    transient_cfg.bits.XTEFE = 1;   // enable X
+    transient_cfg.bits.ZTEFE = 1;   // enable Z
+    write(MMA8451_TRANSIENT_CFG, transient_cfg.octet);
+
+    /* Step 3: Set the Threshold: Register 0x1F 
+     * Note: Step count is 0.063g per count, 0.5g / 0.063g = 7.93.
+     * Therefore set the threshold to 8 counts */
+    write(MMA8451_TRANSIENT_THS, 8);
+
+    /* Step 4: Set the Debounce Counter for 50 ms: Register 0x20
+     * Note: 100 Hz ODR, therefore 10 ms step sizes */
+    write(MMA8451_TRANSIENT_COUNT, 5);
+
+    /* Step 5: Enable Transient Detection Interrupt in the System (CTRL_REG4) */
+    ctrl_reg4.octet = 0;
+    ctrl_reg4.bits.INT_EN_TRANS = 1;
+    write(MMA8451_CTRL_REG4, ctrl_reg4.octet);
+
+    /* Step 6: Route the Transient Interrupt to INT 1 hardware pin (CTRL_REG5) */
+    ctrl_reg5.octet = 0;
+    ctrl_reg5.bits.INT_CFG_TRANS = 1;
+    write(MMA8451_CTRL_REG5, ctrl_reg5.octet);
+
+    /* Step 7: Put the device in Active Mode: Register 0x2A CTRL_REG1 */
+    ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1);
+    ctrl_reg1.bits.ACTIVE = 1;
+    write(MMA8451_CTRL_REG1, ctrl_reg1.octet);
+
+    /* Step 8: Write Interrupt Service Routine Reading the
+     * System Interrupt Status and the Transient Status */
+}
+
+uint8_t MMA8451Q::service()
+{
+    mma_int_source_t int_src;
+    
+    if (m_int_pin)
+        return 0; // no interrupt
+        
+    int_src.octet = read_single(MMA8451_INT_SOURCE);
+    
+    if (int_src.bits.SRC_DRDY) {
+        read(MMA8451_OUT_X_MSB, out.octets, 6);
+    }
+    if (int_src.bits.SRC_FF_MT) {
+        read_single(MMA8451_FF_MT_SRC);
+    }
+    if (int_src.bits.SRC_PULSE) {
+        read_single(MMA8451_PULSE_SRC);
+    }
+    if (int_src.bits.SRC_LNDPRT) {
+        mma_pl_status_t pl_status;
+        /*AN4068 Step 12: Write a Service Routine to Service the Interrupt */
+        pl_status.octet = read_single(MMA8451_PL_STATUS);
+
+        if(verbose)
+            printf("PL_STATUS: ");
+
+        if (pl_status.bits.NEWLP) 
+        { 
+            orientation.reset();
+
+            if (pl_status.bits.LO)
+            {
+                orientation.low = true;
+                if(verbose)
+                    printf("Z-tilt-LO ");
+            }
+                
+
+            if (pl_status.bits.LAPO == 0)
+            {
+                orientation.up = true;
+                if(verbose)
+                    printf("up ");
+            }
+            else if (pl_status.bits.LAPO == 1)
+            {
+                orientation.down = true;
+                if(verbose)
+                    printf("down ");
+            }
+            else if (pl_status.bits.LAPO == 2)
+            {
+                orientation.right = true;
+                if(verbose)
+                    printf("right ");
+            }
+            else if (pl_status.bits.LAPO == 3)
+            {
+                orientation.left = true;
+                if(verbose)
+                    printf("left ");
+            }
+            
+            if (pl_status.bits.BAFRO)
+            {
+                orientation.back = true;
+                if(verbose)
+                    printf("back ");
+            }
+            else
+            {
+                orientation.front = true;
+                if(verbose)
+                    printf("front ");
+            }
+        }
+
+        if(verbose)
+            printf("\r\n");
+    } // ...int_src.bits.SRC_LNDPRT
+                         
+    if (int_src.bits.SRC_TRANS) {
+        transient_src_t t_src;
+        t_src.octet = read_single(MMA8451_TRANSIENT_SRC);
+        if (verbose) {
+            printf("transient src:%x ", t_src.octet);
+            if (t_src.bits.XTRANSE)
+                printf("X_Pol:%d ", t_src.bits.X_Trans_Pol);
+            if (t_src.bits.YTRANSE)
+                printf("Y_Pol:%d ", t_src.bits.Y_Trans_Pol);
+            if (t_src.bits.ZTRANSE)
+                printf("Z_Pol:%d ", t_src.bits.Z_Trans_Pol);
+            printf("\r\n");        
+        } 
+    } // ...int_src.bits.SRC_TRANS
+    
+    if (int_src.bits.SRC_ASLP) {
+        read_single(MMA8451_SYSMOD);
+    }
+    
+    return int_src.octet;
+}