Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Revision:
77:0b96f6867312
Parent:
76:7f5912b6340e
--- a/MMA8451Q/MMA8451Q.cpp	Fri Feb 03 20:50:02 2017 +0000
+++ b/MMA8451Q/MMA8451Q.cpp	Fri Mar 17 22:02:08 2017 +0000
@@ -18,12 +18,14 @@
 
 #include "MMA8451Q.h"
 
+#define REG_F_STATUS      0x00
+#define REG_F_SETUP       0x09
 #define REG_WHO_AM_I      0x0D
-#define REG_CTRL_REG_1    0x2A
-#define REG_CTRL_REG_2    0x2B
-#define REG_CTRL_REG_3    0x2c
-#define REG_CTRL_REG_4    0x2D
-#define REG_CTRL_REG_5    0x2E
+#define REG_CTRL_REG1     0x2A
+#define REG_CTRL_REG2     0x2B
+#define REG_CTRL_REG3     0x2c
+#define REG_CTRL_REG4     0x2D
+#define REG_CTRL_REG5     0x2E
 #define REG_OFF_X         0x2F
 #define REG_OFF_Y         0x30
 #define REG_OFF_Z         0x31
@@ -40,12 +42,29 @@
 #define FS_4G             0x01
 #define FS_8G             0x02
 
+#define F_STATUS_XDR_MASK 0x01  // F_STATUS - X sample ready
+#define F_STATUS_YDR_MASK 0x02  // F_STATUS - Y sample ready
+#define F_STATUS_ZDR_MASK 0x04  // F_STATUS - Z sample ready
+#define F_STATUS_XYZDR_MASK 0x08 // F_STATUS - XYZ sample ready
+#define F_STATUS_CNT_MASK 0x3F  // F_STATUS register mask for FIFO count
+
+#define F_MODE_MASK       0xC0  // F_SETUP register mask for FIFO mode
+#define F_WMRK_MASK       0x3F  // F_SETUP register mask for FIFO watermark
+
+#define F_MODE_DISABLED   0x00  // FIFO disabled
+#define F_MODE_CIRC       0x40  // circular FIFO
+#define F_MODE_STOP       0x80  // FIFO stops when full
+#define F_MODE_TRIGGER    0xC0  // FIFO triggers interrupt when watermark reached
+
 #define HPF_OUT_MASK      0x10
 
-#define MODS1_MASK        0x02
-#define MODS0_MASK        0x01
 #define SMODS_MASK        0x18
+
 #define MODS_MASK         0x03
+#define MODS_NORMAL       0x00   // mode 00 = normal power mode
+#define MODS_LOW_NOISE    0x01   // mode 01 = low noise, low power
+#define MODS_HI_RES       0x02   // mode 10 = high resolution
+#define MODS_LOW_POWER    0x03   // mode 11 = low power
 
 #define DR_MASK           0x38
 #define DR_800_HZ         0x00
@@ -57,6 +76,9 @@
 #define DR_6_HZ           0x30
 #define DR_1_HZ           0x38
 
+#define F_READ_MASK       0x02  // CTRL_REG1 F_READ bit - sets data size mode:
+                                // 1=fast read, 8-bit data; 0=14-bit data
+
 #define CTRL_REG3_IPOL_MASK  0x02
 #define CTRL_REG3_PPOD_MASK  0x01
 
@@ -66,6 +88,9 @@
 
 MMA8451Q::MMA8451Q(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr) 
 {
+    // set the I2C to fast mode
+    m_i2c.frequency(400000);
+
     // initialize parameters
     init();
 }
@@ -74,45 +99,70 @@
 void MMA8451Q::init()
 {    
     // reset all registers to power-on reset values
-    uint8_t d0[2] = { REG_CTRL_REG_2, 0x40 };
+    uint8_t d0[2] = { REG_CTRL_REG2, 0x40 };
     writeRegs(d0,2 );
     
     // wait for the reset bit to clear
     do {
-        readRegs(REG_CTRL_REG_2, d0, 1);
+        readRegs(REG_CTRL_REG2, d0, 1);
     } while ((d0[0] & 0x40) != 0);
     
     // go to standby mode
     standby();
     
+    // turn off FIFO mode - this is required before changing the F_READ bit
+    readRegs(REG_F_SETUP, d0, 1);
+    uint8_t d0a[2] = { REG_F_SETUP, 0 };
+    writeRegs(d0a, 2);
+    
     // read the curent config register
     uint8_t d1[1];
     readRegs(XYZ_DATA_CFG_REG, d1, 1);
     
-    // set 2g mode
+    // set 2g mode by default
     uint8_t d2[2] = { XYZ_DATA_CFG_REG, (d1[0] & ~FS_MASK) | FS_2G };
     writeRegs(d2, 2);
     
     // read the ctl2 register
     uint8_t d3[1];
-    readRegs(REG_CTRL_REG_2, d3, 1);
+    readRegs(REG_CTRL_REG2, d3, 1);
     
     // set the high resolution mode
-    uint8_t d4[2] = {REG_CTRL_REG_2, (d3[0] & ~MODS_MASK) | MODS1_MASK};
+    uint8_t d4[2] = {REG_CTRL_REG2, (d3[0] & ~MODS_MASK) | MODS_HI_RES};
     writeRegs(d4, 2);
     
-    // set 800 Hz mode
+    // set 800 Hz mode, 14-bit data (clear the F_READ bit)
     uint8_t d5[1];
-    readRegs(REG_CTRL_REG_1, d5, 1);
-    uint8_t d6[2] = {REG_CTRL_REG_1, (d5[0] & ~DR_MASK) | DR_800_HZ};
+    readRegs(REG_CTRL_REG1, d5, 1);
+    uint8_t d6[2] = {REG_CTRL_REG1, (d5[0] & ~(DR_MASK | F_READ_MASK)) | DR_800_HZ};
     writeRegs(d6, 2);
     
+    // set circular FIFO mode
+    uint8_t d7[1];
+    readRegs(REG_F_SETUP, d7, 1);
+    uint8_t d8[2] = {REG_F_SETUP, (d7[0] & ~F_MODE_MASK) | F_MODE_CIRC};
+    writeRegs(d8, 2);
+
     // enter active mode
     active();
 }
 
 MMA8451Q::~MMA8451Q() { }
 
