GSMA version

Fork of FXOS8700CQ by Thomas Murphy

Files at this revision

API Documentation at this revision

Comitter:
trm
Date:
Wed May 28 17:08:33 2014 +0000
Parent:
1:3ec7e2676e48
Child:
3:2ce85aa45d7d
Commit message:
Updates to correctness! Correctly fill accel/magn data structs. Access to accel sensor scale (2/4/8g). More comments and documentation. #define for many configuration register properties.

Changed in this revision

FXOS8700CQ.cpp Show annotated file Show diff for this revision Revisions of this file
FXOS8700CQ.h Show annotated file Show diff for this revision Revisions of this file
--- a/FXOS8700CQ.cpp	Wed May 28 13:40:59 2014 +0000
+++ b/FXOS8700CQ.cpp	Wed May 28 17:08:33 2014 +0000
@@ -11,29 +11,34 @@
     uint8_t data[6] = {0, 0, 0, 0, 0, 0}; // target device write address, single byte to write at address
 
     // TODO: verify WHOAMI?
-    
+
     // TODO: un-magic-number register configuration
 
     // Place peripheral in standby for configuration, resetting CTRL_REG1
     data[0] = FXOS8700CQ_CTRL_REG1;
-    // Keep data[1] as 0x00
+    data[1] = 0x00; // this will unset CTRL_REG1:active
     write_regs(data, 2);
 
     // Now that the device is in standby, configure registers
 
     // Setup for write-though for CTRL_REG series
     // Keep data[0] as FXOS8700CQ_CTRL_REG1
-    data[1] = 0x08; // 400 Hz single rate, 200 Hz hybrid mode
+    data[1] =
+        FXOS8700CQ_CTRL_REG1_ASLP_RATE2(1) | // 0b01 gives sleep rate of 12.5Hz
+        FXOS8700CQ_CTRL_REG1_DR3(1); // 0x001 gives ODR of 400Hz/200Hz hybrid
 
     // FXOS8700CQ_CTRL_REG2;
-    data[2] = 0x18; // set low power sleep sampling, no auto sleep, normal sampling
+    data[2] =
+        FXOS8700CQ_CTRL_REG2_SMODS2(3) | // 0b11 gives low power sleep oversampling mode
+        FXOS8700CQ_CTRL_REG2_MODS2(1); // 0b01 gives low noise, low power oversampling mode
 
     // No configuration changes from default 0x00 in CTRL_REG3
     // Interrupts will be active low
     data[3] = 0x00;
 
     // FXOS8700CQ_CTRL_REG4;
-    data[4] = 0x01; // enable data ready interrupt
+    data[4] =
+        FXOS8700CQ_CTRL_REG4_INT_EN_DRDY;
 
     // No configuration changes from default 0x00 in CTRL_REG5
     // Data ready interrupt will appear on INT2
@@ -42,24 +47,32 @@
     // Write to the 5 CTRL_REG registers
     write_regs(data, 6);
 
-    // No configuration changes from default 0x00 in XYZ_DATA_CFG
-    // No high pass filter and +/- 2g range for accelerometer
-    // Do not write any changes
+    // FXOS8700CQ_XYZ_DATA_CFG
+    data[0] = FXOS8700CQ_XYZ_DATA_CFG;
+    data[1] =
+        FXOS8700CQ_XYZ_DATA_CFG_FS2(1); // 0x01 gives 4g full range, 0.488mg/LSB
+    write_regs(data, 2);
 
     // Setup for write-through for M_CTRL_REG series
     data[0] = FXOS8700CQ_M_CTRL_REG1;
-    data[1] = 0x9F; // automatic calibration, maximum oversampling, hybrid sampling mode
+    data[1] =
+        FXOS8700CQ_M_CTRL_REG1_M_ACAL | // set automatic calibration
+        FXOS8700CQ_M_CTRL_REG1_MO_OS3(7) | // use maximum magnetic oversampling
+        FXOS8700CQ_M_CTRL_REG1_M_HMS2(3); // enable hybrid sampling (both sensors)
 
     // FXOS8700CQ_M_CTRL_REG2
