A compilation of some hardware sensors and their shared programming interfaces.
MMA8451Q.cpp
- Committer:
- mgottscho
- Date:
- 2014-03-16
- Revision:
- 0:8d34cc2ff388
File content as of revision 0:8d34cc2ff388:
/* MMA8451Q.cpp * Tested with mbed board: FRDM-KL46Z * Author: Mark Gottscho * mgottscho@ucla.edu */ #include "mbed.h" #include "I2CSensor.h" #include "PeriodicSensor.h" #include "SleepableSensor.h" #include "MMA8451Q.h" using namespace std; //////////////////// PUBLIC METHODS //////////////////// MMA8451Q::MMA8451Q(PinName sda, PinName scl, int i2c_addr) : I2CSensor(sda, scl, i2c_addr), //parent constructor PeriodicSensor(0.05), //default max sampling rate of 20Hz SleepableSensor(), __x(0), __y(0), __z(0), __active(false), __14b_data_enabled(true), __output_data_rate(MMA8451Q::smpl_rate_t(0)), __scale(MMA8451Q::scale_t(0)), __div(G2_DIV) { } MMA8451Q::~MMA8451Q() {} void MMA8451Q::selfInit() { __i2c.frequency(400000); reset(); setOutputDataRate(HZ800); setScale(G2); set14bData(true); //enableDataReadyInterrupt(true, true); //INT1 } void MMA8451Q::reset() { uint8_t data = CTRL_REG2_RST_MASK; setRegister(CTRL_REG2, data); wait(0.1); } uint8_t MMA8451Q::whoAmI() { return getRegister(WHO_AM_I); } bool MMA8451Q::isActive() { return __active; } void MMA8451Q::setActive(bool activate) { uint8_t data; data = getRegister(CTRL_REG1); if (activate) data |= CTRL_REG1_ACTIVE_MASK; //Set bit else data &= ~CTRL_REG1_ACTIVE_MASK; //Clear bit setRegister(CTRL_REG1, data); __active = activate; } uint8_t MMA8451Q::getSystemMode() { return getRegister(SYSMOD); } bool MMA8451Q::is14bDataEnabled() { return __14b_data_enabled; } void MMA8451Q::set14bData(bool enable) { bool wasActive = isActive(); if (wasActive) setActive(false); //deactivate before updating control bits uint8_t data; data = getRegister(CTRL_REG1); data = (data & ~CTRL_REG1_F_READ_MASK) | (CTRL_REG1_F_READ_MASK & enable); //Set 2nd LSB to enable setRegister(CTRL_REG1, data); __14b_data_enabled = enable; if (wasActive) setActive(true); //restore activity } MMA8451Q::smpl_rate_t MMA8451Q::getOutputDataRate() { return __output_data_rate; } void MMA8451Q::setOutputDataRate(MMA8451Q::smpl_rate_t rate) { bool wasActive = __active; if (wasActive) setActive(false); //must disable to update register uint8_t data, dr; data = getRegister(CTRL_REG1); switch (rate) { case HZ800: dr = 0; break; case HZ400: dr = 1; break; case HZ200: dr = 2; break; case HZ100: dr = 3; break; case HZ50: dr = 4; break; case HZ12_5: dr = 5; break; case HZ6_25: dr = 6; break; case HZ1_56: dr = 7; break; default: dr = 0; //800HZ break; } data = (data & ~CTRL_REG1_DR_MASK) | (dr << 3); setRegister(CTRL_REG1, data); if (wasActive) setActive(true); //Restore active state __output_data_rate = rate; } MMA8451Q::scale_t MMA8451Q::getScale() { return __scale; } void MMA8451Q::setScale(MMA8451Q::scale_t scale) { bool wasActive = __active; if (wasActive) setActive(false); //deactivate before updating control bits uint8_t data = getRegister(XYZ_DATA_CFG); data = (data & ~XYZ_DATA_CFG_FS_MASK) | scale; setRegister(XYZ_DATA_CFG, data); if (wasActive) setActive(true); //restore activity __scale = scale; switch (scale) { default: case G2: __div = G2_DIV; break; case G4: __div = G4_DIV; break; case G8: __div = G8_DIV; break; } } void MMA8451Q::enableDataReadyInterrupt(bool enable, bool pinSelect) { //Deactivate sensor bool wasActive = __active; if (wasActive) setActive(false); //Configure interrupt uint8_t tmp; if (pinSelect) tmp = 0xFF; else tmp = 0x00; uint8_t data = tmp & CTRL_REG5_INT_CFG_DRDY_MASK; //Clear all other interrupt configurations, because I said so setRegister(CTRL_REG5, data); //Enable interrupt if (enable) tmp = 0xFF; else tmp = 0x00; data = tmp & CTRL_REG4_INT_EN_DRDY_MASK; //Clear all other interrupt configurations, because I said so setRegister(CTRL_REG4, data); //Clear IPOL bit (2nd LSB), such that active interrupt is LOW, and set PP_OD bit (LSB) such that it is in open drain mode data = getRegister(CTRL_REG3); data = (data & ~CTRL_REG3_IPOL_MASK); // | CTRL_REG3_PP_OD_MASK; setRegister(CTRL_REG3, data); //Re-activate sensor if (wasActive) setActive(true); } int16_t MMA8451Q::getX(bool sampleNow) { __disable_irq(); if (sampleNow) { uint8_t data_msb, data_lsb; //Do bitwise ops on unsigned 8-bit parts uint16_t x_tmp = 0; data_msb = getRegister(OUT_X_MSB); if (__14b_data_enabled) { data_lsb = getRegister(OUT_X_LSB); data_lsb &= 0xFC; //ensure 2 LSB are cleared! } else data_lsb = 0; x_tmp = data_msb << 8; x_tmp |= data_lsb; //Now, treat the number as signed, then arithmetic right shift by 2 __x = x_tmp; __x = __x >> 2; } __dataReady = false; __enable_irq(); return __x; } int16_t MMA8451Q::getY(bool sampleNow) { __disable_irq(); if (sampleNow) { uint8_t data_msb, data_lsb; //Do bitwise ops on unsigned 8-bit parts uint16_t y_tmp = 0; data_msb = getRegister(OUT_Y_MSB); if (__14b_data_enabled) { data_lsb = getRegister(OUT_Y_LSB); data_lsb &= 0xFC; //ensure 2 LSB are cleared! } else data_lsb = 0; y_tmp = data_msb << 8; y_tmp |= data_lsb; //Now, treat the number as signed, then arithmetic right shift by 2 __y = y_tmp; __y = __y >> 2; } __dataReady = false; __enable_irq(); return __y; } int16_t MMA8451Q::getZ(bool sampleNow) { __disable_irq(); if (sampleNow) { uint8_t data_msb, data_lsb; //Do bitwise ops on unsigned 8-bit parts uint16_t z_tmp = 0; data_msb = getRegister(OUT_Z_MSB); if (__14b_data_enabled) { data_lsb = getRegister(OUT_Z_LSB); data_lsb &= 0xFC; //ensure 2 LSB are cleared! } else data_lsb = 0; z_tmp = data_msb << 8; z_tmp |= data_lsb; //Now, treat the number as signed, then arithmetic right shift by 2 __z = z_tmp; __z = __z >> 2; } __dataReady = false; __enable_irq(); return __z; } float MMA8451Q::getFloatX(bool sampleNow) { return getX(sampleNow) * __div; } float MMA8451Q::getFloatY(bool sampleNow) { return getY(sampleNow) * __div; } float MMA8451Q::getFloatZ(bool sampleNow) { return getZ(sampleNow) * __div; } void MMA8451Q::sleep() { } void MMA8451Q::wake() { } void MMA8451Q::__sample_data_ISR() { getX(true); getY(true); getZ(true); __dataReady = true; }