+bool MMA8451Q::sampleReady()
+{
+    uint8_t d[1];
+    readRegs(REG_F_STATUS, d, 1);
+    return (d[0] & F_STATUS_XYZDR_MASK) == F_STATUS_XYZDR_MASK;
+}
+
+int MMA8451Q::getFIFOCount()
+{
+    uint8_t d[1];
+    readRegs(REG_F_STATUS, d, 1);
+    return d[0] & F_STATUS_CNT_MASK;
+}
+
 void MMA8451Q::setInterruptMode(int pin)
 {
     // go to standby mode
@@ -120,24 +170,24 @@
 
     // set IRQ push/pull and active high
     uint8_t d1[1];
-    readRegs(REG_CTRL_REG_3, d1, 1);
+    readRegs(REG_CTRL_REG3, d1, 1);
     uint8_t d2[2] = {
-        REG_CTRL_REG_3, 
+        REG_CTRL_REG3, 
         (d1[0] & ~CTRL_REG3_PPOD_MASK) | CTRL_REG3_IPOL_MASK
     };
     writeRegs(d2, 2);
     
     // set pin 2 or pin 1
-    readRegs(REG_CTRL_REG_5, d1, 1);
+    readRegs(REG_CTRL_REG5, d1, 1);
     uint8_t d3[2] = { 
-        REG_CTRL_REG_5, 
+        REG_CTRL_REG5, 
         (d1[0] & ~INT_CFG_DRDY) | (pin == 1 ? INT_CFG_DRDY : 0)
     };
     writeRegs(d3, 2);
     
     // enable data ready interrupt
-    readRegs(REG_CTRL_REG_4, d1, 1);
-    uint8_t d4[2] = { REG_CTRL_REG_4, d1[0] | INT_EN_DRDY };
+    readRegs(REG_CTRL_REG4, d1, 1);
+    uint8_t d4[2] = { REG_CTRL_REG4, d1[0] | INT_EN_DRDY };
     writeRegs(d4, 2);
     
     // enter active mode
@@ -150,26 +200,46 @@
     standby();
     
     // clear the interrupt register
-    uint8_t d1[2] = { REG_CTRL_REG_4, 0 };
+    uint8_t d1[2] = { REG_CTRL_REG4, 0 };
     writeRegs(d1, 2);
 
     // enter active mode
     active();
 }
 
+void MMA8451Q::setRange(int g)
+{
+    // go to standby mode
+    standby();
+    
+    // read the curent config register
+    uint8_t d1[1];
+    readRegs(XYZ_DATA_CFG_REG, d1, 1);
+    
+    // figure the mode flag for the desired G setting
+    uint8_t mode = (g == 8 ? FS_8G : g == 4 ? FS_4G : FS_2G);
+    
+    // set new mode
+    uint8_t d2[2] = { XYZ_DATA_CFG_REG, (d1[0] & ~FS_MASK) | mode };
+    writeRegs(d2, 2);
+    
+    // enter active mode
+    active();
+}
+
 void MMA8451Q::standby()
 {
     // read the current control register
     uint8_t d1[1];
-    readRegs(REG_CTRL_REG_1, d1, 1);
+    readRegs(REG_CTRL_REG1, d1, 1);
     
     // wait for standby mode
     do {
         // write it back with the Active bit cleared
-        uint8_t d2[2] = { REG_CTRL_REG_1, d1[0] & ~CTL_ACTIVE };
+        uint8_t d2[2] = { REG_CTRL_REG1, d1[0] & ~CTL_ACTIVE };
         writeRegs(d2, 2);
     
-        readRegs(REG_CTRL_REG_1, d1, 1);
+        readRegs(REG_CTRL_REG1, d1, 1);
     } while (d1[0] & CTL_ACTIVE);
 }
 
@@ -177,10 +247,10 @@
 {
     // read the current control register
     uint8_t d1[1];
-    readRegs(REG_CTRL_REG_1, d1, 1);
+    readRegs(REG_CTRL_REG1, d1, 1);
     
     // write it back out with the Active bit set
-    uint8_t d2[2] = { REG_CTRL_REG_1, d1[0] | CTL_ACTIVE };
+    uint8_t d2[2] = { REG_CTRL_REG1, d1[0] | CTL_ACTIVE };
     writeRegs(d2, 2);
 }
 
@@ -228,6 +298,18 @@
     z = int16_t(acc)/(4*4096.0);
 }
 
+void MMA8451Q::getAccXYZ(int &x, int &y, int &z)
+{    
+    // read the X, Y, and Z output registers
+    uint8_t res[6];
+    readRegs(REG_OUT_X_MSB, res, 6);
+    
+    // translate the register values
+    x = xlat14(&res[0]);
+    y = xlat14(&res[2]);
+    z = xlat14(&res[4]);
+}
+
 float MMA8451Q::getAccY() {
     return (float(getAccAxis(REG_OUT_Y_MSB))/4096.0);
 }