mma8451q driver
Dependents: nRF51822_DataLogger_PowerImpulseCounter scpi_sx127x NAMote72_Utility scpi_sx127x_firstTest
mma8451q.cpp
00001 #include "mma8451q.h" 00002 /* turn on: CTRL_REG1 active_bit = 1 00003 * back to standby: CTRL_REG1 active_bit = 0 00004 */ 00005 00006 /* STANDBY: SYSMOD = 00 */ 00007 00008 /* 00009 * MMA8451 I2C address 00010 */ 00011 #define MMA8451_I2C_ADDRESS 0x38 //0x1C 00012 00013 00014 MMA8451Q::MMA8451Q(I2C& r, DigitalIn& int_pin) : m_i2c(r), m_int_pin(int_pin) 00015 { 00016 /* INT pins on this chip default to push-pull output */ 00017 write(MMA8451_CTRL_REG3, 0x01); // set PP_OD 00018 /* INT1 and INT2 are tied together */ 00019 00020 } 00021 00022 MMA8451Q::~MMA8451Q() 00023 { 00024 } 00025 00026 void MMA8451Q::read(uint8_t addr, uint8_t *dst_buf, int length) 00027 { 00028 char cmd[2]; 00029 00030 cmd[0] = addr; 00031 if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 1, true)) 00032 printf("MMA write-fail %02x\n", addr); 00033 if (m_i2c.read(MMA8451_I2C_ADDRESS, (char *)dst_buf, length)) 00034 printf("MMA read-fail\n"); 00035 } 00036 00037 uint8_t MMA8451Q::read_single(uint8_t addr) 00038 { 00039 char cmd[2]; 00040 00041 cmd[0] = addr; 00042 if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 1, true)) 00043 printf("MMA write-fail %02x\n", addr); 00044 if (m_i2c.read(MMA8451_I2C_ADDRESS, cmd, 1)) 00045 printf("MMA read-fail\n"); 00046 00047 return cmd[0]; 00048 } 00049 00050 void MMA8451Q::print_regs() 00051 { 00052 printf("ID: %02x\n", read_single(MMA8451_ID)); 00053 printf("sysmod:%02x\n", read_single(MMA8451_SYSMOD)); 00054 ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1); 00055 printf("ctrl_reg1:%02x\n", ctrl_reg1.octet); 00056 printf("ctrl_reg2:%02x\n", read_single(MMA8451_CTRL_REG2)); 00057 printf("ctrl_reg3:%02x\n", read_single(MMA8451_CTRL_REG3)); /* TODO: PP_OD is bit 0 (1=open drain) */ 00058 printf("(int en) ctrl_reg4:%02x\n", read_single(MMA8451_CTRL_REG4)); 00059 printf("(int cfg) ctrl_reg5:%02x\n", read_single(MMA8451_CTRL_REG5)); 00060 printf("status:%02x\n", read_single(MMA8451_STATUS)); 00061 /* (interrupt status) int src at 0x0c (MMA8451_INT_SOURCE): data ready, motion/freefall, pulse, orientation, transient, auto sleep */ 00062 printf("INT_SOURCE:%02x\n", read_single(MMA8451_INT_SOURCE)); 00063 } 00064 00065 void MMA8451Q::write(uint8_t addr, uint8_t data) 00066 { 00067 uint8_t cmd[2]; 00068 00069 cmd[0] = addr; 00070 cmd[1] = data; 00071 00072 if (m_i2c.write(MMA8451_I2C_ADDRESS, (char *)cmd, 2)) 00073 printf("MMA write-fail %02x\n", addr); 00074 } 00075 00076 void MMA8451Q::set_active(char arg) 00077 { 00078 char cmd[2]; 00079 00080 cmd[0] = MMA8451_CTRL_REG1; 00081 cmd[1] = arg; 00082 00083 if (m_i2c.write(MMA8451_I2C_ADDRESS, cmd, 2)) 00084 printf("MMA write-fail %02x\n", cmd[0]); 00085 } 00086 00087 bool MMA8451Q::get_active(void) 00088 { 00089 uint8_t ret = read_single(MMA8451_CTRL_REG1); 00090 //printf("CTRL_REG1: %x\n", ret); 00091 if (ret & 1) 00092 return true; 00093 else 00094 return false; 00095 } 00096 00097 void MMA8451Q::orient_detect() 00098 { 00099 uint8_t v; 00100 00101 ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1); 00102 /* AN4068 Sensors Freescale Semiconductor, Inc. 00103 * 4.1 Example Steps for Implementing the Embedded Orientation Detection */ 00104 00105 /* Step 1: Put the part into Standby Mode */ 00106 ctrl_reg1.bits.ACTIVE = 0; 00107 write(MMA8451_CTRL_REG1, ctrl_reg1.octet); 00108 00109 /* Step 2: Set the data rate to 50 Hz (for example, but can choose any sample rate). */ 00110 ctrl_reg1.bits.DR = 4; 00111 write(MMA8451_CTRL_REG1, ctrl_reg1.octet); 00112 00113 /* Step 3: Set the PL_EN bit in Register 0x11 PL_CFG. This will enable the orientation detection. */ 00114 v = read_single(MMA8451_PL_CFG); 00115 v |= 0x40; 00116 write(MMA8451_PL_CFG, v); 00117 00118 /* Step 4: Set the Back/Front Angle trip points in register 0x13 following the table in the data sheet. */ 00119 v = read_single(MMA8451_PL_BF_ZCOMP); 00120 /*v &= 0x3f; 00121 v |= 0xX0; 00122 write(MMA8451_PL_BF_ZCOMP, v);*/ 00123 00124 /* Step 5: Set the Z-Lockout angle trip point in register 0x13 following the table in the data sheet. */ 00125 /* v &= 0xf8; 00126 v |= 0x0X; 00127 */ 00128 00129 /* Step 6: Set the Trip Threshold Angle */ 00130 v = read_single(MMA8451_PL_THS_REG); 00131 /*v &= 0x07; 00132 v |= 0x0X << 3; 00133 write(MMA8451_PL_THS_REG. v);*/ 00134 00135 /* Step 7: Set the Hysteresis Angle */ 00136 v = read_single(MMA8451_PL_THS_REG); 00137 /*v &= 0xf8; 00138 v |= 0x0X; 00139 write(MMA8451_PL_THS_REG. v);*/ 00140 00141 /* Step 8: Register 0x2D, Control Register 4 configures all embedded features for interrupt */ 00142 ctrl_reg4.octet = 0; 00143 ctrl_reg4.bits.INT_EN_LNDPRT = 1; 00144 write(MMA8451_CTRL_REG4, ctrl_reg4.octet); 00145 00146 /* Step 9: Register 0x2E is Control Register 5 which gives the option of routing the interrupt to either INT1 or INT2 */ 00147 ctrl_reg5.octet = 0; 00148 ctrl_reg5.bits.INT_CFG_LNDPRT = 1; 00149 write(MMA8451_CTRL_REG5, ctrl_reg5.octet); 00150 00151 /* Step 10: Set the debounce counter in register 0x12 */ 00152 write(MMA8451_PL_COUNT, 5); // 5: debounce to 100ms at 50hz 00153 00154 /* Step 11: Put the device in Active Mode */ 00155 ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1); 00156 ctrl_reg1.bits.ACTIVE = 1; 00157 write(MMA8451_CTRL_REG1, ctrl_reg1.octet); 00158 00159 /* Step 12: in service() function */ 00160 } 00161 00162 00163 void MMA8451Q::transient_detect() 00164 { 00165 ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1); 00166 /* AN4071 Sensors Freescale Semiconductor, Inc. 00167 * 7.1 Example Steps for Configuring Transient Detection 00168 * Change in X or Y > 0.5g for 50 ms at 100 Hz ODR, Normal mode */ 00169 00170 /* Step 1: Put the device in Standby Mode: Register 0x2A CTRL_REG1 */ 00171 ctrl_reg1.bits.ACTIVE = 0; 00172 write(MMA8451_CTRL_REG1, ctrl_reg1.octet); 00173 ctrl_reg1.bits.DR = 3; //Set device in 100 Hz ODR, Standby 00174 write(MMA8451_CTRL_REG1, ctrl_reg1.octet); 00175 00176 /* Step 2: Enable X and Y Axes and enable the latch: Register 0x1D Configuration Register */ 00177 transient_cfg.octet = 0; 00178 transient_cfg.bits.ELE = 1; // enable latch 00179 transient_cfg.bits.YTEFE = 1; // enable Y 00180 transient_cfg.bits.XTEFE = 1; // enable X 00181 transient_cfg.bits.ZTEFE = 1; // enable Z 00182 write(MMA8451_TRANSIENT_CFG, transient_cfg.octet); 00183 00184 /* Step 3: Set the Threshold: Register 0x1F 00185 * Note: Step count is 0.063g per count, 0.5g / 0.063g = 7.93. 00186 * Therefore set the threshold to 8 counts */ 00187 write(MMA8451_TRANSIENT_THS, 8); 00188 00189 /* Step 4: Set the Debounce Counter for 50 ms: Register 0x20 00190 * Note: 100 Hz ODR, therefore 10 ms step sizes */ 00191 write(MMA8451_TRANSIENT_COUNT, 5); 00192 00193 /* Step 5: Enable Transient Detection Interrupt in the System (CTRL_REG4) */ 00194 ctrl_reg4.octet = 0; 00195 ctrl_reg4.bits.INT_EN_TRANS = 1; 00196 write(MMA8451_CTRL_REG4, ctrl_reg4.octet); 00197 00198 /* Step 6: Route the Transient Interrupt to INT 1 hardware pin (CTRL_REG5) */ 00199 ctrl_reg5.octet = 0; 00200 ctrl_reg5.bits.INT_CFG_TRANS = 1; 00201 write(MMA8451_CTRL_REG5, ctrl_reg5.octet); 00202 00203 /* Step 7: Put the device in Active Mode: Register 0x2A CTRL_REG1 */ 00204 ctrl_reg1.octet = read_single(MMA8451_CTRL_REG1); 00205 ctrl_reg1.bits.ACTIVE = 1; 00206 write(MMA8451_CTRL_REG1, ctrl_reg1.octet); 00207 00208 /* Step 8: Write Interrupt Service Routine Reading the 00209 * System Interrupt Status and the Transient Status */ 00210 } 00211 00212 uint8_t MMA8451Q::service() 00213 { 00214 mma_int_source_t int_src; 00215 if (m_int_pin) 00216 return 0; // no interrupt 00217 00218 int_src.octet = read_single(MMA8451_INT_SOURCE); 00219 00220 if (int_src.bits.SRC_DRDY) { 00221 read(MMA8451_OUT_X_MSB, out.octets, 6); 00222 } 00223 if (int_src.bits.SRC_FF_MT) { 00224 read_single(MMA8451_FF_MT_SRC); 00225 } 00226 if (int_src.bits.SRC_PULSE) { 00227 read_single(MMA8451_PULSE_SRC); 00228 } 00229 if (int_src.bits.SRC_LNDPRT) { 00230 mma_pl_status_t pl_status; 00231 /*AN4068 Step 12: Write a Service Routine to Service the Interrupt */ 00232 pl_status.octet = read_single(MMA8451_PL_STATUS); 00233 if (verbose) { 00234 printf("PL_STATUS: "); 00235 if (pl_status.bits.NEWLP) { 00236 if (pl_status.bits.LO) 00237 printf("Z-tilt-LO "); 00238 00239 if (pl_status.bits.LAPO == 0) 00240 printf("up "); 00241 else if (pl_status.bits.LAPO == 1) 00242 printf("down "); 00243 else if (pl_status.bits.LAPO == 2) 00244 printf("left "); 00245 else if (pl_status.bits.LAPO == 3) 00246 printf("right "); 00247 00248 if (pl_status.bits.BAFRO) 00249 printf("back "); 00250 else 00251 printf("front "); 00252 } 00253 printf("\r\n"); 00254 } 00255 } // ...int_src.bits.SRC_LNDPRT 00256 00257 if (int_src.bits.SRC_TRANS) { 00258 transient_src_t t_src; 00259 t_src.octet = read_single(MMA8451_TRANSIENT_SRC); 00260 if (verbose) { 00261 printf("transient src:%x ", t_src.octet); 00262 if (t_src.bits.XTRANSE) 00263 printf("X_Pol:%d ", t_src.bits.X_Trans_Pol); 00264 if (t_src.bits.YTRANSE) 00265 printf("Y_Pol:%d ", t_src.bits.Y_Trans_Pol); 00266 if (t_src.bits.ZTRANSE) 00267 printf("Z_Pol:%d ", t_src.bits.Z_Trans_Pol); 00268 printf("\r\n"); 00269 } 00270 } // ...int_src.bits.SRC_TRANS 00271 00272 if (int_src.bits.SRC_ASLP) { 00273 read_single(MMA8451_SYSMOD); 00274 } 00275 00276 return int_src.octet; 00277 }
Generated on Fri Jul 22 2022 09:25:44 by 1.7.2