An in-development library to provide effective access to all features of the FXOS8700CQ on the FRDM-K64F mbed-enabled development board. As of 28 May 2014 1325EDT, the code should be generally usable and modifiable.

Dependents:   fxos8700cq_example frdm_fxos8700_logger AVC_test1 frdm_accel ... more

A basic implementation of accessing the FXOS8700CQ. This should be useable, but as the Apache License says, don't expect it to be good at doing anything, even what it's supposed to do.

Committer:
trm
Date:
Wed May 28 17:08:33 2014 +0000
Revision:
2:4c2f8a3549a9
Parent:
0:cf6299acfe98
Child:
3:2ce85aa45d7d
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.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
trm 0:cf6299acfe98 1 #include "FXOS8700CQ.h"
trm 0:cf6299acfe98 2
trm 0:cf6299acfe98 3 uint8_t status_reg; // Status register contents
trm 0:cf6299acfe98 4 uint8_t raw[FXOS8700CQ_READ_LEN]; // Buffer for reading out stored data
trm 0:cf6299acfe98 5
trm 0:cf6299acfe98 6 // Construct class and its contents
trm 0:cf6299acfe98 7 FXOS8700CQ::FXOS8700CQ(PinName sda, PinName scl, int addr) : dev_i2c(sda, scl), dev_addr(addr)
trm 0:cf6299acfe98 8 {
trm 0:cf6299acfe98 9 // Initialization of the FXOS8700CQ
trm 0:cf6299acfe98 10 dev_i2c.frequency(I2C_400K); // Use maximum I2C frequency
trm 0:cf6299acfe98 11 uint8_t data[6] = {0, 0, 0, 0, 0, 0}; // target device write address, single byte to write at address
trm 0:cf6299acfe98 12
trm 0:cf6299acfe98 13 // TODO: verify WHOAMI?
trm 2:4c2f8a3549a9 14
trm 0:cf6299acfe98 15 // TODO: un-magic-number register configuration
trm 0:cf6299acfe98 16
trm 0:cf6299acfe98 17 // Place peripheral in standby for configuration, resetting CTRL_REG1
trm 0:cf6299acfe98 18 data[0] = FXOS8700CQ_CTRL_REG1;
trm 2:4c2f8a3549a9 19 data[1] = 0x00; // this will unset CTRL_REG1:active
trm 0:cf6299acfe98 20 write_regs(data, 2);
trm 0:cf6299acfe98 21
trm 0:cf6299acfe98 22 // Now that the device is in standby, configure registers
trm 0:cf6299acfe98 23
trm 0:cf6299acfe98 24 // Setup for write-though for CTRL_REG series
trm 0:cf6299acfe98 25 // Keep data[0] as FXOS8700CQ_CTRL_REG1
trm 2:4c2f8a3549a9 26 data[1] =
trm 2:4c2f8a3549a9 27 FXOS8700CQ_CTRL_REG1_ASLP_RATE2(1) | // 0b01 gives sleep rate of 12.5Hz
trm 2:4c2f8a3549a9 28 FXOS8700CQ_CTRL_REG1_DR3(1); // 0x001 gives ODR of 400Hz/200Hz hybrid
trm 0:cf6299acfe98 29
trm 0:cf6299acfe98 30 // FXOS8700CQ_CTRL_REG2;
trm 2:4c2f8a3549a9 31 data[2] =
trm 2:4c2f8a3549a9 32 FXOS8700CQ_CTRL_REG2_SMODS2(3) | // 0b11 gives low power sleep oversampling mode
trm 2:4c2f8a3549a9 33 FXOS8700CQ_CTRL_REG2_MODS2(1); // 0b01 gives low noise, low power oversampling mode
trm 0:cf6299acfe98 34
trm 0:cf6299acfe98 35 // No configuration changes from default 0x00 in CTRL_REG3
trm 0:cf6299acfe98 36 // Interrupts will be active low
trm 0:cf6299acfe98 37 data[3] = 0x00;
trm 0:cf6299acfe98 38
trm 0:cf6299acfe98 39 // FXOS8700CQ_CTRL_REG4;
trm 2:4c2f8a3549a9 40 data[4] =
trm 2:4c2f8a3549a9 41 FXOS8700CQ_CTRL_REG4_INT_EN_DRDY;
trm 0:cf6299acfe98 42
trm 0:cf6299acfe98 43 // No configuration changes from default 0x00 in CTRL_REG5
trm 0:cf6299acfe98 44 // Data ready interrupt will appear on INT2
trm 0:cf6299acfe98 45 data[5] = 0x00;
trm 0:cf6299acfe98 46
trm 0:cf6299acfe98 47 // Write to the 5 CTRL_REG registers
trm 0:cf6299acfe98 48 write_regs(data, 6);
trm 0:cf6299acfe98 49
trm 2:4c2f8a3549a9 50 // FXOS8700CQ_XYZ_DATA_CFG
trm 2:4c2f8a3549a9 51 data[0] = FXOS8700CQ_XYZ_DATA_CFG;
trm 2:4c2f8a3549a9 52 data[1] =
trm 2:4c2f8a3549a9 53 FXOS8700CQ_XYZ_DATA_CFG_FS2(1); // 0x01 gives 4g full range, 0.488mg/LSB
trm 2:4c2f8a3549a9 54 write_regs(data, 2);
trm 0:cf6299acfe98 55
trm 0:cf6299acfe98 56 // Setup for write-through for M_CTRL_REG series
trm 0:cf6299acfe98 57 data[0] = FXOS8700CQ_M_CTRL_REG1;
trm 2:4c2f8a3549a9 58 data[1] =
trm 2:4c2f8a3549a9 59 FXOS8700CQ_M_CTRL_REG1_M_ACAL | // set automatic calibration
trm 2:4c2f8a3549a9 60 FXOS8700CQ_M_CTRL_REG1_MO_OS3(7) | // use maximum magnetic oversampling
trm 2:4c2f8a3549a9 61 FXOS8700CQ_M_CTRL_REG1_M_HMS2(3); // enable hybrid sampling (both sensors)
trm 0:cf6299acfe98 62
trm 0:cf6299acfe98 63 // FXOS8700CQ_M_CTRL_REG2
trm 2:4c2f8a3549a9 64 data[2] =
trm 2:4c2f8a3549a9 65 FXOS8700CQ_M_CTRL_REG2_HYB_AUTOINC_MODE;
trm 0:cf6299acfe98 66
trm 0:cf6299acfe98 67 // FXOS8700CQ_M_CTRL_REG3
trm 2:4c2f8a3549a9 68 data[3] =
trm 2:4c2f8a3549a9 69 FXOS8700CQ_M_CTRL_REG3_M_ASLP_OS3(7); // maximum sleep magnetic oversampling
trm 0:cf6299acfe98 70
trm 0:cf6299acfe98 71 // Write to the 3 M_CTRL_REG registers
trm 0:cf6299acfe98 72 write_regs(data, 4);
trm 0:cf6299acfe98 73
trm 0:cf6299acfe98 74 // Peripheral is configured, but disabled
trm 2:4c2f8a3549a9 75 enabled = false;
trm 0:cf6299acfe98 76 }
trm 0:cf6299acfe98 77
trm 0:cf6299acfe98 78 // Destruct class
trm 0:cf6299acfe98 79 FXOS8700CQ::~FXOS8700CQ(void) {}
trm 0:cf6299acfe98 80
trm 0:cf6299acfe98 81
trm 0:cf6299acfe98 82 void FXOS8700CQ::enable(void)
trm 0:cf6299acfe98 83 {
trm 0:cf6299acfe98 84 uint8_t data[2];
trm 0:cf6299acfe98 85 read_regs( FXOS8700CQ_CTRL_REG1, &data[1], 1);
trm 2:4c2f8a3549a9 86 data[1] |= FXOS8700CQ_CTRL_REG1_ACTIVE;
trm 0:cf6299acfe98 87 data[0] = FXOS8700CQ_CTRL_REG1;
trm 0:cf6299acfe98 88 write_regs(data, 2); // write back
trm 2:4c2f8a3549a9 89
trm 2:4c2f8a3549a9 90 enabled = true;
trm 0:cf6299acfe98 91 }
trm 0:cf6299acfe98 92
trm 0:cf6299acfe98 93 void FXOS8700CQ::disable(void)
trm 0:cf6299acfe98 94 {
trm 0:cf6299acfe98 95 uint8_t data[2];
trm 0:cf6299acfe98 96 read_regs( FXOS8700CQ_CTRL_REG1, &data[1], 1);
trm 0:cf6299acfe98 97 data[0] = FXOS8700CQ_CTRL_REG1;
trm 2:4c2f8a3549a9 98 data[1] &= ~FXOS8700CQ_CTRL_REG1_ACTIVE;
trm 0:cf6299acfe98 99 write_regs(data, 2); // write back
trm 2:4c2f8a3549a9 100
trm 2:4c2f8a3549a9 101 enabled = false;
trm 0:cf6299acfe98 102 }
trm 0:cf6299acfe98 103
trm 0:cf6299acfe98 104
trm 0:cf6299acfe98 105 uint8_t FXOS8700CQ::status(void)
trm 0:cf6299acfe98 106 {
trm 0:cf6299acfe98 107 read_regs(FXOS8700CQ_STATUS, &status_reg, 1);
trm 0:cf6299acfe98 108 return status_reg;
trm 0:cf6299acfe98 109 }
trm 0:cf6299acfe98 110
trm 0:cf6299acfe98 111 uint8_t FXOS8700CQ::get_whoami(void)
trm 0:cf6299acfe98 112 {
trm 0:cf6299acfe98 113 uint8_t databyte = 0x00;
trm 0:cf6299acfe98 114 read_regs(FXOS8700CQ_WHOAMI, &databyte, 1);
trm 0:cf6299acfe98 115 return databyte;
trm 0:cf6299acfe98 116 }
trm 0:cf6299acfe98 117
trm 2:4c2f8a3549a9 118 uint8_t FXOS8700CQ::get_data(SRAWDATA *accel_data, SRAWDATA *magn_data)
trm 0:cf6299acfe98 119 {
trm 2:4c2f8a3549a9 120 if(!enabled) {
trm 2:4c2f8a3549a9 121 return 1;
trm 2:4c2f8a3549a9 122 }
trm 2:4c2f8a3549a9 123
trm 2:4c2f8a3549a9 124 read_regs(FXOS8700CQ_M_OUT_X_MSB, raw, FXOS8700CQ_READ_LEN);
trm 0:cf6299acfe98 125
trm 0:cf6299acfe98 126 // Pull out 16-bit, 2's complement magnetometer data
trm 0:cf6299acfe98 127 magn_data->x = (raw[0] << 8) | raw[1];
trm 0:cf6299acfe98 128 magn_data->y = (raw[2] << 8) | raw[3];
trm 0:cf6299acfe98 129 magn_data->z = (raw[4] << 8) | raw[5];
trm 0:cf6299acfe98 130
trm 0:cf6299acfe98 131 // Pull out 14-bit, 2's complement, right-justified accelerometer data
trm 0:cf6299acfe98 132 accel_data->x = (raw[6] << 8) | raw[7];
trm 0:cf6299acfe98 133 accel_data->y = (raw[8] << 8) | raw[9];
trm 0:cf6299acfe98 134 accel_data->z = (raw[10] << 8) | raw[11];
trm 2:4c2f8a3549a9 135
trm 2:4c2f8a3549a9 136 // Have to apply corrections to make the int16_t correct
trm 2:4c2f8a3549a9 137 if(accel_data->x > UINT14_MAX/2) {
trm 2:4c2f8a3549a9 138 accel_data->x -= UINT14_MAX;
trm 2:4c2f8a3549a9 139 }
trm 2:4c2f8a3549a9 140 if(accel_data->y > UINT14_MAX/2) {
trm 2:4c2f8a3549a9 141 accel_data->y -= UINT14_MAX;
trm 2:4c2f8a3549a9 142 }
trm 2:4c2f8a3549a9 143 if(accel_data->z > UINT14_MAX/2) {
trm 2:4c2f8a3549a9 144 accel_data->z -= UINT14_MAX;
trm 2:4c2f8a3549a9 145 }
trm 2:4c2f8a3549a9 146
trm 2:4c2f8a3549a9 147 return 0;
trm 0:cf6299acfe98 148 }
trm 0:cf6299acfe98 149
trm 2:4c2f8a3549a9 150 uint8_t FXOS8700CQ::get_accel_scale(void)
trm 2:4c2f8a3549a9 151 {
trm 2:4c2f8a3549a9 152 uint8_t data = 0x00;
trm 2:4c2f8a3549a9 153 read_regs(FXOS8700CQ_XYZ_DATA_CFG, &data, 1);
trm 2:4c2f8a3549a9 154 data &= FXOS8700CQ_XYZ_DATA_CFG_FS2(3); // mask with 0b11
trm 2:4c2f8a3549a9 155
trm 2:4c2f8a3549a9 156 switch(data) {
trm 2:4c2f8a3549a9 157 case FXOS8700CQ_XYZ_DATA_CFG_FS2(0):
trm 2:4c2f8a3549a9 158 return 2;
trm 2:4c2f8a3549a9 159 case FXOS8700CQ_XYZ_DATA_CFG_FS2(1):
trm 2:4c2f8a3549a9 160 return 4;
trm 2:4c2f8a3549a9 161 case FXOS8700CQ_XYZ_DATA_CFG_FS2(2):
trm 2:4c2f8a3549a9 162 return 8;
trm 2:4c2f8a3549a9 163 default:
trm 2:4c2f8a3549a9 164 return 0;
trm 2:4c2f8a3549a9 165 }
trm 2:4c2f8a3549a9 166 }
trm 0:cf6299acfe98 167
trm 0:cf6299acfe98 168 // Private methods
trm 0:cf6299acfe98 169
trm 0:cf6299acfe98 170 void FXOS8700CQ::read_regs(int reg_addr, uint8_t* data, int len)
trm 0:cf6299acfe98 171 {
trm 0:cf6299acfe98 172 char t[1] = {reg_addr};
trm 0:cf6299acfe98 173 dev_i2c.write(dev_addr, t, 1, true);
trm 0:cf6299acfe98 174 dev_i2c.read(dev_addr, (char *)data, len);
trm 0:cf6299acfe98 175 }
trm 0:cf6299acfe98 176
trm 0:cf6299acfe98 177 void FXOS8700CQ::write_regs(uint8_t* data, int len)
trm 0:cf6299acfe98 178 {
trm 0:cf6299acfe98 179 dev_i2c.write(dev_addr, (char*)data, len);
trm 0:cf6299acfe98 180 }