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.
Fork of MMA845x by
MMA845x.cpp
00001 /** 00002 * @file MMA845x.cpp 00003 * @brief Device driver - MMA845X 3-axis accelerometer IC W/RTOS support 00004 * @author Tim Barr 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) 2015 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 * 5/5/2015 Forked from https://developer.mbed.org/users/sam_grove/code/MMA845x/ 00025 * 00026 * 6/20/2015 TAB Added setup functions and polling data capability. Also added RTOS calls 00027 * TODO Still need to add interrupt support for other Accelerometer mode support 00028 */ 00029 00030 #include "MMA845x.h" 00031 #include "mbed_debug.h" 00032 #include "rtos.h" 00033 00034 MMA845x::MMA845x(I2C &i2c, SA0 const i2c_addr, InterruptIn* int1, InterruptIn* int2) 00035 { 00036 _i2c = &i2c; 00037 _int1 = int1; 00038 _int2 = int2; 00039 00040 _i2c_addr = (0x1c | i2c_addr) << 1; 00041 00042 MMA845x::init(); 00043 00044 return; 00045 } 00046 00047 uint8_t MMA845x::init(void) 00048 { 00049 uint8_t result = 0; 00050 uint8_t i = 0; 00051 char reg_val[1]; 00052 00053 _who_am_i = 0x00; 00054 00055 // Reset all registers to POR values 00056 result = MMA845x::writeRegister(CTRL_REG2, 0xFF); //REG 0x2B 00057 if (result == 0) { 00058 00059 do { 00060 // wait for the reset bit to clear. readRegister may error out so we re-try 10 times 00061 osDelay(200); 00062 reg_val[0] = 0x40; 00063 result = MMA845x::readRegister(CTRL_REG2,1,reg_val); 00064 reg_val[0] = reg_val[0] & 0x40; 00065 i++; 00066 } while(((reg_val[0] != 0)||( result != 0)) && (i<=10)); 00067 } 00068 00069 if (result == 0) { 00070 result = MMA845x::readRegister(WHO_AM_I,1,reg_val); 00071 } 00072 00073 switch (reg_val[0]) { 00074 case MMA8451 : 00075 case MMA8452 : 00076 case MMA8453 : 00077 _who_am_i= reg_val[0]; 00078 if ((_int1 == NULL) && (_int2 == NULL)) 00079 _polling_mode = true; 00080 else _polling_mode = false; 00081 break; 00082 default: 00083 debug ("Device not supported by this library!\n\r"); 00084 result = 1; 00085 } 00086 00087 if(result != 0) { 00088 debug("MMA845x:init failed\n\r"); 00089 } 00090 00091 00092 return result; 00093 } 00094 00095 uint8_t MMA845x::setCommonParameters(RANGE range, RESOLUTION resolution, LOW_NOISE lo_noise, 00096 DATA_RATE data_rate, OVERSAMPLE_MODE os_mode, HPF_MODE hpf_mode) const 00097 { 00098 uint8_t result = 0; 00099 char datain[1]; 00100 uint8_t dataout = 0; 00101 00102 result |= MMA845x::readRegister(SYSMOD,1,datain); // Make sure MMA845x is in Stand-By mode 00103 if ((datain[0] & 0x03) != 0 ) { 00104 debug ("MMA845x not in STAND BY mode\n\f"); 00105 debug("MMA845x:setCommonParameters failed\n\r"); 00106 result = 1; 00107 return result; 00108 } 00109 00110 result |= MMA845x::readRegister(CTRL_REG1, 1, datain); 00111 dataout = (datain[0] & 0xC1) | resolution | lo_noise | data_rate; // 0b 0010 1010 00112 result |= MMA845x::writeRegister(CTRL_REG1, dataout); // Set resolution, Low Noise mode, and data rate 00113 00114 result |= MMA845x::readRegister(CTRL_REG2,1, datain); 00115 dataout = (datain[0] & 0xFC) | os_mode; 00116 result |= MMA845x::writeRegister(CTRL_REG2, dataout); // Set Oversample mode for Active State 00117 00118 result |= MMA845x::readRegister(XYZ_DATA_CFG,1, datain); 00119 dataout = range | hpf_mode; 00120 result |= MMA845x::writeRegister(XYZ_DATA_CFG, dataout); //Set HPF mode and range 00121 00122 // result |= MMA845x::readRegister(HP_FILTER_CUTOFF,1, datain); 00123 // result |= MMA845x::writeRegister(HP_FILTER_CUTOFF, dataout); //REG 0xF HPF settings 00124 00125 if(result != 0) { 00126 debug("MMA845x:setParameters failed\n\r"); 00127 } 00128 00129 return result; 00130 00131 } 00132 00133 uint8_t MMA845x::enableMotionDetect(void) const 00134 { 00135 uint8_t result = 0; 00136 return result; 00137 } 00138 00139 uint8_t MMA845x::enablePulseDetect(char x_threshold , char y_threshold, char z_threshold, char window, char latency, INTERRUPT_PIN pin) const 00140 { 00141 uint8_t result = 0; 00142 result |= MMA845x::writeRegister(MMA845x::PULSE_CFG, (0b01000000 | (x_threshold?0b1:0) | (y_threshold?0b100:0) | (z_threshold?0b10000:0))); // enable tap latch & single taps on every axis 00143 MMA845x::writeRegister(MMA845x::PULSE_THSX, x_threshold & 127); // some thresholds 00144 MMA845x::writeRegister(MMA845x::PULSE_THSY, y_threshold & 127); 00145 MMA845x::writeRegister(MMA845x::PULSE_THSZ, z_threshold & 127); 00146 MMA845x::writeRegister(MMA845x::PULSE_TMLT, window); // time window. unit of 5ms 00147 MMA845x::writeRegister(MMA845x::PULSE_LTCY, latency); // set latency to 300..ms ?..? 00148 MMA845x::writeRegister(MMA845x::HP_FILTER_CUTOFF, 0b00110000); // by-pass High pass filter for pulse processing // for good meausure (??) 00149 00150 result |= configInterrupt(INT_PULSE, pin); 00151 00152 return result; 00153 } 00154 00155 uint8_t MMA845x::enableOrientationDetect(uint8_t debounce_steps, INTERRUPT_PIN pin) const 00156 { 00157 uint8_t result = 0; 00158 // if(_who_am_i != MMA8451) { 00159 // debug("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__); 00160 // result = 1; 00161 // } 00162 // ↑ not true. MMA8451 is the only one supporting variable trip-angle values 00163 00164 MMA845x::writeRegister(PL_COUNT, debounce_steps); 00165 MMA845x::writeRegister(PL_CFG, 0b11000000); // enable and set debounce counter to clear out of {clear, decrement} 00166 00167 result |= configInterrupt(INT_LNDPRT, pin); 00168 00169 return result; 00170 } 00171 00172 uint8_t MMA845x::enableTransientDetect(void) const 00173 { 00174 uint8_t result = 0; 00175 return result; 00176 } 00177 00178 uint8_t MMA845x::enableAutoSleep(void) const 00179 { 00180 uint8_t result = 0; 00181 return result; 00182 } 00183 00184 uint8_t MMA845x::enableFIFO(void) const 00185 { 00186 uint8_t result = 0; 00187 00188 if(_who_am_i != MMA8451 ) { 00189 debug("%s %d: Feature not compatible with the connected device.\n", __FILE__, __LINE__); 00190 result = 1; 00191 } 00192 00193 return result; 00194 } 00195 00196 uint8_t MMA845x::configInterrupt(INTERRUPT_CFG_EN_SOURCE function, INTERRUPT_PIN pin) const 00197 { 00198 uint8_t result = 0; 00199 char datain[1]; 00200 uint8_t dataout; 00201 00202 if (pin != INT_NONE) { 00203 // enable interrupt 00204 result |= MMA845x::readRegister(CTRL_REG4, 1, datain); 00205 dataout = (datain[0] | function); 00206 result |= MMA845x::writeRegister(CTRL_REG4, dataout); 00207 00208 //set pin for the interrupt 00209 result |= MMA845x::readRegister(CTRL_REG5, 1, datain); 00210 if (pin == 0) dataout = (datain[0] & ~function); // clearing bit 00211 else dataout = (datain[0] | function); // setting bit 00212 } else { 00213 // disable interrupt 00214 result |= MMA845x::readRegister(CTRL_REG4, 1, datain); 00215 dataout = (datain[0] & ~function); 00216 result |= MMA845x::writeRegister(CTRL_REG4, dataout); 00217 } 00218 return result; 00219 } 00220 00221 uint8_t MMA845x::activeMode(void) const 00222 { 00223 uint8_t result = 0; 00224 char datain[1]; 00225 uint8_t dataout; 00226 00227 result |= MMA845x::readRegister(CTRL_REG1,1, datain); 00228 dataout = (datain[0] & 0xFE) | 0x01 ; 00229 result |= MMA845x::writeRegister(CTRL_REG1, dataout); // Set to active mode 00230 00231 return result; 00232 } 00233 uint8_t MMA845x::standbyMode(void) const 00234 { 00235 uint8_t result = 0; 00236 char datain[1]; 00237 uint8_t dataout; 00238 00239 result |= MMA845x::readRegister(CTRL_REG1,1, datain); 00240 dataout = (datain[0] & 0xFE); 00241 result |= MMA845x::writeRegister(CTRL_REG1, dataout); // Set to standby mode 00242 00243 return result; 00244 } 00245 00246 uint8_t MMA845x::getStatus(void) const 00247 { 00248 uint8_t result = 0; 00249 char datain[1]; 00250 uint8_t dataout; 00251 00252 result = MMA845x::readRegister(STATUS,1, datain); 00253 00254 if (result != 0) 00255 dataout = result; 00256 else 00257 dataout = datain[0]; 00258 00259 return dataout; 00260 } 00261 00262 int16_t MMA845x::getX(void) 00263 { 00264 char datain[2]; 00265 00266 if (_polling_mode) { 00267 MMA845x::readRegister(OUT_X_MSB,2, datain); 00268 _data._x = ((datain[0] << 8) | datain[1]); /* data is 14 bit signed with 2 LSB = 0 */ 00269 _data._x /= 4; /* need to shift first to preserve sign then /4 to remove LSBs */ 00270 } 00271 return _data._x ; 00272 00273 } 00274 00275 int16_t MMA845x::getY(void) 00276 { 00277 char datain[2]; 00278 00279 if (_polling_mode) { 00280 MMA845x::readRegister(OUT_Y_MSB,2, datain); 00281 _data._y = ((datain[0] << 8) | datain[1]); /* data is 14 bit signed with 2 LSB = 0 */ 00282 _data._y /= 4; /* need to shift first to preserve sign then /4 to remove LSBs */ 00283 } 00284 return _data._y ; 00285 } 00286 00287 int16_t MMA845x::getZ(void) 00288 { 00289 char datain[2]; 00290 00291 if (_polling_mode) { 00292 MMA845x::readRegister(OUT_Z_MSB,2, datain); 00293 _data._z = ((datain[0] << 8) | datain[1]); /* data is 14 bit signed with 2 LSB = 0 */ 00294 _data._z /= 4; /* need to shift first to preserve sign then /4 to remove LSBs */ 00295 } 00296 00297 return _data._z ; 00298 } 00299 00300 MMA845x_DATA MMA845x::getXYZ(void) 00301 { 00302 char datain[6]; 00303 00304 if (_polling_mode) { 00305 MMA845x::readRegister(OUT_X_MSB,6, datain); /* data is 14 bit signed with 2 LSB = 0 */ 00306 _data._x = ((datain[0] << 8) | datain[1]); /* need to shift first to preserve sign */ 00307 _data._x /= 4; /* then /4 to remove LSBs */ 00308 _data._y = ((datain[2] << 8) | datain[3]); 00309 _data._y /= 4; 00310 _data._z = ((datain[4] << 8) | datain[5]); 00311 _data._z /= 4; 00312 } 00313 00314 return _data; 00315 } 00316 00317 char MMA845x::getWhoAmI(void) const 00318 { 00319 return _who_am_i; 00320 } 00321 00322 uint8_t MMA845x::writeRegister(uint8_t const reg, uint8_t const data) const 00323 { 00324 char buf[2] = {reg, data}; 00325 uint8_t result = 0; 00326 00327 buf[0] = reg; 00328 buf[1] = data; 00329 00330 result |= _i2c->write(_i2c_addr, buf, 2); 00331 00332 if (result != 0) { 00333 debug("MMA845x::writeRegister failed r-%d\n\r",result); 00334 } 00335 00336 return result; 00337 } 00338 00339 uint8_t MMA845x::readRegister(uint8_t const reg, uint8_t count, char* data) const 00340 { 00341 uint8_t result = 0; 00342 char reg_out[1]; 00343 00344 reg_out[0] = reg; 00345 _i2c->lock(); 00346 00347 // MMA8451Q expects a repeated start from the master 00348 result |= _i2c->write(_i2c_addr,reg_out,1,true); 00349 00350 if (result != 0) { 00351 debug("MMA845x::readRegister failed write r- %d\n\r", result); 00352 goto exit; 00353 } 00354 00355 result |= _i2c->read(_i2c_addr,data,count,false); 00356 00357 if (result != 0) { 00358 debug("MMA845x::readRegister failed read r-%d\n\r",result); 00359 } 00360 00361 exit: 00362 _i2c->unlock(); 00363 return result; 00364 }
Generated on Tue Jul 12 2022 18:37:50 by
1.7.2
