Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
Diff: MMA8451Q/MMA8451Q.cpp
- 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); }