-    data[2] = 0x20; // allow automatic read-through from accel to magn data at acc_z (0x05/0x06)
+    data[2] =
+        FXOS8700CQ_M_CTRL_REG2_HYB_AUTOINC_MODE;
 
     // FXOS8700CQ_M_CTRL_REG3
-    data[3] = 0x70; // use calibration data, sleep oversampling
+    data[3] =
+        FXOS8700CQ_M_CTRL_REG3_M_ASLP_OS3(7); // maximum sleep magnetic oversampling
 
     // Write to the 3 M_CTRL_REG registers
     write_regs(data, 4);
 
     // Peripheral is configured, but disabled
+    enabled = false;
 }
 
 // Destruct class
@@ -70,18 +83,22 @@
 {
     uint8_t data[2];
     read_regs( FXOS8700CQ_CTRL_REG1, &data[1], 1);
-    data[1] |= 0x01; // set bit 0, CTRL_REG1:active
+    data[1] |= FXOS8700CQ_CTRL_REG1_ACTIVE;
     data[0] = FXOS8700CQ_CTRL_REG1;
     write_regs(data, 2); // write back
+
+    enabled = true;
 }
 
 void FXOS8700CQ::disable(void)
 {
     uint8_t data[2];
     read_regs( FXOS8700CQ_CTRL_REG1, &data[1], 1);
-    data[1] &= 0xFE; // unset bit 0, CTRL_REG1:active
     data[0] = FXOS8700CQ_CTRL_REG1;
+    data[1] &= ~FXOS8700CQ_CTRL_REG1_ACTIVE;
     write_regs(data, 2); // write back
+
+    enabled = false;
 }
 
 
@@ -98,22 +115,55 @@
     return databyte;
 }
 
-void FXOS8700CQ::get_data(SRAWDATA *accel_data, SRAWDATA *magn_data)
+uint8_t FXOS8700CQ::get_data(SRAWDATA *accel_data, SRAWDATA *magn_data)
 {
-    read_regs(FXOS8700CQ_OUT_X_MSB, raw, FXOS8700CQ_READ_LEN); // WRONG, getting accel then magn
+    if(!enabled) {
+        return 1;
+    }
+
+    read_regs(FXOS8700CQ_M_OUT_X_MSB, raw, FXOS8700CQ_READ_LEN);
 
     // Pull out 16-bit, 2's complement magnetometer data
     magn_data->x = (raw[0] << 8) | raw[1];
     magn_data->y = (raw[2] << 8) | raw[3];
     magn_data->z = (raw[4] << 8) | raw[5];
 
-    // Below is wrong, using left-justified version
     // Pull out 14-bit, 2's complement, right-justified accelerometer data
     accel_data->x = (raw[6] << 8) | raw[7];
     accel_data->y = (raw[8] << 8) | raw[9];
     accel_data->z = (raw[10] << 8) | raw[11];
+
+    // Have to apply corrections to make the int16_t correct
+    if(accel_data->x > UINT14_MAX/2) {
+        accel_data->x -= UINT14_MAX;
+    }
+    if(accel_data->y > UINT14_MAX/2) {
+        accel_data->y -= UINT14_MAX;
+    }
+    if(accel_data->z > UINT14_MAX/2) {
+        accel_data->z -= UINT14_MAX;
+    }
+
+    return 0;
 }
 
+uint8_t FXOS8700CQ::get_accel_scale(void)
+{
+    uint8_t data = 0x00;
+    read_regs(FXOS8700CQ_XYZ_DATA_CFG, &data, 1);
+    data &= FXOS8700CQ_XYZ_DATA_CFG_FS2(3); // mask with 0b11
+
+    switch(data) {
+        case FXOS8700CQ_XYZ_DATA_CFG_FS2(0):
+            return 2;
+        case FXOS8700CQ_XYZ_DATA_CFG_FS2(1):
+            return 4;
+        case FXOS8700CQ_XYZ_DATA_CFG_FS2(2):
+            return 8;
+        default:
+            return 0;
+    }
+}
 
 // Private methods
 
