Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API nRF51822 mbed
Fork of KS7 by
MMA845x.cpp
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 *)®, 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
Generated on Tue Jul 12 2022 21:16:17 by
1.7.2
