Reimplemented FXAS21000 library for Freescale Gyro

Fork of FXAS21000 by Jim Carver

Files at this revision

API Documentation at this revision

Comitter:
Mashu
Date:
Wed Jul 08 13:34:46 2015 +0000
Parent:
3:a8f83b52f4df
Commit message:
Reimplemented FXAS21000 library based on FXOS8700Q and updated MotionSensor data types.

Changed in this revision

FXAS21000.cpp Show annotated file Show diff for this revision Revisions of this file
FXAS21000.h Show annotated file Show diff for this revision Revisions of this file
diff -r a8f83b52f4df -r 41bd7f360406 FXAS21000.cpp
--- a/FXAS21000.cpp	Mon Jun 02 17:36:38 2014 +0000
+++ b/FXAS21000.cpp	Wed Jul 08 13:34:46 2015 +0000
@@ -1,71 +1,185 @@
- #include "FXAS21000.h"
- 
-FXAS21000::FXAS21000(PinName sda, PinName scl) : _i2c(sda, scl) {
- 
-    begin();
-}
-              
-void FXAS21000::RegRead( char reg, char * d, int len)
+#include "FXAS21000.h"
+
+const uint16_t uint14_max = 0x3FFF;
+void static inline normalize_14bits(int16_t &x)
 {
-    char cmd[1];
-    cmd[0] = reg;
-char i2c_addr = FXAS21000_SLAVE_ADDR;
-_i2c.write( i2c_addr, cmd, 1, true);
-_i2c.read ( i2c_addr, d, len);
+    x = ((x) > (uint14_max/2)) ? (x - uint14_max) : (x);
 }
 
-void FXAS21000::begin(void)
+static int16_t dummy_int16_t = 0;
+static float dummy_float = 0.0f;
+
+FXAS21000::FXAS21000(I2C &i2c, uint8_t addr)
 {
-    char data[2];
-    // write 0000 1000 = 0x08 to gyro control register 1 to place FXAS21000 into
-    // standby
-    // [7-1] = 0000 000
-    // [0]: active=0
+    _i2c = &i2c;
+    _addr = addr;
+    // activate the peripheral
+    uint8_t data[2];
+    _i2c->frequency(400000);
+    
+    /*
+     * | ZR_COND | RST | ST | DR[2:0] | Active | Ready |
+     * |    0    |  0  | 0  |   010   |   0    |   0   |
+     * ZR_COND - Offset compensation calibration
+     * RST - Reset of the device
+     * DR - Sampling rate 50Hz (010)
+     * Active - Device is measuring
+     * Ready - Device is ready to measure but not taking samples
+     */
     data[0] = FXAS21000_CTRL_REG1;
-    data[1] = 0x08;
-    _i2c.write( FXAS21000_SLAVE_ADDR, data, 2);
+    data[1] = 0x08; // 00001000
+    writeRegs(data, 2);
     
-    // write 0001 1011 to CRTL_REG0 register
+    /*
+     * CTRL_REG0 can be only modified in Standby or Read modes
+     * | 0 | 0 | SPIW | SEL[1:0] | HPF_EN | FS[1:0] |
+     * | 0 | 0 |  0   |    11    |   0    |    11   |
+     * SPIW - SPI bus mode, zero for four wires
+     * SEL - High pass filter frequency cut-off
+     * HPF_EN - Enable high-pass filter
+     * FS - Full scale ranges +-1600 dps when 00
+     */
     data[0] = FXAS21000_CTRL_REG0;
     data[1] = 0x1B;
-    _i2c.write( FXAS21000_SLAVE_ADDR, data, 2);
-
-    // write 0000 1001 to gyro control register 1
+    writeRegs(data, 2);
+    
+    /*
+     * Same a first write but Active bit gets enabled
+     */
     data[0] = FXAS21000_CTRL_REG1;
     data[1] = 0x0A;
-    _i2c.write( FXAS21000_SLAVE_ADDR, data, 2);
+    writeRegs(data, 2);
+}
+
+FXAS21000::~FXAS21000()
+{
+    _i2c = 0;
+    _addr = 0;
+}
+
+void FXAS21000::readRegs(uint8_t addr, uint8_t *data, uint32_t len) const
+{
+    uint8_t t[1] = {addr};
+    _i2c->write(_addr, (char *)t, sizeof(t), true);
+    _i2c->read(_addr, (char *)data, len);
+}
+
+uint8_t FXAS21000::whoAmI() const
+{
+    uint8_t who_am_i = 0;
+    readRegs(FXAS21000_WHOAMI, &who_am_i, sizeof(who_am_i));
+    return who_am_i;
+}
+
+void FXAS21000::writeRegs(uint8_t * data, uint32_t len) const
+{
+    _i2c->write(_addr, (char *)data, len);
 }
 