--- a/FXOS8700CQ.h	Wed May 28 13:40:59 2014 +0000
+++ b/FXOS8700CQ.h	Wed May 28 17:08:33 2014 +0000
@@ -15,19 +15,82 @@
 #define FXOS8700CQ_STATUS 0x00
 #define FXOS8700CQ_OUT_X_MSB 0x01
 #define FXOS8700CQ_WHOAMI 0x0D
+#define FXOS8700CQ_M_OUT_X_MSB 0x33
+
 #define FXOS8700CQ_XYZ_DATA_CFG 0x0E
+
 #define FXOS8700CQ_CTRL_REG1 0x2A
 #define FXOS8700CQ_CTRL_REG2 0x2B
 #define FXOS8700CQ_CTRL_REG3 0x2C
 #define FXOS8700CQ_CTRL_REG4 0x2D
 #define FXOS8700CQ_CTRL_REG5 0x2E
 
-#define FXOS8700CQ_M_OUT_X_MSB 0x34
-
 #define FXOS8700CQ_M_CTRL_REG1 0x5B
 #define FXOS8700CQ_M_CTRL_REG2 0x5C
 #define FXOS8700CQ_M_CTRL_REG3 0x5D
 
+// FXOS8700CQ configuration macros, per register
+
+#define FXOS8700CQ_CTRL_REG1_ASLP_RATE2(x) (x << 6) // x is 2-bit
+#define FXOS8700CQ_CTRL_REG1_DR3(x) (x << 3) // x is 3-bit
+#define FXOS8700CQ_CTRL_REG1_LNOISE (1 << 2)
+#define FXOS8700CQ_CTRL_REG1_F_READ (1 << 1)
+#define FXOS8700CQ_CTRL_REG1_ACTIVE (1 << 0)
+
+#define FXOS8700CQ_CTRL_REG2_ST (1 << 7)
+#define FXOS8700CQ_CTRL_REG2_RST (1 << 6)
+#define FXOS8700CQ_CTRL_REG2_SMODS2(x) (x << 3) // x is 2-bit
+#define FXOS8700CQ_CTRL_REG2_SLPE (1 << 2)
+#define FXOS8700CQ_CTRL_REG2_MODS2(x) (x << 0) // x is 2-bit
+
+#define FXOS8700CQ_CTRL_REG3_FIFO_GATE (1 << 7)
+#define FXOS8700CQ_CTRL_REG3_WAKE_TRANS (1 << 6)
+#define FXOS8700CQ_CTRL_REG3_WAKE_LNDPRT (1 << 5)
+#define FXOS8700CQ_CTRL_REG3_WAKE_PULSE (1 << 4)
+#define FXOS8700CQ_CTRL_REG3_WAKE_FFMT (1 << 3)
+#define FXOS8700CQ_CTRL_REG3_WAKE_A_VECM (1 << 2)
+#define FXOS8700CQ_CTRL_REG3_IPOL (1 << 1)
+#define FXOS8700CQ_CTRL_REG3_PP_OD (1 << 0)
+
+#define FXOS8700CQ_CTRL_REG4_INT_EN_ASLP (1 << 7)
+#define FXOS8700CQ_CTRL_REG4_INT_EN_FIFO (1 << 6)
+#define FXOS8700CQ_CTRL_REG4_INT_EN_TRANS (1 << 5)
+#define FXOS8700CQ_CTRL_REG4_INT_EN_LNDPRT (1 << 4)
+#define FXOS8700CQ_CTRL_REG4_INT_EN_PULSE (1 << 3)
+#define FXOS8700CQ_CTRL_REG4_INT_EN_FFMT (1 << 2)
+#define FXOS8700CQ_CTRL_REG4_INT_EN_A_VECM (1 << 1)
+#define FXOS8700CQ_CTRL_REG4_INT_EN_DRDY (1 << 0)
+
+#define FXOS8700CQ_CTRL_REG5_INT_CFG_ASLP (1 << 7)
+#define FXOS8700CQ_CTRL_REG5_INT_CFG_FIFO (1 << 6)
+#define FXOS8700CQ_CTRL_REG5_INT_CFG_TRANS (1 << 5)
+#define FXOS8700CQ_CTRL_REG5_INT_CFG_LNDPRT (1 << 4)
+#define FXOS8700CQ_CTRL_REG5_INT_CFG_PULSE (1 << 3)
+#define FXOS8700CQ_CTRL_REG5_INT_CFG_FFMT (1 << 2)
+#define FXOS8700CQ_CTRL_REG5_INT_CFG_A_VECM (1 << 1)
+#define FXOS8700CQ_CTRL_REG5_INT_CFG_DRDY (1 << 0)
+
+#define FXOS8700CQ_XYZ_DATA_CFG_HPF_OUT (1 << 4)
+#define FXOS8700CQ_XYZ_DATA_CFG_FS2(x) (x << 0) // x is 2-bit
+
+#define FXOS8700CQ_M_CTRL_REG1_M_ACAL (1 << 7)
+#define FXOS8700CQ_M_CTRL_REG1_M_RST (1 << 6)
+#define FXOS8700CQ_M_CTRL_REG1_M_OST (1 << 5)
+#define FXOS8700CQ_M_CTRL_REG1_MO_OS3(x) (x << 2) // x is 3-bit
+#define FXOS8700CQ_M_CTRL_REG1_M_HMS2(x) (x << 0) // x is 2-bit
+
+#define FXOS8700CQ_M_CTRL_REG2_HYB_AUTOINC_MODE (1 << 5)
+#define FXOS8700CQ_M_CTRL_REG2_M_MAXMIN_DIS (1 << 4)
+#define FXOS8700CQ_M_CTRL_REG2_M_MAXMIN_DIS_THS (1 << 3)
+#define FXOS8700CQ_M_CTRL_REG2_M_MAXMIN_RST (1 << 2)
+#define FXOS8700CQ_M_CTRL_REG2_M_RST_CNT2(x) (x << 0) // x is 2-bit
+
+#define FXOS8700CQ_M_CTRL_REG3_M_RAW (1 << 7)
+#define FXOS8700CQ_M_CTRL_REG3_M_ASLP_OS3(x) (x << 4) // x is 3-bit
+#define FXOS8700CQ_M_CTRL_REG3_M_THS_XYZ_UPDATE (1 << 3)
+#define FXOS8700CQ_M_CTRL_REG3_M_ST_Z (1 << 2)
+#define FXOS8700CQ_M_CTRL_REG3_M_ST_XY2(x) (x << 0) // x is 2-bit
+
 // FXOS8700CQ WHOAMI production register value
 #define FXOS8700CQ_WHOAMI_VAL 0xC7
 
