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_Int_example 4_accelerometer 4_accelerometer shake_to_wake

Fork of FXOS8700CQ by Thomas Murphy

Committer:
maclobdell
Date:
Sun Jan 10 17:45:05 2016 +0000
Revision:
5:7bdb0d5e5287
Parent:
3:2ce85aa45d7d
added interrupt and motion detection support

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 3:2ce85aa45d7d 11 uint8_t data[6] = {0, 0, 0, 0, 0, 0}; // to write over I2C: device register, up to 5 bytes data
trm 0:cf6299acfe98 12
trm 0:cf6299acfe98 13 // TODO: verify WHOAMI?
trm 2:4c2f8a3549a9 14
trm 0:cf6299acfe98 15 // Place peripheral in standby for configuration, resetting CTRL_REG1
trm 0:cf6299acfe98 16 data[0] = FXOS8700CQ_CTRL_REG1;
trm 2:4c2f8a3549a9 17 data[1] = 0x00; // this will unset CTRL_REG1:active
trm 0:cf6299acfe98 18 write_regs(data, 2);
trm 0:cf6299acfe98 19
trm 3:2ce85aa45d7d 20 // Now that the device is in standby, configure registers at will
trm 0:cf6299acfe98 21
trm 0:cf6299acfe98 22 // Setup for write-though for CTRL_REG series
trm 0:cf6299acfe98 23 // Keep data[0] as FXOS8700CQ_CTRL_REG1
trm 2:4c2f8a3549a9 24 data[1] =
trm 2:4c2f8a3549a9 25 FXOS8700CQ_CTRL_REG1_ASLP_RATE2(1) | // 0b01 gives sleep rate of 12.5Hz
trm 2:4c2f8a3549a9 26 FXOS8700CQ_CTRL_REG1_DR3(1); // 0x001 gives ODR of 400Hz/200Hz hybrid
trm 0:cf6299acfe98 27
trm 0:cf6299acfe98 28 // FXOS8700CQ_CTRL_REG2;
trm 2:4c2f8a3549a9 29 data[2] =
trm 2:4c2f8a3549a9 30 FXOS8700CQ_CTRL_REG2_SMODS2(3) | // 0b11 gives low power sleep oversampling mode
trm 2:4c2f8a3549a9 31 FXOS8700CQ_CTRL_REG2_MODS2(1); // 0b01 gives low noise, low power oversampling mode
trm 0:cf6299acfe98 32
maclobdell 5:7bdb0d5e5287 33 //MPL - don't configure interrupts here.
maclobdell 5:7bdb0d5e5287 34 /*
trm 0:cf6299acfe98 35 // No configuration changes from default 0x00 in CTRL_REG3
trm 3:2ce85aa45d7d 36 // Interrupts will be active low, their outputs in push-pull mode
trm 0:cf6299acfe98 37 data[3] = 0x00;
trm 0:cf6299acfe98 38
maclobdell 5:7bdb0d5e5287 39
trm 0:cf6299acfe98 40 // FXOS8700CQ_CTRL_REG4;
maclobdell 5:7bdb0d5e5287 41 data[4] =
trm 3:2ce85aa45d7d 42 FXOS8700CQ_CTRL_REG4_INT_EN_DRDY; // Enable the Data-Ready interrupt
trm 0:cf6299acfe98 43
trm 0:cf6299acfe98 44 // No configuration changes from default 0x00 in CTRL_REG5
trm 3:2ce85aa45d7d 45 // Data-Ready interrupt will appear on INT2
trm 0:cf6299acfe98 46 data[5] = 0x00;
trm 0:cf6299acfe98 47
maclobdell 5:7bdb0d5e5287 48 // Write to the 4 CTRL_REG registers
maclobdell 5:7bdb0d5e5287 49
maclobdell 5:7bdb0d5e5287 50 write_regs(data, 6);
maclobdell 5:7bdb0d5e5287 51 */
maclobdell 5:7bdb0d5e5287 52 write_regs(data, 3);
trm 0:cf6299acfe98 53
trm 2:4c2f8a3549a9 54 // FXOS8700CQ_XYZ_DATA_CFG
trm 2:4c2f8a3549a9 55 data[0] = FXOS8700CQ_XYZ_DATA_CFG;
trm 2:4c2f8a3549a9 56 data[1] =
trm 2:4c2f8a3549a9 57 FXOS8700CQ_XYZ_DATA_CFG_FS2(1); // 0x01 gives 4g full range, 0.488mg/LSB
trm 2:4c2f8a3549a9 58 write_regs(data, 2);
trm 0:cf6299acfe98 59
trm 0:cf6299acfe98 60 // Setup for write-through for M_CTRL_REG series
trm 0:cf6299acfe98 61 data[0] = FXOS8700CQ_M_CTRL_REG1;
trm 2:4c2f8a3549a9 62 data[1] =
trm 2:4c2f8a3549a9 63 FXOS8700CQ_M_CTRL_REG1_M_ACAL | // set automatic calibration
trm 2:4c2f8a3549a9 64 FXOS8700CQ_M_CTRL_REG1_MO_OS3(7) | // use maximum magnetic oversampling
trm 2:4c2f8a3549a9 65 FXOS8700CQ_M_CTRL_REG1_M_HMS2(3); // enable hybrid sampling (both sensors)
trm 0:cf6299acfe98 66
trm 0:cf6299acfe98 67 // FXOS8700CQ_M_CTRL_REG2
trm 2:4c2f8a3549a9 68 data[2] =
trm 2:4c2f8a3549a9 69 FXOS8700CQ_M_CTRL_REG2_HYB_AUTOINC_MODE;
trm 0:cf6299acfe98 70
trm 0:cf6299acfe98 71 // FXOS8700CQ_M_CTRL_REG3
trm 2:4c2f8a3549a9 72 data[3] =
trm 2:4c2f8a3549a9 73 FXOS8700CQ_M_CTRL_REG3_M_ASLP_OS3(7); // maximum sleep magnetic oversampling
trm 0:cf6299acfe98 74
trm 0:cf6299acfe98 75 // Write to the 3 M_CTRL_REG registers
trm 0:cf6299acfe98 76 write_regs(data, 4);
trm 0:cf6299acfe98 77
maclobdell 5:7bdb0d5e5287 78
trm 0:cf6299acfe98 79 // Peripheral is configured, but disabled
trm 2:4c2f8a3549a9 80 enabled = false;
trm 0:cf6299acfe98 81 }
trm 0:cf6299acfe98 82
trm 0:cf6299acfe98 83 // Destruct class
trm 0:cf6299acfe98 84 FXOS8700CQ::~FXOS8700CQ(void) {}
trm 0:cf6299acfe98 85
trm 0:cf6299acfe98 86
trm 0:cf6299acfe98 87 void FXOS8700CQ::enable(void)
trm 0:cf6299acfe98 88 {
trm 0:cf6299acfe98 89 uint8_t data[2];
trm 0:cf6299acfe98 90 read_regs( FXOS8700CQ_CTRL_REG1, &data[1], 1);
trm 2:4c2f8a3549a9 91 data[1] |= FXOS8700CQ_CTRL_REG1_ACTIVE;
trm 0:cf6299acfe98 92 data[0] = FXOS8700CQ_CTRL_REG1;
trm 0:cf6299acfe98 93 write_regs(data, 2); // write back
trm 2:4c2f8a3549a9 94
trm 2:4c2f8a3549a9 95 enabled = true;
trm 0:cf6299acfe98 96 }
trm 0:cf6299acfe98 97
maclobdell 5:7bdb0d5e5287 98 //MPL
maclobdell 5:7bdb0d5e5287 99 uint8_t FXOS8700CQ::config_int( void)
maclobdell 5:7bdb0d5e5287 100 {
maclobdell 5:7bdb0d5e5287 101
maclobdell 5:7bdb0d5e5287 102 /*don't enable interrupts in constructor. Do that here. */
maclobdell 5:7bdb0d5e5287 103
maclobdell 5:7bdb0d5e5287 104 /* todo: pass in a structure and have this function enable the interrupts you want, set the pin you want them to come out on, and set whether active high or low */
maclobdell 5:7bdb0d5e5287 105
maclobdell 5:7bdb0d5e5287 106 uint8_t data[2];
maclobdell 5:7bdb0d5e5287 107
maclobdell 5:7bdb0d5e5287 108 //external interrupt signal is active low & push-pull by default (bit value 0).
maclobdell 5:7bdb0d5e5287 109 data[0] = FXOS8700CQ_CTRL_REG3;
maclobdell 5:7bdb0d5e5287 110 data[1] = 0x08; //enable freefall/motion detection interrupt to wake sensor from sleep mode
maclobdell 5:7bdb0d5e5287 111 write_regs(data, 2);
maclobdell 5:7bdb0d5e5287 112
maclobdell 5:7bdb0d5e5287 113 data[0] = FXOS8700CQ_CTRL_REG4;
maclobdell 5:7bdb0d5e5287 114 data[1] = 0x04; //enable freefall/motion detection interrupt
maclobdell 5:7bdb0d5e5287 115 write_regs(data, 2);
maclobdell 5:7bdb0d5e5287 116
maclobdell 5:7bdb0d5e5287 117 //by default it comes out on INT2
maclobdell 5:7bdb0d5e5287 118 //INT2 connected to PTD1 on FRDM-KL26Z
maclobdell 5:7bdb0d5e5287 119 data[0] = FXOS8700CQ_CTRL_REG5;
maclobdell 5:7bdb0d5e5287 120 data[1] = 0x00; //interrupts come out on INT2
maclobdell 5:7bdb0d5e5287 121 write_regs(data, 2);
maclobdell 5:7bdb0d5e5287 122
maclobdell 5:7bdb0d5e5287 123 //todo: what is the correct return value for okay?
maclobdell 5:7bdb0d5e5287 124 return 99;
maclobdell 5:7bdb0d5e5287 125 }
maclobdell 5:7bdb0d5e5287 126
maclobdell 5:7bdb0d5e5287 127 //MPL
maclobdell 5:7bdb0d5e5287 128 void FXOS8700CQ::clear_int( void)
maclobdell 5:7bdb0d5e5287 129 {
maclobdell 5:7bdb0d5e5287 130 /* todo: pass in a structure and have this function clear the interrupts you want */
maclobdell 5:7bdb0d5e5287 131
maclobdell 5:7bdb0d5e5287 132 //this is only for the freefall / motion detection
maclobdell 5:7bdb0d5e5287 133
maclobdell 5:7bdb0d5e5287 134 uint8_t data[2];
maclobdell 5:7bdb0d5e5287 135
maclobdell 5:7bdb0d5e5287 136 read_regs(FXOS8700CQ_INT_SOURCE, &data[1], 1); // need to clear this because we had selected to latch the interrupt
maclobdell 5:7bdb0d5e5287 137 //printf("INT_SOURCE = %x\n",data[1]);
maclobdell 5:7bdb0d5e5287 138
maclobdell 5:7bdb0d5e5287 139 read_regs(FXOS8700CQ_A_FFMT_SRC, &data[1], 1); //clear the motion interrupt because we enabled it
maclobdell 5:7bdb0d5e5287 140 //printf("A_FFMT_SRC = %x\n",data[1]);
maclobdell 5:7bdb0d5e5287 141
maclobdell 5:7bdb0d5e5287 142 }
maclobdell 5:7bdb0d5e5287 143
maclobdell 5:7bdb0d5e5287 144 //MPL
maclobdell 5:7bdb0d5e5287 145 uint8_t FXOS8700CQ::config_feature( void)
maclobdell 5:7bdb0d5e5287 146 {
maclobdell 5:7bdb0d5e5287 147 //dont enable specific features (tap detection, motion detection, etc) in constructor - do that here
maclobdell 5:7bdb0d5e5287 148 //todo: should this be in a separate function that allows users to select what capabilities to enable?
maclobdell 5:7bdb0d5e5287 149
maclobdell 5:7bdb0d5e5287 150 //MPL - enable motion detection
maclobdell 5:7bdb0d5e5287 151
maclobdell 5:7bdb0d5e5287 152 uint8_t data[2];
maclobdell 5:7bdb0d5e5287 153
maclobdell 5:7bdb0d5e5287 154 data[0] = FXOS8700CQ_A_FFMT_CFG;
maclobdell 5:7bdb0d5e5287 155 data[1] = 0x78; //(don't latch event in register.) bit6: 1 motion flag. bits5,4,3: 1 enable detection in all 3 accel axis
maclobdell 5:7bdb0d5e5287 156 write_regs(data, 2);
maclobdell 5:7bdb0d5e5287 157
maclobdell 5:7bdb0d5e5287 158 data[0] = FXOS8700CQ_A_FFMT_THS;
maclobdell 5:7bdb0d5e5287 159 data[1] = 0x07; //will this work?? //do I need to enable the debounce filter?
maclobdell 5:7bdb0d5e5287 160 write_regs(data, 2);
maclobdell 5:7bdb0d5e5287 161
maclobdell 5:7bdb0d5e5287 162 return 0; // not implemented return yet
maclobdell 5:7bdb0d5e5287 163
maclobdell 5:7bdb0d5e5287 164 }
trm 0:cf6299acfe98 165 void FXOS8700CQ::disable(void)
trm 0:cf6299acfe98 166 {
trm 0:cf6299acfe98 167 uint8_t data[2];
trm 0:cf6299acfe98 168 read_regs( FXOS8700CQ_CTRL_REG1, &data[1], 1);
trm 0:cf6299acfe98 169 data[0] = FXOS8700CQ_CTRL_REG1;
trm 2:4c2f8a3549a9 170 data[1] &= ~FXOS8700CQ_CTRL_REG1_ACTIVE;
trm 0:cf6299acfe98 171 write_regs(data, 2); // write back
trm 2:4c2f8a3549a9 172
trm 2:4c2f8a3549a9 173 enabled = false;
trm 0:cf6299acfe98 174 }
trm 0:cf6299acfe98 175
trm 0:cf6299acfe98 176
trm 0:cf6299acfe98 177 uint8_t FXOS8700CQ::status(void)
trm 0:cf6299acfe98 178 {
trm 0:cf6299acfe98 179 read_regs(FXOS8700CQ_STATUS, &status_reg, 1);
trm 0:cf6299acfe98 180 return status_reg;
trm 0:cf6299acfe98 181 }
trm 0:cf6299acfe98 182
trm 0:cf6299acfe98 183 uint8_t FXOS8700CQ::get_whoami(void)
trm 0:cf6299acfe98 184 {
trm 0:cf6299acfe98 185 uint8_t databyte = 0x00;
trm 0:cf6299acfe98 186 read_regs(FXOS8700CQ_WHOAMI, &databyte, 1);
trm 0:cf6299acfe98 187 return databyte;
trm 0:cf6299acfe98 188 }
trm 0:cf6299acfe98 189
trm 2:4c2f8a3549a9 190 uint8_t FXOS8700CQ::get_data(SRAWDATA *accel_data, SRAWDATA *magn_data)
trm 0:cf6299acfe98 191 {
trm 2:4c2f8a3549a9 192 if(!enabled) {
trm 2:4c2f8a3549a9 193 return 1;
trm 2:4c2f8a3549a9 194 }
trm 2:4c2f8a3549a9 195
trm 2:4c2f8a3549a9 196 read_regs(FXOS8700CQ_M_OUT_X_MSB, raw, FXOS8700CQ_READ_LEN);
trm 0:cf6299acfe98 197
trm 0:cf6299acfe98 198 // Pull out 16-bit, 2's complement magnetometer data
trm 0:cf6299acfe98 199 magn_data->x = (raw[0] << 8) | raw[1];
trm 0:cf6299acfe98 200 magn_data->y = (raw[2] << 8) | raw[3];
trm 0:cf6299acfe98 201 magn_data->z = (raw[4] << 8) | raw[5];
trm 0:cf6299acfe98 202
trm 0:cf6299acfe98 203 // Pull out 14-bit, 2's complement, right-justified accelerometer data
trm 0:cf6299acfe98 204 accel_data->x = (raw[6] << 8) | raw[7];
trm 0:cf6299acfe98 205 accel_data->y = (raw[8] << 8) | raw[9];
trm 0:cf6299acfe98 206 accel_data->z = (raw[10] << 8) | raw[11];
trm 2:4c2f8a3549a9 207
trm 2:4c2f8a3549a9 208 // Have to apply corrections to make the int16_t correct
trm 2:4c2f8a3549a9 209 if(accel_data->x > UINT14_MAX/2) {
trm 2:4c2f8a3549a9 210 accel_data->x -= UINT14_MAX;
trm 2:4c2f8a3549a9 211 }
trm 2:4c2f8a3549a9 212 if(accel_data->y > UINT14_MAX/2) {
trm 2:4c2f8a3549a9 213 accel_data->y -= UINT14_MAX;
trm 2:4c2f8a3549a9 214 }
trm 2:4c2f8a3549a9 215 if(accel_data->z > UINT14_MAX/2) {
trm 2:4c2f8a3549a9 216 accel_data->z -= UINT14_MAX;
trm 2:4c2f8a3549a9 217 }
trm 2:4c2f8a3549a9 218
trm 2:4c2f8a3549a9 219 return 0;
trm 0:cf6299acfe98 220 }
trm 0:cf6299acfe98 221
trm 2:4c2f8a3549a9 222 uint8_t FXOS8700CQ::get_accel_scale(void)
trm 2:4c2f8a3549a9 223 {
trm 2:4c2f8a3549a9 224 uint8_t data = 0x00;
trm 2:4c2f8a3549a9 225 read_regs(FXOS8700CQ_XYZ_DATA_CFG, &data, 1);
trm 2:4c2f8a3549a9 226 data &= FXOS8700CQ_XYZ_DATA_CFG_FS2(3); // mask with 0b11
trm 2:4c2f8a3549a9 227
trm 3:2ce85aa45d7d 228 // Choose output value based on masked data
trm 2:4c2f8a3549a9 229 switch(data) {
trm 2:4c2f8a3549a9 230 case FXOS8700CQ_XYZ_DATA_CFG_FS2(0):
trm 2:4c2f8a3549a9 231 return 2;
trm 2:4c2f8a3549a9 232 case FXOS8700CQ_XYZ_DATA_CFG_FS2(1):
trm 2:4c2f8a3549a9 233 return 4;
trm 2:4c2f8a3549a9 234 case FXOS8700CQ_XYZ_DATA_CFG_FS2(2):
trm 2:4c2f8a3549a9 235 return 8;
trm 2:4c2f8a3549a9 236 default:
trm 2:4c2f8a3549a9 237 return 0;
trm 2:4c2f8a3549a9 238 }
trm 2:4c2f8a3549a9 239 }
trm 0:cf6299acfe98 240
trm 0:cf6299acfe98 241 // Private methods
trm 0:cf6299acfe98 242
trm 3:2ce85aa45d7d 243 // Excepting the call to dev_i2c.frequency() in the constructor,
trm 3:2ce85aa45d7d 244 // the use of the mbed I2C class is restricted to these methods
trm 0:cf6299acfe98 245 void FXOS8700CQ::read_regs(int reg_addr, uint8_t* data, int len)
trm 0:cf6299acfe98 246 {
trm 0:cf6299acfe98 247 char t[1] = {reg_addr};
trm 0:cf6299acfe98 248 dev_i2c.write(dev_addr, t, 1, true);
trm 0:cf6299acfe98 249 dev_i2c.read(dev_addr, (char *)data, len);
trm 0:cf6299acfe98 250 }
trm 0:cf6299acfe98 251
trm 0:cf6299acfe98 252 void FXOS8700CQ::write_regs(uint8_t* data, int len)
trm 0:cf6299acfe98 253 {
trm 0:cf6299acfe98 254 dev_i2c.write(dev_addr, (char*)data, len);
trm 0:cf6299acfe98 255 }