Dan Bryant / firstRig

Dependencies:   BLE_API PinDetect mbed-src-bmd-200

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MMA845x.cpp Source File

MMA845x.cpp

Go to the documentation of this file.
00001 /**
00002  * @file    MMA845x.cpp
00003  * @brief   Device driver - MMA845X 3-axis accelerometer IC
00004  * @author  sam grove
00005  * @version 1.0
00006  * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8451Q.pdf
00007  * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8452Q.pdf
00008  * @see     http://cache.freescale.com/files/sensors/doc/data_sheet/MMA8453Q.pdf
00009  *
00010  * Copyright (c) 2013
00011  *
00012  * Licensed under the Apache License, Version 2.0 (the "License");
00013  * you may not use this file except in compliance with the License.
00014  * You may obtain a copy of the License at
00015  *
00016  *     http://www.apache.org/licenses/LICENSE-2.0
00017  *
00018  * Unless required by applicable law or agreed to in writing, software
00019  * distributed under the License is distributed on an "AS IS" BASIS,
00020  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00021  * See the License for the specific language governing permissions and
00022  * limitations under the License.
00023  */
00024  
00025 #include "MMA845x.h"
00026 #include "mbed.h"
00027  
00028 
00029 void MMA845x::disable(void)
00030 {
00031     uint8_t reg_val = 0;
00032     // Reset all registers to POR values
00033     MMA845x::writeRegister(CTRL_REG2, 0xF0);        //REG 0x2B
00034     wait(0.05);
00035     do{
00036         // wait for the reset bit to clear
00037         reg_val = MMA845x::readRegister(CTRL_REG2) & 0x40;
00038     }while(reg_val);
00039     MMA845x::writeRegister(CTRL_REG1, 0x00);        //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 50hz
00040 }
00041 
00042 void MMA845x::setIntMode(int intMode)
00043 {
00044     _intMode = intMode;
00045 }
00046 
00047 void MMA845x::interrupt_1(void)
00048 {
00049     //_int1_waiting = true;
00050     
00051     uint8_t reg_int_sts;
00052     uint8_t reg_sts;
00053     uint8_t reg_pulse_sts;
00054     uint8_t reg_motion_sts;
00055     char reg_data[3][2] = { 0 };
00056     int16_t values[3] = { 0 };
00057     float g_values[3] = { 0 };
00058     reg_int_sts = MMA845x::readRegister(INT_SOURCE);    //REG 0x0C
00059     if((reg_int_sts & 0x01)) //Mask register read with SRC_DRDY bit
00060     {
00061         printf("Int1:");
00062         printf(" Data Ready");
00063         reg_sts = MMA845x::readRegister(STATUS);    //REG 0x00
00064         
00065         reg_pulse_sts = MMA845x::readRegister(PULSE_SRC);    //REG 0x22
00066         
00067         reg_data[0][0] = MMA845x::readRegister(OUT_X_MSB);    //REG 0x01
00068         reg_data[0][1] = MMA845x::readRegister(OUT_X_LSB);    //REG 0x02
00069         reg_data[1][0] = MMA845x::readRegister(OUT_Y_MSB);    //REG 0x03
00070         reg_data[1][1] = MMA845x::readRegister(OUT_Y_LSB);    //REG 0x04
00071         reg_data[2][0] = MMA845x::readRegister(OUT_Z_MSB);    //REG 0x05
00072         reg_data[2][1] = MMA845x::readRegister(OUT_Z_LSB);    //REG 0x06
00073         //printf(" STATUS: 0x%02X X: %d %d Y: %d %d Z: %d %d\n\r", reg_sts, reg_data[0][0], reg_data[0][1], reg_data[1][0], reg_data[1][1], reg_data[2][0], reg_data[2][1]);
00074             
00075         values[0] = ((reg_data[0][0] * 256) + ((unsigned short) reg_data[0][1]));
00076         values[1] = ((reg_data[1][0] * 256) + ((unsigned short) reg_data[1][1]));
00077         values[2] = ((reg_data[2][0] * 256) + ((unsigned short) reg_data[2][1]));
00078     
00079         g_values[0] = ((float) values[0]) / 16384.0;
00080         g_values[1] = ((float) values[1]) / 16384.0;
00081         g_values[2] = ((float) values[2]) / 16384.0;
00082             
00083         //printf(" STATUS: 0x%02X X: %d Y: %d Z: %d\n\r", reg_sts, values[0], values[1], values[2]); 
00084         
00085         if (_intMode == 1)
00086         {
00087             printf(" STATUS: 0x%02X X: %.3f Y: %.3f Z: %.3f", reg_sts, g_values[0], g_values[1], g_values[2]);
00088         }
00089         else
00090         {
00091             int bars = abs( values[0] / 512 );
00092             printf(" X: ");
00093             for( int i = 0; i < bars; i++ )
00094             {
00095                 printf(">");
00096             }
00097         }
00098         
00099         if (reg_pulse_sts & 0x10)
00100         {
00101             printf(" ***********************************************");
00102             _callbackZAxisPulse.call();
00103             if (reg_pulse_sts & 0x01)
00104             {
00105                 printf("--------------");    
00106             }
00107         }
00108         printf("\n\r");
00109     }
00110     if (reg_int_sts & 0x08) //Pulse interrupt
00111     {
00112         
00113         reg_pulse_sts = MMA845x::readRegister(PULSE_SRC);    //REG 0x22
00114         if (reg_pulse_sts & 0x40) //Z-axis event
00115         {
00116             
00117             if (reg_pulse_sts & 0x08) //Pulse event was double pulse
00118             {
00119                 
00120                 
00121             }
00122             if (reg_pulse_sts & 0x04)//Z-axis pulse direction
00123             {
00124                 
00125             }
00126             _callbackZAxisPulse.call();
00127             
00128         }
00129     }
00130     if (reg_int_sts & 0x04) //Motion interrupt
00131     {
00132         
00133         reg_motion_sts = MMA845x::readRegister(FF_MT_SRC);    //REG 0x16
00134         if (reg_motion_sts & 0x02) //
00135         {
00136             /*
00137             if (reg_motion_sts & 0x08) //
00138             {
00139                 
00140                 
00141             }
00142             if (reg_motion_sts & 0x04)//
00143             {
00144                 
00145             }
00146             */
00147             _callbackZAxisPulse.call();
00148             
00149         }
00150     }
00151 }
00152 
00153      /* Call this function when a Z-axis pulse detected
00154      *  @param function A C function pointer
00155      */
00156 void MMA845x::attachZAxisPulse( void (*function)(void) )
00157 {
00158     _callbackZAxisPulse.attach( function );
00159 }
00160     
00161 void MMA845x::interrupt_handler(void)
00162 {
00163     
00164     uint8_t reg_int_sts;
00165     uint8_t reg_sts;
00166     int reg_data[3] = { 0x00, 0x00, 0x00 };
00167     printf("Int1:");
00168     reg_int_sts = MMA845x::readRegister(INT_SOURCE);    //REG 0x0C
00169     if((reg_int_sts & 0x01)) //Mask register read with SRC_DRDY bit
00170     {
00171         printf(" Data Ready");
00172         reg_sts = MMA845x::readRegister(STATUS);    //REG 0x00
00173         reg_data[0] = MMA845x::readRegister(OUT_X_MSB);    //REG 0x01
00174         reg_data[1] = MMA845x::readRegister(OUT_Y_MSB);    //REG 0x03
00175         reg_data[2] = MMA845x::readRegister(OUT_Z_MSB);    //REG 0x05
00176         printf(" STATUS: 0x%02X X: %d Y: %d Z: %d\n\r", reg_sts, reg_data[0], reg_data[1], reg_data[2]);
00177     }
00178 }
00179 
00180 void MMA845x::init(void) const
00181 {
00182     uint8_t reg_val = 0;
00183     
00184     _i2c->frequency(400000);
00185     
00186     // Reset all registers to POR values
00187     MMA845x::writeRegister(CTRL_REG2, 0x40);        //REG 0x2B
00188     do{
00189         // wait for the reset bit to clear
00190         reg_val = MMA845x::readRegister(CTRL_REG2) & 0x40;
00191     }while(reg_val);
00192     
00193     // setup the registers that are common among modes
00194     MMA845x::writeRegister(CTRL_REG1, 0xA0);        //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 50hz
00195     MMA845x::writeRegister(CTRL_REG2, 0x18);        //REG 0x2B Setup for low-power, no auto-sleep
00196     MMA845x::writeRegister(CTRL_REG3, 0x00);        //REG 0x2C No interrupts wake device, active low int, push-pull
00197     MMA845x::writeRegister(CTRL_REG4, 0x00);        //REG 0x2D
00198     MMA845x::writeRegister(CTRL_REG5, 0xFD);        //REG 0x2E All interrupt sources to INT1
00199     
00200     MMA845x::writeRegister(XYZ_DATA_CFG, 0x11);      //REG 0x0E HPF / scale +/-2,4,8g
00201     MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x00);  //REG 0x0F HPF settings
00202     
00203     return;
00204 }
00205 
00206 void MMA845x::enableDataReadyMode(void) const
00207 {
00208     MMA845x::init();
00209     //MMA845x::writeRegister(SYSMOD, 0x01);        //REG 0x0B This register is read only
00210     //MMA845x::writeRegister(INT_SOURCE, 0x01);    //REG 0x0C This register is read only
00211     MMA845x::writeRegister(CTRL_REG4, 0x09);        //REG 0x2D Enable data ready interrupt
00212     
00213     
00214     
00215     //MMA845x::writeRegister(CTRL_REG1, 0xA3);        //REG 0x2A 0xA3 = ASLP_RATE: 6.25hz Data Rate: 50hz, Fast Read, Active mode
00216     
00217     MMA845x::writeRegister(XYZ_DATA_CFG, 0x11);      //REG 0x0E HPF / scale +/-2,4,8g - Enable HPF
00218     MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x10);  //REG 0x0F HPF settings - HPF for pulse on, 0.25Hz cutoff for 12.5rate
00219     
00220     
00221     MMA845x::writeRegister(PULSE_CFG, 0x41);        //REG 0x21 Setup single pulse in x axis
00222     MMA845x::writeRegister(PULSE_THSX, 0x09);        //REG 0x21 Setup pulse threshold in x axis
00223     MMA845x::writeRegister(PULSE_TMLT, 0x14);        //REG 0x21 Setup single pulse in x axis
00224     MMA845x::writeRegister(PULSE_LTCY, 0x04);        //REG 0x21 Setup single latency in x axis
00225     
00226     
00227     MMA845x::writeRegister(CTRL_REG1, 0xA1);        //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 12.5hz, Normal Read, Active mode
00228     
00229 }
00230 
00231 void MMA845x::enableMotionMode(void) const
00232 {
00233     MMA845x::init();
00234     
00235     MMA845x::writeRegister(CTRL_REG4, 0x04);        //REG 0x2D Enable pulse interrupt
00236         
00237     MMA845x::writeRegister(XYZ_DATA_CFG, 0xF1);      //REG 0x0E HPF / scale +/-4g, Enable HPF for output data
00238     MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x00);  //REG 0x0F HPF settings - HPF for pulse on, 4Hz cutoff for 100Hz rate
00239     
00240     MMA845x::writeRegister(FF_MT_CFG, 0xC8);        //REG 0x21 Setup 
00241     MMA845x::writeRegister(FF_MT_THS, 0x01);        //REG 0x21 Setup 
00242     MMA845x::writeRegister(FF_MT_COUNT, 0x5);        //REG 0x21 Setup 
00243     
00244     MMA845x::writeRegister(CTRL_REG2, 0x03);        //REG 0x2B Setup for low power mode, no auto-sleep
00245     MMA845x::writeRegister(CTRL_REG1, 0xA1);        //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 12.5Hz, Normal Read, Active mode
00246     
00247 }
00248 
00249 void MMA845x::enablePulseMode(void) const
00250 {
00251     MMA845x::init();
00252     
00253     MMA845x::writeRegister(CTRL_REG4, 0x08);        //REG 0x2D Enable pulse interrupt
00254         
00255     MMA845x::writeRegister(XYZ_DATA_CFG, 0xF1);      //REG 0x0E HPF / scale +/-2,4,8g - Enable HPF
00256     MMA845x::writeRegister(HP_FILTER_CUTOFF, 0x00);  //REG 0x0F HPF settings - HPF for pulse on, 4Hz cutoff for 100Hz rate
00257     
00258     MMA845x::writeRegister(PULSE_CFG, 0x50);        //REG 0x21 Setup single pulse in z axis
00259     MMA845x::writeRegister(PULSE_THSX, 0x06);        //REG 0x21 Setup pulse threshold in x axis
00260     MMA845x::writeRegister(PULSE_THSZ, 0x2F);        //REG 0x21 Setup pulse threshold in z axis
00261     MMA845x::writeRegister(PULSE_TMLT, 0x28);        //REG 0x21 Setup single pulse
00262     MMA845x::writeRegister(PULSE_LTCY, 0x0D);        //REG 0x21 Setup single latency
00263     MMA845x::writeRegister(PULSE_WIND, 0x2D);        //REG 0x21 Setup double pulse window
00264     
00265     MMA845x::writeRegister(CTRL_REG2, 0x00);        //REG 0x2B Setup for normal power mode, no auto-sleep
00266     MMA845x::writeRegister(CTRL_REG1, 0x99);        //REG 0x2A 0x98 = ASLP_RATE: 6.25hz Data Rate: 100Hz, Normal Read, Active mode
00267     
00268 }
00269 
00270 void MMA845x::enableOrientationMode(void) const
00271 {
00272     uint16_t who_am_i = MMA845x::readRegister(WHO_AM_I);
00273     if(who_am_i != MMA8451 )
00274     {
00275         error("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
00276     }
00277     
00278     return;
00279 }
00280 
00281 void MMA845x::enableTransitMode(void) const{}
00282 void MMA845x::enableAutoSleepMode(void) const{}
00283 
00284 void MMA845x::enableFIFOMode(void) const
00285 {
00286     uint16_t who_am_i = MMA845x::readRegister(WHO_AM_I);
00287     if(who_am_i != MMA8451 )
00288     {
00289         error("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__);
00290     }
00291     
00292     //MMA845x::writeRegister(
00293     
00294     return;
00295 }
00296 
00297 uint16_t MMA845x::getX(void) const
00298 {
00299     return _data._x ;
00300 }
00301     
00302 uint16_t MMA845x::getY(void) const
00303 {
00304     return _data._y ;
00305 }
00306 
00307 uint16_t MMA845x::getZ(void) const
00308 {
00309     return _data._z ;
00310 }
00311     
00312 MMA845x_DATA MMA845x::getXYZ(void) const
00313 {
00314     return _data;
00315 }
00316 
00317 void MMA845x::writeRegister(uint8_t const reg, uint8_t const data) const
00318 {
00319     char buf[2] = {reg, data};
00320     uint8_t result = 0;
00321     
00322     /*
00323     __disable_irq(); // Tickers and other timebase events can jack up the I2C bus for some devices
00324     result = _i2c->write(_i2c_addr, buf, 2);
00325     __enable_irq();  // Just need to block during the transaction
00326     */
00327 
00328     result = _i2c->write(_i2c_addr, (const char *)&buf, 2, false);
00329     
00330     if(0 != result)
00331     {
00332         error("%s %d: I2c write failed\n", __FILE__, __LINE__);
00333     }
00334     
00335     return;
00336 }
00337 
00338 uint8_t MMA845x::readRegister(uint8_t const reg) const
00339 {
00340     uint8_t result = 1, data = 0;
00341     /*
00342     __disable_irq(); // Tickers and other timebase events can jack up the I2C bus
00343     _i2c->start();
00344     result &= _i2c->write(_i2c_addr);
00345     result &= _i2c->write(reg);
00346     // issue a repeated start...
00347     _i2c->start();
00348     result &= _i2c->write(_i2c_addr | 0x01);
00349     // read with nak
00350     data = _i2c->read(0);
00351     _i2c->stop();
00352     __enable_irq();  // Just need to block during the transaction
00353     */
00354     
00355     result &= _i2c->write(_i2c_addr, (const char *)&reg, 1, true);
00356     result &= _i2c->read(_i2c_addr, (char *)&data, 1);
00357     
00358     if(1 != result)
00359     {
00360         //error("%s %d: I2C read failed\n", __FILE__, __LINE__);
00361     }
00362     
00363     return data;
00364 }
00365 
00366 void MMA845x::registerDump(void) const
00367 {
00368     uint8_t reg_val = 0;
00369     printf("Starting register dump...\n\r");
00370     
00371     for(int i=0; i<0x31; i++)
00372     {
00373         reg_val = MMA845x::readRegister(i);
00374         printf("Reg 0x%02x: 0x%02x \n\r", i, reg_val);
00375     }
00376     
00377     return;
00378 }
00379