@@ -65,13 +128,12 @@
     * @param sdl SCL pin
     * @param addr address of the I2C peripheral in (7-bit << 1) form
     */
-
     FXOS8700CQ(PinName sda, PinName scl, int addr);
 
     /**
     * FXOS8700CQ destructor
     */
-    ~FXOS8700CQ();
+    ~FXOS8700CQ(void);
 
     void enable(void);
     void disable(void);
@@ -83,14 +145,23 @@
     *
     * @param accel_data destination XYZ accelerometer data struct
     * @param magn_data destination XYZ magnetometer data struct
+    * @return 0 on success, non-zero on failure
     */
-    void get_data(SRAWDATA *accel_data, SRAWDATA *magn_data);
+    uint8_t get_data(SRAWDATA *accel_data, SRAWDATA *magn_data);
+    
+    /**
+    * Retrieve the full-range scale value of the accelerometer
+    * 
+    * @return 2, 4, or 8, depending on part configuration; 0 on error
+    */
+    uint8_t get_accel_scale(void);
 
 
 
 private:
     I2C dev_i2c; // instance of the mbed I2C class
     uint8_t dev_addr; // Device I2C address, in (7-bit << 1) form
+    bool enabled;
 
     // I2C helper methods
     void read_regs(int reg_addr, uint8_t* data, int len);