-char FXAS21000::getWhoAmI(void)
+int16_t FXAS21000::getSensorAxis(uint8_t addr) const
+{
+    uint8_t res[2];
+    readRegs(addr, res, sizeof(res));
+    return static_cast<int16_t>((res[0] << 8) | res[1]);
+}
+
+void FXAS21000::enable(void) const
+{
+    uint8_t data[2];
+    readRegs(FXAS21000_CTRL_REG1, &data[1], 1);
+    data[1] |= 0x0A; // 00000010 to turn on Active bit
+    data[0] = FXAS21000_CTRL_REG1;
+    writeRegs(data, sizeof(data));
+}
+
+void FXAS21000::disable(void) const
 {
-    char d;
-    RegRead( FXAS21000_WHOAMI, &d, 1);
-    return(d);
+    uint8_t data[2];
+    readRegs(FXAS21000_CTRL_REG1, &data[1], 1);
+    data[1] &= 0xFD; // 11111101 to turn off Active bit
+    data[0] = FXAS21000_CTRL_REG1;
+    writeRegs(data, sizeof(data));
+}
+
+uint32_t FXAS21000::dataReady(void) const
+{
+    uint8_t stat = 0;
+    readRegs(FXAS21000_STATUS, &stat, 1);
+    stat &= 0x88; // 10001000 to zero out other bits
+    if(stat == 0x88) { // If 7th and 4th bit are positive then return 1
+        stat = 1;
+    } else {
+        stat = 0;    // Otherwise no data ready, return 0
+    }
+    return (uint32_t)stat;
 }
 
-void FXAS21000::ReadXYZ(float * a)
+// OK
+uint32_t FXAS21000::sampleRate(uint32_t frequency) const
 {
-    char d[7];
-    int16_t t[6];
+    return(50); // for now sample rate is fixed at 50Hz
+}
+
+int16_t FXAS21000Gyroscpe::getX(int16_t &x = dummy_int16_t) const
+{
+    x = getSensorAxis(FXAS21000_OUT_X_MSB) >> 2;
+    normalize_14bits(x);
+    return x;
+}
 
-    RegRead( FXAS21000_STATUS, d, 7);
-    t[0] = ((d[1] * 256) + ((unsigned short) d[2]));
-    t[1] = ((d[3] * 256) + ((unsigned short) d[4]));
-    t[2] = ((d[5] * 256) + ((unsigned short) d[6]));
-    //printf("%X\r\n", (int) d[0]);
+int16_t FXAS21000Gyroscpe::getY(int16_t &y = dummy_int16_t) const
+{
+    y = getSensorAxis(FXAS21000_OUT_Y_MSB) >> 2;
+    normalize_14bits(y);
+    return y;
+}
 
-    a[0] = (float) t[0] * 0.003125;
-    a[1] = (float) t[1] * 0.003125;
-    a[2] = (float) t[2] * 0.003125;
-  
+int16_t FXAS21000Gyroscpe::getZ(int16_t &z = dummy_int16_t) const
+{
+    z = getSensorAxis(FXAS21000_OUT_Z_MSB) >> 2;
+    normalize_14bits(z);
+    return z;
+}
+
+float FXAS21000Gyroscpe::getX(float &x = dummy_float) const
+{
+    int16_t val = getSensorAxis(FXAS21000_OUT_X_MSB) >> 2;
+    normalize_14bits(val);
+    x = val / 4096.0f;
+    return x;
 }
 
-void FXAS21000::ReadXYZraw(int16_t * t)
+float FXAS21000Gyroscpe::getY(float &y = dummy_float) const
 {
-    char d[7];
+    int16_t val = getSensorAxis(FXAS21000_OUT_Y_MSB) >> 2;
+    normalize_14bits(val);
+    y = val / 4096.0f;
+    return y;
+}
+
+float FXAS21000Gyroscpe::getZ(float &z = dummy_float) const
+{
+    int16_t val = getSensorAxis(FXAS21000_OUT_Z_MSB) >> 2;
+    normalize_14bits(val);
+    z = val / 4096.0f;
+    return z;
+}
 
