test

Dependencies:   BLE_API nRF51822 mbed

Fork of KS7 by masaaki makabe

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