A compilation of some hardware sensors and their shared programming interfaces.

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MMA8451Q.cpp Source File

MMA8451Q.cpp

00001 /* MMA8451Q.cpp
00002  * Tested with mbed board: FRDM-KL46Z
00003  * Author: Mark Gottscho
00004  * mgottscho@ucla.edu
00005  */
00006  
00007 #include "mbed.h"
00008 #include "I2CSensor.h"
00009 #include "PeriodicSensor.h"
00010 #include "SleepableSensor.h"
00011 #include "MMA8451Q.h"
00012 
00013 using namespace std;
00014 
00015 //////////////////// PUBLIC METHODS ////////////////////
00016 
00017 MMA8451Q::MMA8451Q (PinName sda, PinName scl, int i2c_addr) : 
00018                                         I2CSensor(sda, scl, i2c_addr), //parent constructor
00019                                         PeriodicSensor(0.05), //default max sampling rate of 20Hz
00020                                         SleepableSensor(),
00021                                         __x(0),
00022                                         __y(0),
00023                                         __z(0),
00024                                         __active(false),
00025                                         __14b_data_enabled(true),
00026                                         __output_data_rate(MMA8451Q::smpl_rate_t(0)),
00027                                         __scale(MMA8451Q::scale_t(0)),
00028                                         __div(G2_DIV)
00029                                         { }
00030 
00031 MMA8451Q::~MMA8451Q() {}
00032 
00033 void MMA8451Q::selfInit() {
00034     __i2c.frequency(400000);
00035     reset();
00036     setOutputDataRate (HZ800);
00037     setScale (G2);
00038     set14bData (true);
00039     //enableDataReadyInterrupt(true, true); //INT1
00040 }
00041 
00042 void MMA8451Q::reset() {
00043     uint8_t data = CTRL_REG2_RST_MASK;
00044     setRegister(CTRL_REG2, data);
00045     wait(0.1); 
00046 }
00047 
00048 uint8_t MMA8451Q::whoAmI() {
00049     return getRegister(WHO_AM_I);
00050 }
00051 
00052 bool MMA8451Q::isActive () {
00053     return __active;
00054 }
00055 
00056 void MMA8451Q::setActive (bool activate) {
00057     uint8_t data;
00058     data = getRegister(CTRL_REG1);
00059     if (activate)
00060         data |= CTRL_REG1_ACTIVE_MASK; //Set bit
00061     else
00062         data &= ~CTRL_REG1_ACTIVE_MASK; //Clear bit
00063     setRegister(CTRL_REG1, data);
00064     __active = activate;
00065 }
00066 
00067 uint8_t MMA8451Q::getSystemMode () {
00068     return getRegister(SYSMOD);  
00069 }
00070 
00071 bool MMA8451Q::is14bDataEnabled () {
00072     return __14b_data_enabled;
00073 }
00074 
00075 void MMA8451Q::set14bData (bool enable) {
00076     bool wasActive = isActive ();
00077     if (wasActive)
00078         setActive (false); //deactivate before updating control bits
00079         
00080     uint8_t data;
00081     data = getRegister(CTRL_REG1);
00082     data = (data & ~CTRL_REG1_F_READ_MASK) | (CTRL_REG1_F_READ_MASK & enable); //Set 2nd LSB to enable
00083     setRegister(CTRL_REG1, data);
00084     __14b_data_enabled = enable;
00085     
00086     if (wasActive)
00087         setActive (true); //restore activity
00088 }
00089 
00090 MMA8451Q::smpl_rate_t MMA8451Q::getOutputDataRate () {
00091     return __output_data_rate;   
00092 }
00093 
00094 void MMA8451Q::setOutputDataRate (MMA8451Q::smpl_rate_t rate) {
00095     bool wasActive = __active;
00096     if (wasActive)
00097         setActive (false); //must disable to update register
00098         
00099     uint8_t data, dr;
00100     data = getRegister(CTRL_REG1);
00101     switch (rate) {
00102         case HZ800:
00103             dr = 0;
00104             break;
00105         case HZ400:
00106             dr = 1;
00107             break;
00108         case HZ200:
00109             dr = 2;
00110             break;
00111         case HZ100:
00112             dr = 3;
00113             break;
00114         case HZ50:
00115             dr = 4;
00116             break;
00117         case HZ12_5:
00118             dr = 5;
00119             break;
00120         case HZ6_25:
00121             dr = 6;
00122             break;
00123         case HZ1_56:
00124             dr = 7;
00125             break;
00126         default:
00127             dr = 0; //800HZ
00128             break;    
00129     }   
00130     data = (data & ~CTRL_REG1_DR_MASK) | (dr << 3);
00131     setRegister(CTRL_REG1, data);
00132     
00133     if (wasActive)
00134         setActive (true); //Restore active state
00135         
00136     __output_data_rate = rate;
00137 }
00138 
00139 MMA8451Q::scale_t MMA8451Q::getScale () {
00140     return __scale;
00141 }
00142 
00143 void MMA8451Q::setScale (MMA8451Q::scale_t scale) {
00144     bool wasActive = __active;
00145     if (wasActive)
00146         setActive (false); //deactivate before updating control bits
00147         
00148     uint8_t data = getRegister(XYZ_DATA_CFG);
00149     data = (data & ~XYZ_DATA_CFG_FS_MASK) | scale;
00150     setRegister(XYZ_DATA_CFG, data);
00151     
00152     if (wasActive)
00153         setActive (true); //restore activity
00154         
00155     __scale = scale;
00156     switch (scale) {
00157         default:
00158         case G2:
00159             __div = G2_DIV;
00160             break;
00161         case G4:
00162             __div = G4_DIV;
00163             break;
00164         case G8:
00165             __div = G8_DIV;
00166             break;
00167     }
00168 }
00169 
00170 void MMA8451Q::enableDataReadyInterrupt(bool enable, bool pinSelect) {
00171     //Deactivate sensor
00172     bool wasActive = __active;
00173     if (wasActive)
00174         setActive (false);
00175 
00176     //Configure interrupt
00177     uint8_t tmp;
00178     if (pinSelect)
00179         tmp = 0xFF;
00180     else
00181         tmp = 0x00;
00182     uint8_t data = tmp & CTRL_REG5_INT_CFG_DRDY_MASK; //Clear all other interrupt configurations, because I said so
00183     setRegister(CTRL_REG5, data);
00184     
00185     //Enable interrupt
00186     if (enable)
00187         tmp = 0xFF;
00188     else
00189         tmp = 0x00;
00190     data = tmp & CTRL_REG4_INT_EN_DRDY_MASK; //Clear all other interrupt configurations, because I said so
00191     setRegister(CTRL_REG4, data);
00192     
00193     //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
00194     data = getRegister(CTRL_REG3);
00195     data = (data & ~CTRL_REG3_IPOL_MASK); // | CTRL_REG3_PP_OD_MASK;
00196     setRegister(CTRL_REG3, data);
00197     
00198     //Re-activate sensor
00199     if (wasActive)
00200         setActive (true);    
00201 }
00202         
00203 int16_t MMA8451Q::getX (bool sampleNow) {
00204     __disable_irq();
00205     if (sampleNow) {
00206         uint8_t data_msb, data_lsb;
00207         
00208         //Do bitwise ops on unsigned 8-bit parts
00209         uint16_t x_tmp = 0;
00210         data_msb = getRegister(OUT_X_MSB);
00211         if (__14b_data_enabled) {
00212             data_lsb = getRegister(OUT_X_LSB);
00213             data_lsb &= 0xFC; //ensure 2 LSB are cleared!
00214         } else
00215             data_lsb = 0;
00216         x_tmp = data_msb << 8;
00217         x_tmp |= data_lsb;
00218         
00219         //Now, treat the number as signed, then arithmetic right shift by 2
00220         __x = x_tmp;
00221         __x = __x >> 2;
00222     }
00223     
00224     __dataReady = false;
00225     __enable_irq();
00226     
00227     return __x;
00228 }
00229 
00230 int16_t MMA8451Q::getY (bool sampleNow) {
00231     __disable_irq();
00232     if (sampleNow) {
00233         uint8_t data_msb, data_lsb;
00234     
00235         //Do bitwise ops on unsigned 8-bit parts
00236         uint16_t y_tmp = 0;
00237         data_msb = getRegister(OUT_Y_MSB);
00238         if (__14b_data_enabled) {
00239             data_lsb = getRegister(OUT_Y_LSB);
00240             data_lsb &= 0xFC; //ensure 2 LSB are cleared!
00241         } else
00242             data_lsb = 0;
00243         y_tmp = data_msb << 8;
00244         y_tmp |= data_lsb;
00245         
00246         //Now, treat the number as signed, then arithmetic right shift by 2
00247         __y = y_tmp;
00248         __y = __y >> 2;
00249     }
00250     
00251     __dataReady = false;
00252     __enable_irq();
00253     
00254     return __y;
00255 }
00256 
00257 int16_t MMA8451Q::getZ (bool sampleNow) {
00258     __disable_irq();
00259     if (sampleNow) {
00260         uint8_t data_msb, data_lsb;
00261         
00262         //Do bitwise ops on unsigned 8-bit parts
00263         uint16_t z_tmp = 0;
00264         data_msb = getRegister(OUT_Z_MSB);
00265         if (__14b_data_enabled) {
00266             data_lsb = getRegister(OUT_Z_LSB);
00267             data_lsb &= 0xFC; //ensure 2 LSB are cleared!
00268         } else
00269             data_lsb = 0;
00270         z_tmp = data_msb << 8;
00271         z_tmp |= data_lsb;
00272         
00273         //Now, treat the number as signed, then arithmetic right shift by 2
00274         __z = z_tmp;
00275         __z = __z >> 2;
00276     }
00277     
00278     __dataReady = false;
00279     __enable_irq();
00280     
00281     return __z;
00282 }
00283 
00284 float MMA8451Q::getFloatX (bool sampleNow) {
00285     return getX (sampleNow) * __div;   
00286 }
00287 
00288 float MMA8451Q::getFloatY (bool sampleNow) {
00289     return getY (sampleNow) * __div;   
00290 }
00291 
00292 float MMA8451Q::getFloatZ (bool sampleNow) {
00293     return getZ (sampleNow) * __div;   
00294 }
00295 
00296 void MMA8451Q::sleep() {
00297     
00298 }
00299 
00300 void MMA8451Q::wake() {
00301     
00302 }
00303 
00304 void MMA8451Q::__sample_data_ISR() {
00305     getX (true);
00306     getY (true);
00307     getZ (true);
00308     __dataReady = true;
00309 }