-    RegRead( FXAS21000_STATUS, d, 7);
-    t[0] = ((d[1] * 256) + ((unsigned short) d[2]));
-    t[1] = ((d[3] * 256) + ((unsigned short) d[4]));
-    t[2] = ((d[5] * 256) + ((unsigned short) d[6]));
-}
\ No newline at end of file
+void FXAS21000Gyroscpe::getAxis(motion_data_counts_t &xyz) const
+{
+    xyz.x = getSensorAxis(FXAS21000_OUT_X_MSB) >> 2;
+    xyz.y = getSensorAxis(FXAS21000_OUT_Y_MSB) >> 2;
+    xyz.z = getSensorAxis(FXAS21000_OUT_Z_MSB) >> 2;
+    normalize_14bits(xyz.x);
+    normalize_14bits(xyz.y);
+    normalize_14bits(xyz.z);
+}
+
+void FXAS21000Gyroscpe::getAxis(motion_data_units_t &xyz) const
+{
+    motion_data_counts_t _xyz;
+    FXAS21000Gyroscpe::getAxis(_xyz);
+    xyz.x = _xyz.x / 4096.0f;
+    xyz.y = _xyz.y / 4096.0f;
+    xyz.z = _xyz.z / 4096.0f;
+}
diff -r a8f83b52f4df -r 41bd7f360406 FXAS21000.h
--- a/FXAS21000.h	Mon Jun 02 17:36:38 2014 +0000
+++ b/FXAS21000.h	Wed Jul 08 13:34:46 2015 +0000
@@ -20,65 +20,84 @@
 #define FXAS21000_H
 
 #include "mbed.h"
-
+#include "MotionSensor.h"
 
 /**
- * MMA8652 Slave Address
+ * FXAS21000 Slave Address
  */
 #define FXAS21000_SLAVE_ADDR 0x40
 
-// MMA8652 internal register addresses
+// FXAS21000 internal register addresses
 #define FXAS21000_STATUS 0x00
 #define FXAS21000_WHOAMI 0x0C
 #define FXAS21000_XYZ_DATA_CFG 0x0E
 #define FXAS21000_CTRL_REG0 0x0D
 #define FXAS21000_CTRL_REG1 0x13
 #define FXAS21000_WHOAMI_VAL 0xD1
+#define FXAS21000_OUT_X_MSB 0x01
+#define FXAS21000_OUT_Y_MSB 0x03
+#define FXAS21000_OUT_Z_MSB 0x05
 
 /**
- * FXAS21000 gyroscope on I2C
+ * FXAS21000 driver class
  */
-class FXAS21000
+class FXAS21000 : public MotionSensor
 {
 public:
-    /**
-     * FXAS21000 constructor
-     *
-     * @param sda SDA pin
-     * @param sdl SCL pin
+
+    /** Read a device register
+        @param addr The address to read from
+        @param data The data to read from it
+        @param len The amount of data to read from it
+        @return 0 if successful, negative number otherwise
      */
-    FXAS21000(PinName sda, PinName scl);
- 
-    /**
-     * Get the Gyro values as floating point degrees / second
-     *
-     * @param floating point array where the results will be placed
+    void readRegs(uint8_t addr, uint8_t *data, uint32_t len) const;
+
+    /** Read the ID from a whoAmI register
+        @return The device whoAmI register contents
      */
-    void ReadXYZ(float * a);
+    uint8_t whoAmI(void) const;
+
+    virtual void enable(void) const;
+    virtual void disable(void) const;
+    virtual uint32_t sampleRate(uint32_t frequency) const;
+    virtual uint32_t dataReady(void) const;
 
-    /**
-     * Get the Gyro values as signed 16 bit value
-     *
-     * @param int16_t point array where the results will be placed
+protected:
+    I2C *_i2c;
+    uint8_t _addr;
+    
+    /** FXAS21000 constructor
+        @param i2c a configured i2c object
+        @param addr addr of the I2C peripheral as wired
      */
-    void ReadXYZraw(int16_t * t);
-   
-    /**
-     * Get the value of the WHO_AM_I register
-     *
-     * @returns DEVICE_ID value == 0xD1
+    FXAS21000(I2C &i2c, uint8_t addr);
+
+    /** FXAS21000 deconstructor
      */
-    char getWhoAmI(void);
+    ~FXAS21000();
     
-private:
-    I2C _i2c;
+    void writeRegs(uint8_t *data, uint32_t len) const;
+    int16_t getSensorAxis(uint8_t addr) const;
+};
+
+/** FXAS21000Gyroscpe interface
+ */
+class FXAS21000Gyroscpe : public FXAS21000
+{
+public:
 
-    /**
-     * Set the device in active mode
-     */
-    void begin( void);
-    
-    void RegRead( char reg, char * d, int len);
+    FXAS21000Gyroscpe(I2C &i2c, uint8_t addr) : FXAS21000(i2c, addr) {}
+
+    virtual int16_t getX(int16_t &x) const;
+    virtual int16_t getY(int16_t &y) const;
+    virtual int16_t getZ(int16_t &z) const;
+    virtual float getX(float &x) const;
+    virtual float getY(float &y) const;
+    virtual float getZ(float &z) const;
+    virtual void getAxis(motion_data_counts_t &xyz) const;
+    virtual void getAxis(motion_data_units_t &xyz) const;
+
 };
 
 #endif