Chen Huan
/
MPU6050_Driver_Balance
平衡车的MPU6050驱动 C.H.
Embed:
(wiki syntax)
Show/hide line numbers
mpu6050.cpp
00001 #include <stdio.h> 00002 #include <stdint.h> 00003 #include <stdlib.h> 00004 #include <string.h> 00005 #include <math.h> 00006 #include "mpu6050.h" 00007 00008 ////////////////////////////////////////////////////////////////////////////////// 00009 //MPU6050驱动程序 C.H. 00010 ////////////////////////////////////////////////////////////////////////////////// 00011 00012 00013 00014 //初始化MPU6050 00015 //返回值:0,成功 00016 // 其他,错误代码 00017 unsigned char MPU_Init(void) 00018 { 00019 unsigned char res; 00020 MPU_IIC_Init();//初始化IIC总线 00021 MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80); //复位MPU6050 00022 delay_ms(100); 00023 MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00); //唤醒MPU6050 00024 MPU_Set_Gyro_Fsr(3); //陀螺仪传感器,±2000dps 00025 MPU_Set_Accel_Fsr(0); //加速度传感器,±2g 00026 MPU_Set_Rate(50); //设置采样率50Hz 00027 MPU_Write_Byte(MPU_INT_EN_REG,0X00); //关闭所有中断 00028 MPU_Write_Byte(MPU_USER_CTRL_REG,0X00); //I2C主模式关闭 00029 MPU_Write_Byte(MPU_FIFO_EN_REG,0X00); //关闭FIFO 00030 MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80); //INT引脚低电平有效 00031 res=MPU_Read_Byte(MPU_DEVICE_ID_REG); 00032 if(res==MPU_ADDR)//器件ID正确 00033 { 00034 MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01); //设置CLKSEL,PLL X轴为参考 00035 MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00); //加速度与陀螺仪都工作 00036 MPU_Set_Rate(50); //设置采样率为50Hz 00037 }else return 1; 00038 return 0; 00039 } 00040 00041 00042 00043 //设置MPU6050陀螺仪传感器满量程范围 00044 //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps 00045 //返回值:0,设置成功 00046 // 其他,设置失败 00047 unsigned char MPU_Set_Gyro_Fsr(unsigned char fsr) 00048 { 00049 return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围 00050 } 00051 //设置MPU6050加速度传感器满量程范围 00052 //fsr:0,±2g;1,±4g;2,±8g;3,±16g 00053 //返回值:0,设置成功 00054 // 其他,设置失败 00055 unsigned char MPU_Set_Accel_Fsr(unsigned char fsr) 00056 { 00057 return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围 00058 } 00059 //设置MPU6050的数字低通滤波器 00060 //lpf:数字低通滤波频率(Hz) 00061 //返回值:0,设置成功 00062 // 其他,设置失败 00063 unsigned char MPU_Set_LPF(unsigned short lpf) 00064 { 00065 unsigned char data=0; 00066 if(lpf>=188)data=1; 00067 else if(lpf>=98)data=2; 00068 else if(lpf>=42)data=3; 00069 else if(lpf>=20)data=4; 00070 else if(lpf>=10)data=5; 00071 else data=6; 00072 return MPU_Write_Byte(MPU_CFG_REG,data);//设置数字低通滤波器 00073 } 00074 //设置MPU6050的采样率(假定Fs=1KHz) 00075 //rate:4~1000(Hz) 00076 //返回值:0,设置成功 00077 // 其他,设置失败 00078 unsigned char MPU_Set_Rate(unsigned short rate) 00079 { 00080 unsigned char data; 00081 if(rate>1000)rate=1000; 00082 if(rate<4)rate=4; 00083 data=1000/rate-1; 00084 data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data); //设置数字低通滤波器 00085 return MPU_Set_LPF(rate/2); //自动设置LPF为采样率的一半 00086 } 00087 00088 //得到温度值 00089 //返回值:温度值(扩大了100倍) 00090 short MPU_Get_Temperature(void) 00091 { 00092 unsigned char buf[2]; 00093 short raw; 00094 float temp; 00095 MPU_Read_Len(MPU_ADDR,MPU_TEMP_OUTH_REG,2,buf); 00096 raw=((unsigned short )buf[0]<<8)|buf[1]; 00097 temp=36.53+((double)raw)/340; 00098 return temp*100;; 00099 } 00100 //得到陀螺仪值(原始值) 00101 //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号) 00102 //返回值:0,成功 00103 // 其他,错误代码 00104 unsigned char MPU_Get_Gyroscope(short *gx,short *gy,short *gz) 00105 { 00106 unsigned char buf[6],res; 00107 res=MPU_Read_Len(MPU_ADDR,MPU_GYRO_XOUTH_REG,6,buf); 00108 if(res==0) 00109 { 00110 *gx=((unsigned short )buf[0]<<8)|buf[1]; 00111 *gy=((unsigned short )buf[2]<<8)|buf[3]; 00112 *gz=((unsigned short )buf[4]<<8)|buf[5]; 00113 } 00114 return res;; 00115 } 00116 //得到加速度值(原始值) 00117 //gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号) 00118 //返回值:0,成功 00119 // 其他,错误代码 00120 unsigned char MPU_Get_Accelerometer(short *ax,short *ay,short *az) 00121 { 00122 unsigned char buf[6],res; 00123 res=MPU_Read_Len(MPU_ADDR,MPU_ACCEL_XOUTH_REG,6,buf); 00124 if(res==0) 00125 { 00126 *ax=((unsigned short )buf[0]<<8)|buf[1]; 00127 *ay=((unsigned short )buf[2]<<8)|buf[3]; 00128 *az=((unsigned short )buf[4]<<8)|buf[5]; 00129 } 00130 return res;; 00131 } 00132 //IIC连续写 00133 //addr:器件地址 00134 //reg:寄存器地址 00135 //len:写入长度 00136 //buf:数据区 00137 //返回值:0,正常 00138 // 其他,错误代码 00139 unsigned char MPU_Write_Len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf) 00140 { 00141 unsigned char i; 00142 MPU_IIC_Start(); 00143 MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令 00144 if(MPU_IIC_Wait_Ack()) //等待应答 00145 { 00146 MPU_IIC_Stop(); 00147 return 1; 00148 } 00149 MPU_IIC_Send_Byte(reg); //写寄存器地址 00150 MPU_IIC_Wait_Ack(); //等待应答 00151 for(i=0;i<len;i++) 00152 { 00153 MPU_IIC_Send_Byte(buf[i]); //发送数据 00154 if(MPU_IIC_Wait_Ack()) //等待ACK 00155 { 00156 MPU_IIC_Stop(); 00157 return 1; 00158 } 00159 } 00160 MPU_IIC_Stop(); 00161 return 0; 00162 } 00163 //IIC连续读 00164 //addr:器件地址 00165 //reg:要读取的寄存器地址 00166 //len:要读取的长度 00167 //buf:读取到的数据存储区 00168 //返回值:0,正常 00169 // 其他,错误代码 00170 unsigned char MPU_Read_Len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf) 00171 { 00172 MPU_IIC_Start(); 00173 MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令 00174 if(MPU_IIC_Wait_Ack()) //等待应答 00175 { 00176 MPU_IIC_Stop(); 00177 return 1; 00178 } 00179 MPU_IIC_Send_Byte(reg); //写寄存器地址 00180 MPU_IIC_Wait_Ack(); //等待应答 00181 MPU_IIC_Start(); 00182 MPU_IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令 00183 MPU_IIC_Wait_Ack(); //等待应答 00184 while(len) 00185 { 00186 if(len==1)*buf=MPU_IIC_Read_Byte(0);//读数据,发送nACK 00187 else *buf=MPU_IIC_Read_Byte(1); //读数据,发送ACK 00188 len--; 00189 buf++; 00190 } 00191 MPU_IIC_Stop(); //产生一个停止条件 00192 return 0; 00193 } 00194 //IIC写一个字节 00195 //reg:寄存器地址 00196 //data:数据 00197 //返回值:0,正常 00198 // 其他,错误代码 00199 unsigned char MPU_Write_Byte(unsigned char reg,unsigned char data) 00200 { 00201 MPU_IIC_Start(); 00202 MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 00203 if(MPU_IIC_Wait_Ack()) //等待应答 00204 { 00205 MPU_IIC_Stop(); 00206 return 1; 00207 } 00208 MPU_IIC_Send_Byte(reg); //写寄存器地址 00209 MPU_IIC_Wait_Ack(); //等待应答 00210 MPU_IIC_Send_Byte(data);//发送数据 00211 if(MPU_IIC_Wait_Ack()) //等待ACK 00212 { 00213 MPU_IIC_Stop(); 00214 return 1; 00215 } 00216 MPU_IIC_Stop(); 00217 return 0; 00218 } 00219 //IIC读一个字节 00220 //reg:寄存器地址 00221 //返回值:读到的数据 00222 unsigned char MPU_Read_Byte(unsigned char reg) 00223 { 00224 unsigned char res; 00225 MPU_IIC_Start(); 00226 MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令 00227 MPU_IIC_Wait_Ack(); //等待应答 00228 MPU_IIC_Send_Byte(reg); //写寄存器地址 00229 MPU_IIC_Wait_Ack(); //等待应答 00230 MPU_IIC_Start(); 00231 MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令 00232 MPU_IIC_Wait_Ack(); //等待应答 00233 res=MPU_IIC_Read_Byte(0);//读取数据,发送nACK 00234 MPU_IIC_Stop(); //产生一个停止条件 00235 return res; 00236 }/**/ 00237 00238 00239 //MPU IIC 延时函数 00240 void MPU_IIC_Delay(void) 00241 { 00242 delay_us(2); 00243 } 00244 //初始化IIC 00245 void MPU_IIC_Init(void) 00246 { 00247 00248 00249 #if defined DRIVER_MODE_BALANCE 00250 RCC->APB2ENR|=1<<3; //先使能外设IO PORTC时钟 00251 GPIOB->CRL&=0X00FFFFFF; //PC11/12 推挽输出 00252 GPIOB->CRL|=0X33000000; 00253 GPIOB->ODR|=3<<6; //PC11,12 输出高 00254 #elif defined DRIVER_MODE_ROTOR 00255 RCC->APB2ENR|=1<<3; //先使能外设IO PORTC时钟 00256 GPIOB->CRH&=0XFFF00FFF; //PC11/12 推挽输出 00257 GPIOB->CRH|=0X00033000; 00258 GPIOB->ODR|=3<<11; //PC11,12 输出高 00259 #else 00260 #error Target Board is not specified. 00261 #endif 00262 } 00263 //产生IIC起始信号 00264 void MPU_IIC_Start(void) 00265 { 00266 MPU_SDA_OUT(); //sda线输出 00267 MPU_IIC_SDA=1; 00268 MPU_IIC_SCL=1; 00269 MPU_IIC_Delay(); 00270 MPU_IIC_SDA=0;//START:when CLK is high,DATA change form high to low 00271 MPU_IIC_Delay(); 00272 MPU_IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 00273 } 00274 //产生IIC停止信号 00275 void MPU_IIC_Stop(void) 00276 { 00277 MPU_SDA_OUT();//sda线输出 00278 MPU_IIC_SCL=0; 00279 MPU_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high 00280 MPU_IIC_Delay(); 00281 MPU_IIC_SCL=1; 00282 MPU_IIC_SDA=1;//发送I2C总线结束信号 00283 MPU_IIC_Delay(); 00284 } 00285 //等待应答信号到来 00286 //返回值:1,接收应答失败 00287 // 0,接收应答成功 00288 unsigned char MPU_IIC_Wait_Ack(void) 00289 { 00290 unsigned char ucErrTime=0; 00291 MPU_SDA_IN(); //SDA设置为输入 00292 MPU_IIC_SDA=1;MPU_IIC_Delay(); 00293 MPU_IIC_SCL=1;MPU_IIC_Delay(); 00294 while(MPU_READ_SDA) 00295 { 00296 ucErrTime++; 00297 if(ucErrTime>250) 00298 { 00299 MPU_IIC_Stop(); 00300 return 1; 00301 } 00302 } 00303 MPU_IIC_SCL=0;//时钟输出0 00304 return 0; 00305 } 00306 //产生ACK应答 00307 void MPU_IIC_Ack(void) 00308 { 00309 MPU_IIC_SCL=0; 00310 MPU_SDA_OUT(); 00311 MPU_IIC_SDA=0; 00312 MPU_IIC_Delay(); 00313 MPU_IIC_SCL=1; 00314 MPU_IIC_Delay(); 00315 MPU_IIC_SCL=0; 00316 } 00317 //不产生ACK应答 00318 void MPU_IIC_NAck(void) 00319 { 00320 MPU_IIC_SCL=0; 00321 MPU_SDA_OUT(); 00322 MPU_IIC_SDA=1; 00323 MPU_IIC_Delay(); 00324 MPU_IIC_SCL=1; 00325 MPU_IIC_Delay(); 00326 MPU_IIC_SCL=0; 00327 } 00328 //IIC发送一个字节 00329 //返回从机有无应答 00330 //1,有应答 00331 //0,无应答 00332 void MPU_IIC_Send_Byte(unsigned char txd) 00333 { 00334 unsigned char t; 00335 MPU_SDA_OUT(); 00336 MPU_IIC_SCL=0;//拉低时钟开始数据传输 00337 for(t=0;t<8;t++) 00338 { 00339 MPU_IIC_SDA=(txd&0x80)>>7; 00340 txd<<=1; 00341 MPU_IIC_SCL=1; 00342 MPU_IIC_Delay(); 00343 MPU_IIC_SCL=0; 00344 MPU_IIC_Delay(); 00345 } 00346 } 00347 //读1个字节,ack=1时,发送ACK,ack=0,发送nACK 00348 unsigned char MPU_IIC_Read_Byte(unsigned char ack) 00349 { 00350 unsigned char i,receive=0; 00351 MPU_SDA_IN();//SDA设置为输入 00352 for(i=0;i<8;i++ ) 00353 { 00354 MPU_IIC_SCL=0; 00355 MPU_IIC_Delay(); 00356 MPU_IIC_SCL=1; 00357 receive<<=1; 00358 if(MPU_READ_SDA)receive++; 00359 MPU_IIC_Delay(); 00360 } 00361 if (!ack) 00362 MPU_IIC_NAck();//发送nACK 00363 else 00364 MPU_IIC_Ack(); //发送ACK 00365 return receive; 00366 } 00367 00368 #define MPU6050 //定义我们使用的传感器为MPU6050 00369 #define MOTION_DRIVER_TARGET_MSP430 //定义驱动部分,采用MSP430的驱动(移植到STM32F1) 00370 00371 /* The following functions must be defined for this platform: 00372 * i2c_write(unsigned char slave_addr, unsigned char reg_addr, 00373 * unsigned char length, unsigned char const *data) 00374 * i2c_read(unsigned char slave_addr, unsigned char reg_addr, 00375 * unsigned char length, unsigned char *data) 00376 * delay_ms(unsigned long num_ms) 00377 * get_ms(unsigned long *count) 00378 * reg_int_cb(void (*cb)(void), unsigned char port, unsigned char pin) 00379 * labs(long x) 00380 * fabsf(float x) 00381 * min(int a, int b) 00382 */ 00383 #if defined MOTION_DRIVER_TARGET_MSP430 00384 //#include "msp430.h" 00385 //#include "msp430_i2c.h" 00386 //#include "msp430_clock.h" 00387 //#include "msp430_interrupt.h" 00388 00389 #define i2c_write MPU_Write_Len 00390 #define i2c_read MPU_Read_Len 00391 //#define delay_ms delay_ms 00392 #define get_ms mget_ms 00393 //static inline int reg_int_cb(struct int_param_s *int_param) 00394 //{ 00395 // return msp430_reg_int_cb(int_param->cb, int_param->pin, int_param->lp_exit, 00396 // int_param->active_low); 00397 //} 00398 ////#define // printf //打印信息 00399 ////#define // printf //打印信息 00400 /* labs is already defined by TI's toolchain. */ 00401 /* fabs is for doubles. fabsf is for floats. */ 00402 #define fabs fabsf 00403 #define min(a,b) ((a<b)?a:b) 00404 #elif defined EMPL_TARGET_MSP430 00405 #include "msp430.h" 00406 #include "msp430_i2c.h" 00407 #include "msp430_clock.h" 00408 #include "msp430_interrupt.h" 00409 #include "log.h" 00410 #define i2c_write msp430_i2c_write 00411 #define i2c_read msp430_i2c_read 00412 #define delay_ms msp430_delay_ms 00413 #define get_ms msp430_get_clock_ms 00414 static inline int reg_int_cb(struct int_param_s *int_param) 00415 { 00416 return msp430_reg_int_cb(int_param->cb, int_param->pin, int_param->lp_exit, 00417 int_param->active_low); 00418 } 00419 //#define // MPL_LOGI 00420 //#define // MPL_LOGE 00421 /* labs is already defined by TI's toolchain. */ 00422 /* fabs is for doubles. fabsf is for floats. */ 00423 #define fabs fabsf 00424 #define min(a,b) ((a<b)?a:b) 00425 #elif defined EMPL_TARGET_UC3L0 00426 /* Instead of using the standard TWI driver from the ASF library, we're using 00427 * a TWI driver that follows the slave address + register address convention. 00428 */ 00429 #include "twi.h" 00430 #include "delay.h" 00431 #include "sysclk.h" 00432 #include "log.h" 00433 #include "sensors_xplained.h" 00434 #include "uc3l0_clock.h" 00435 #define i2c_write(a, b, c, d) twi_write(a, b, d, c) 00436 #define i2c_read(a, b, c, d) twi_read(a, b, d, c) 00437 /* delay_ms is a function already defined in ASF. */ 00438 #define get_ms uc3l0_get_clock_ms 00439 static inline int reg_int_cb(struct int_param_s *int_param) 00440 { 00441 sensor_board_irq_connect(int_param->pin, int_param->cb, int_param->arg); 00442 return 0; 00443 } 00444 //#define // MPL_LOGI 00445 //#define // MPL_LOGE 00446 /* UC3 is a 32-bit processor, so abs and labs are equivalent. */ 00447 #define labs abs 00448 #define fabs(x) (((x)>0)?(x):-(x)) 00449 #else 00450 #error Gyro driver is missing the system layer implementations. 00451 #endif 00452 00453 #if !defined MPU6050 && !defined MPU9150 && !defined MPU6500 && !defined MPU9250 00454 #error Which gyro are you using? Define MPUxxxx in your compiler options. 00455 #endif 00456 00457 /* Time for some messy macro work. =] 00458 * #define MPU9150 00459 * is equivalent to.. 00460 * #define MPU6050 00461 * #define AK8975_SECONDARY 00462 * 00463 * #define MPU9250 00464 * is equivalent to.. 00465 * #define MPU6500 00466 * #define AK8963_SECONDARY 00467 */ 00468 #if defined MPU9150 00469 #ifndef MPU6050 00470 #define MPU6050 00471 #endif /* #ifndef MPU6050 */ 00472 #if defined AK8963_SECONDARY 00473 #error "MPU9150 and AK8963_SECONDARY cannot both be defined." 00474 #elif !defined AK8975_SECONDARY /* #if defined AK8963_SECONDARY */ 00475 #define AK8975_SECONDARY 00476 #endif /* #if defined AK8963_SECONDARY */ 00477 #elif defined MPU9250 /* #if defined MPU9150 */ 00478 #ifndef MPU6500 00479 #define MPU6500 00480 #endif /* #ifndef MPU6500 */ 00481 #if defined AK8975_SECONDARY 00482 #error "MPU9250 and AK8975_SECONDARY cannot both be defined." 00483 #elif !defined AK8963_SECONDARY /* #if defined AK8975_SECONDARY */ 00484 #define AK8963_SECONDARY 00485 #endif /* #if defined AK8975_SECONDARY */ 00486 #endif /* #if defined MPU9150 */ 00487 00488 #if defined AK8975_SECONDARY || defined AK8963_SECONDARY 00489 #define AK89xx_SECONDARY 00490 #else 00491 /* #warning "No compass = less profit for Invensense. Lame." */ 00492 #endif 00493 00494 static int set_int_enable(unsigned char enable); 00495 00496 /* Hardware registers needed by driver. */ 00497 struct gyro_reg_s { 00498 unsigned char who_am_i; 00499 unsigned char rate_div; 00500 unsigned char lpf; 00501 unsigned char prod_id; 00502 unsigned char user_ctrl; 00503 unsigned char fifo_en; 00504 unsigned char gyro_cfg; 00505 unsigned char accel_cfg; 00506 // unsigned char accel_cfg2; 00507 // unsigned char lp_accel_odr; 00508 unsigned char motion_thr; 00509 unsigned char motion_dur; 00510 unsigned char fifo_count_h; 00511 unsigned char fifo_r_w; 00512 unsigned char raw_gyro; 00513 unsigned char raw_accel; 00514 unsigned char temp; 00515 unsigned char int_enable; 00516 unsigned char dmp_int_status; 00517 unsigned char int_status; 00518 // unsigned char accel_intel; 00519 unsigned char pwr_mgmt_1; 00520 unsigned char pwr_mgmt_2; 00521 unsigned char int_pin_cfg; 00522 unsigned char mem_r_w; 00523 unsigned char accel_offs; 00524 unsigned char i2c_mst; 00525 unsigned char bank_sel; 00526 unsigned char mem_start_addr; 00527 unsigned char prgm_start_h; 00528 #if defined AK89xx_SECONDARY 00529 unsigned char s0_addr; 00530 unsigned char s0_reg; 00531 unsigned char s0_ctrl; 00532 unsigned char s1_addr; 00533 unsigned char s1_reg; 00534 unsigned char s1_ctrl; 00535 unsigned char s4_ctrl; 00536 unsigned char s0_do; 00537 unsigned char s1_do; 00538 unsigned char i2c_delay_ctrl; 00539 unsigned char raw_compass; 00540 /* The I2C_MST_VDDIO bit is in this register. */ 00541 unsigned char yg_offs_tc; 00542 #endif 00543 }; 00544 00545 /* Information specific to a particular device. */ 00546 struct hw_s { 00547 unsigned char addr; 00548 unsigned short max_fifo; 00549 unsigned char num_reg; 00550 unsigned short temp_sens; 00551 short temp_offset; 00552 unsigned short bank_size; 00553 #if defined AK89xx_SECONDARY 00554 unsigned short compass_fsr; 00555 #endif 00556 }; 00557 00558 /* When entering motion interrupt mode, the driver keeps track of the 00559 * previous state so that it can be restored at a later time. 00560 * TODO: This is tacky. Fix it. 00561 */ 00562 struct motion_int_cache_s { 00563 unsigned short gyro_fsr; 00564 unsigned char accel_fsr; 00565 unsigned short lpf; 00566 unsigned short sample_rate; 00567 unsigned char sensors_on; 00568 unsigned char fifo_sensors; 00569 unsigned char dmp_on; 00570 }; 00571 00572 /* Cached chip configuration data. 00573 * TODO: A lot of these can be handled with a bitmask. 00574 */ 00575 struct chip_cfg_s { 00576 /* Matches gyro_cfg >> 3 & 0x03 */ 00577 unsigned char gyro_fsr; 00578 /* Matches accel_cfg >> 3 & 0x03 */ 00579 unsigned char accel_fsr; 00580 /* Enabled sensors. Uses same masks as fifo_en, NOT pwr_mgmt_2. */ 00581 unsigned char sensors; 00582 /* Matches config register. */ 00583 unsigned char lpf; 00584 unsigned char clk_src; 00585 /* Sample rate, NOT rate divider. */ 00586 unsigned short sample_rate; 00587 /* Matches fifo_en register. */ 00588 unsigned char fifo_enable; 00589 /* Matches int enable register. */ 00590 unsigned char int_enable; 00591 /* 1 if devices on auxiliary I2C bus appear on the primary. */ 00592 unsigned char bypass_mode; 00593 /* 1 if half-sensitivity. 00594 * NOTE: This doesn't belong here, but everything else in hw_s is const, 00595 * and this allows us to save some precious RAM. 00596 */ 00597 unsigned char accel_half; 00598 /* 1 if device in low-power accel-only mode. */ 00599 unsigned char lp_accel_mode; 00600 /* 1 if interrupts are only triggered on motion events. */ 00601 unsigned char int_motion_only; 00602 struct motion_int_cache_s cache; 00603 /* 1 for active low interrupts. */ 00604 unsigned char active_low_int; 00605 /* 1 for latched interrupts. */ 00606 unsigned char latched_int; 00607 /* 1 if DMP is enabled. */ 00608 unsigned char dmp_on; 00609 /* Ensures that DMP will only be loaded once. */ 00610 unsigned char dmp_loaded; 00611 /* Sampling rate used when DMP is enabled. */ 00612 unsigned short dmp_sample_rate; 00613 #ifdef AK89xx_SECONDARY 00614 /* Compass sample rate. */ 00615 unsigned short compass_sample_rate; 00616 unsigned char compass_addr; 00617 short mag_sens_adj[3]; 00618 #endif 00619 }; 00620 00621 /* Information for self-test. */ 00622 struct test_s { 00623 unsigned long gyro_sens; 00624 unsigned long accel_sens; 00625 unsigned char reg_rate_div; 00626 unsigned char reg_lpf; 00627 unsigned char reg_gyro_fsr; 00628 unsigned char reg_accel_fsr; 00629 unsigned short wait_ms; 00630 unsigned char packet_thresh; 00631 float min_dps; 00632 float max_dps; 00633 float max_gyro_var; 00634 float min_g; 00635 float max_g; 00636 float max_accel_var; 00637 }; 00638 00639 /* Gyro driver state variables. */ 00640 struct gyro_state_s { 00641 const struct gyro_reg_s *reg; 00642 const struct hw_s *hw; 00643 struct chip_cfg_s chip_cfg; 00644 const struct test_s *test; 00645 }; 00646 00647 /* Filter configurations. */ 00648 enum lpf_e { 00649 INV_FILTER_256HZ_NOLPF2 = 0, 00650 INV_FILTER_188HZ, 00651 INV_FILTER_98HZ, 00652 INV_FILTER_42HZ, 00653 INV_FILTER_20HZ, 00654 INV_FILTER_10HZ, 00655 INV_FILTER_5HZ, 00656 INV_FILTER_2100HZ_NOLPF, 00657 NUM_FILTER 00658 }; 00659 00660 /* Full scale ranges. */ 00661 enum gyro_fsr_e { 00662 INV_FSR_250DPS = 0, 00663 INV_FSR_500DPS, 00664 INV_FSR_1000DPS, 00665 INV_FSR_2000DPS, 00666 NUM_GYRO_FSR 00667 }; 00668 00669 /* Full scale ranges. */ 00670 enum accel_fsr_e { 00671 INV_FSR_2G = 0, 00672 INV_FSR_4G, 00673 INV_FSR_8G, 00674 INV_FSR_16G, 00675 NUM_ACCEL_FSR 00676 }; 00677 00678 /* Clock sources. */ 00679 enum clock_sel_e { 00680 INV_CLK_INTERNAL = 0, 00681 INV_CLK_PLL, 00682 NUM_CLK 00683 }; 00684 00685 /* Low-power accel wakeup rates. */ 00686 enum lp_accel_rate_e { 00687 #if defined MPU6050 00688 INV_LPA_1_25HZ, 00689 INV_LPA_5HZ, 00690 INV_LPA_20HZ, 00691 INV_LPA_40HZ 00692 #elif defined MPU6500 00693 INV_LPA_0_3125HZ, 00694 INV_LPA_0_625HZ, 00695 INV_LPA_1_25HZ, 00696 INV_LPA_2_5HZ, 00697 INV_LPA_5HZ, 00698 INV_LPA_10HZ, 00699 INV_LPA_20HZ, 00700 INV_LPA_40HZ, 00701 INV_LPA_80HZ, 00702 INV_LPA_160HZ, 00703 INV_LPA_320HZ, 00704 INV_LPA_640HZ 00705 #endif 00706 }; 00707 00708 #define BIT_I2C_MST_VDDIO (0x80) 00709 #define BIT_FIFO_EN (0x40) 00710 #define BIT_DMP_EN (0x80) 00711 #define BIT_FIFO_RST (0x04) 00712 #define BIT_DMP_RST (0x08) 00713 #define BIT_FIFO_OVERFLOW (0x10) 00714 #define BIT_DATA_RDY_EN (0x01) 00715 #define BIT_DMP_INT_EN (0x02) 00716 #define BIT_MOT_INT_EN (0x40) 00717 #define BITS_FSR (0x18) 00718 #define BITS_LPF (0x07) 00719 #define BITS_HPF (0x07) 00720 #define BITS_CLK (0x07) 00721 #define BIT_FIFO_SIZE_1024 (0x40) 00722 #define BIT_FIFO_SIZE_2048 (0x80) 00723 #define BIT_FIFO_SIZE_4096 (0xC0) 00724 #define BIT_RESET (0x80) 00725 #define BIT_SLEEP (0x40) 00726 #define BIT_S0_DELAY_EN (0x01) 00727 #define BIT_S2_DELAY_EN (0x04) 00728 #define BITS_SLAVE_LENGTH (0x0F) 00729 #define BIT_SLAVE_BYTE_SW (0x40) 00730 #define BIT_SLAVE_GROUP (0x10) 00731 #define BIT_SLAVE_EN (0x80) 00732 #define BIT_I2C_READ (0x80) 00733 #define BITS_I2C_MASTER_DLY (0x1F) 00734 #define BIT_AUX_IF_EN (0x20) 00735 #define BIT_ACTL (0x80) 00736 #define BIT_LATCH_EN (0x20) 00737 #define BIT_ANY_RD_CLR (0x10) 00738 #define BIT_BYPASS_EN (0x02) 00739 #define BITS_WOM_EN (0xC0) 00740 #define BIT_LPA_CYCLE (0x20) 00741 #define BIT_STBY_XA (0x20) 00742 #define BIT_STBY_YA (0x10) 00743 #define BIT_STBY_ZA (0x08) 00744 #define BIT_STBY_XG (0x04) 00745 #define BIT_STBY_YG (0x02) 00746 #define BIT_STBY_ZG (0x01) 00747 #define BIT_STBY_XYZA (BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA) 00748 #define BIT_STBY_XYZG (BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG) 00749 00750 #if defined AK8975_SECONDARY 00751 #define SUPPORTS_AK89xx_HIGH_SENS (0x00) 00752 #define AK89xx_FSR (9830) 00753 #elif defined AK8963_SECONDARY 00754 #define SUPPORTS_AK89xx_HIGH_SENS (0x10) 00755 #define AK89xx_FSR (4915) 00756 #endif 00757 00758 #ifdef AK89xx_SECONDARY 00759 #define AKM_REG_WHOAMI (0x00) 00760 00761 #define AKM_REG_ST1 (0x02) 00762 #define AKM_REG_HXL (0x03) 00763 #define AKM_REG_ST2 (0x09) 00764 00765 #define AKM_REG_CNTL (0x0A) 00766 #define AKM_REG_ASTC (0x0C) 00767 #define AKM_REG_ASAX (0x10) 00768 #define AKM_REG_ASAY (0x11) 00769 #define AKM_REG_ASAZ (0x12) 00770 00771 #define AKM_DATA_READY (0x01) 00772 #define AKM_DATA_OVERRUN (0x02) 00773 #define AKM_OVERFLOW (0x80) 00774 #define AKM_DATA_ERROR (0x40) 00775 00776 #define AKM_BIT_SELF_TEST (0x40) 00777 00778 #define AKM_POWER_DOWN (0x00 | SUPPORTS_AK89xx_HIGH_SENS) 00779 #define AKM_SINGLE_MEASUREMENT (0x01 | SUPPORTS_AK89xx_HIGH_SENS) 00780 #define AKM_FUSE_ROM_ACCESS (0x0F | SUPPORTS_AK89xx_HIGH_SENS) 00781 #define AKM_MODE_SELF_TEST (0x08 | SUPPORTS_AK89xx_HIGH_SENS) 00782 00783 #define AKM_WHOAMI (0x48) 00784 #endif 00785 00786 #if defined MPU6050 00787 //const struct gyro_reg_s reg = { 00788 // .who_am_i = 0x75, 00789 // .rate_div = 0x19, 00790 // .lpf = 0x1A, 00791 // .prod_id = 0x0C, 00792 // .user_ctrl = 0x6A, 00793 // .fifo_en = 0x23, 00794 // .gyro_cfg = 0x1B, 00795 // .accel_cfg = 0x1C, 00796 // .motion_thr = 0x1F, 00797 // .motion_dur = 0x20, 00798 // .fifo_count_h = 0x72, 00799 // .fifo_r_w = 0x74, 00800 // .raw_gyro = 0x43, 00801 // .raw_accel = 0x3B, 00802 // .temp = 0x41, 00803 // .int_enable = 0x38, 00804 // .dmp_int_status = 0x39, 00805 // .int_status = 0x3A, 00806 // .pwr_mgmt_1 = 0x6B, 00807 // .pwr_mgmt_2 = 0x6C, 00808 // .int_pin_cfg = 0x37, 00809 // .mem_r_w = 0x6F, 00810 // .accel_offs = 0x06, 00811 // .i2c_mst = 0x24, 00812 // .bank_sel = 0x6D, 00813 // .mem_start_addr = 0x6E, 00814 // .prgm_start_h = 0x70 00815 //#ifdef AK89xx_SECONDARY 00816 // ,.raw_compass = 0x49, 00817 // .yg_offs_tc = 0x01, 00818 // .s0_addr = 0x25, 00819 // .s0_reg = 0x26, 00820 // .s0_ctrl = 0x27, 00821 // .s1_addr = 0x28, 00822 // .s1_reg = 0x29, 00823 // .s1_ctrl = 0x2A, 00824 // .s4_ctrl = 0x34, 00825 // .s0_do = 0x63, 00826 // .s1_do = 0x64, 00827 // .i2c_delay_ctrl = 0x67 00828 //#endif 00829 //}; 00830 const struct gyro_reg_s reg = { 00831 0x75, //who_am_i 00832 0x19, //rate_div 00833 0x1A, //lpf 00834 0x0C, //prod_id 00835 0x6A, //user_ctrl 00836 0x23, //fifo_en 00837 0x1B, //gyro_cfg 00838 0x1C, //accel_cfg 00839 0x1F, // motion_thr 00840 0x20, // motion_dur 00841 0x72, // fifo_count_h 00842 0x74, // fifo_r_w 00843 0x43, // raw_gyro 00844 0x3B, // raw_accel 00845 0x41, // temp 00846 0x38, // int_enable 00847 0x39, // dmp_int_status 00848 0x3A, // int_status 00849 0x6B, // pwr_mgmt_1 00850 0x6C, // pwr_mgmt_2 00851 0x37, // int_pin_cfg 00852 0x6F, // mem_r_w 00853 0x06, // accel_offs 00854 0x24, // i2c_mst 00855 0x6D, // bank_sel 00856 0x6E, // mem_start_addr 00857 0x70 // prgm_start_h 00858 }; 00859 00860 //const struct hw_s hw = { 00861 // .addr = 0x68, 00862 // .max_fifo = 1024, 00863 // .num_reg = 118, 00864 // .temp_sens = 340, 00865 // .temp_offset = -521, 00866 // .bank_size = 256 00867 //#if defined AK89xx_SECONDARY 00868 // ,.compass_fsr = AK89xx_FSR 00869 //#endif 00870 //}; 00871 const struct hw_s hw={ 00872 0x68, //addr 00873 1024, //max_fifo 00874 118, //num_reg 00875 340, //temp_sens 00876 -521, //temp_offset 00877 256 //bank_size 00878 }; 00879 00880 //const struct test_s test = { 00881 // .gyro_sens = 32768/250, 00882 // .accel_sens = 32768/16, 00883 // .reg_rate_div = 0, /* 1kHz. */ 00884 // .reg_lpf = 1, /* 188Hz. */ 00885 // .reg_gyro_fsr = 0, /* 250dps. */ 00886 // .reg_accel_fsr = 0x18, /* 16g. */ 00887 // .wait_ms = 50, 00888 // .packet_thresh = 5, /* 5% */ 00889 // .min_dps = 10.f, 00890 // .max_dps = 105.f, 00891 // .max_gyro_var = 0.14f, 00892 // .min_g = 0.3f, 00893 // .max_g = 0.95f, 00894 // .max_accel_var = 0.14f 00895 //}; 00896 const struct test_s test={ 00897 32768/250, //gyro_sens 00898 32768/16, // accel_sens 00899 0, // reg_rate_div 00900 1, // reg_lpf 00901 0, // reg_gyro_fsr 00902 0x18, // reg_accel_fsr 00903 50, // wait_ms 00904 5, // packet_thresh 00905 10.0f, // min_dps 00906 105.0f, // max_dps 00907 0.14f, // max_gyro_var 00908 0.3f, // min_g 00909 0.95f, // max_g 00910 0.14f // max_accel_var 00911 }; 00912 00913 //static struct gyro_state_s st = { 00914 // .reg = ®, 00915 // .hw = &hw, 00916 // .test = &test 00917 //}; 00918 static struct gyro_state_s st={ 00919 ®, 00920 &hw, 00921 {0}, 00922 &test 00923 }; 00924 00925 00926 #elif defined MPU6500 00927 const struct gyro_reg_s reg = { 00928 .who_am_i = 0x75, 00929 .rate_div = 0x19, 00930 .lpf = 0x1A, 00931 .prod_id = 0x0C, 00932 .user_ctrl = 0x6A, 00933 .fifo_en = 0x23, 00934 .gyro_cfg = 0x1B, 00935 .accel_cfg = 0x1C, 00936 .accel_cfg2 = 0x1D, 00937 .lp_accel_odr = 0x1E, 00938 .motion_thr = 0x1F, 00939 .motion_dur = 0x20, 00940 .fifo_count_h = 0x72, 00941 .fifo_r_w = 0x74, 00942 .raw_gyro = 0x43, 00943 .raw_accel = 0x3B, 00944 .temp = 0x41, 00945 .int_enable = 0x38, 00946 .dmp_int_status = 0x39, 00947 .int_status = 0x3A, 00948 .accel_intel = 0x69, 00949 .pwr_mgmt_1 = 0x6B, 00950 .pwr_mgmt_2 = 0x6C, 00951 .int_pin_cfg = 0x37, 00952 .mem_r_w = 0x6F, 00953 .accel_offs = 0x77, 00954 .i2c_mst = 0x24, 00955 .bank_sel = 0x6D, 00956 .mem_start_addr = 0x6E, 00957 .prgm_start_h = 0x70 00958 #ifdef AK89xx_SECONDARY 00959 ,.raw_compass = 0x49, 00960 .s0_addr = 0x25, 00961 .s0_reg = 0x26, 00962 .s0_ctrl = 0x27, 00963 .s1_addr = 0x28, 00964 .s1_reg = 0x29, 00965 .s1_ctrl = 0x2A, 00966 .s4_ctrl = 0x34, 00967 .s0_do = 0x63, 00968 .s1_do = 0x64, 00969 .i2c_delay_ctrl = 0x67 00970 #endif 00971 }; 00972 const struct hw_s hw = { 00973 .addr = 0x68, 00974 .max_fifo = 1024, 00975 .num_reg = 128, 00976 .temp_sens = 321, 00977 .temp_offset = 0, 00978 .bank_size = 256 00979 #if defined AK89xx_SECONDARY 00980 ,.compass_fsr = AK89xx_FSR 00981 #endif 00982 }; 00983 00984 const struct test_s test = { 00985 .gyro_sens = 32768/250, 00986 .accel_sens = 32768/16, 00987 .reg_rate_div = 0, /* 1kHz. */ 00988 .reg_lpf = 1, /* 188Hz. */ 00989 .reg_gyro_fsr = 0, /* 250dps. */ 00990 .reg_accel_fsr = 0x18, /* 16g. */ 00991 .wait_ms = 50, 00992 .packet_thresh = 5, /* 5% */ 00993 .min_dps = 10.f, 00994 .max_dps = 105.f, 00995 .max_gyro_var = 0.14f, 00996 .min_g = 0.3f, 00997 .max_g = 0.95f, 00998 .max_accel_var = 0.14f 00999 }; 01000 01001 static struct gyro_state_s st = { 01002 .reg = ®, 01003 .hw = &hw, 01004 .test = &test 01005 }; 01006 #endif 01007 01008 #define MAX_PACKET_LENGTH (12) 01009 01010 #ifdef AK89xx_SECONDARY 01011 static int setup_compass(void); 01012 #define MAX_COMPASS_SAMPLE_RATE (100) 01013 #endif 01014 01015 /** 01016 * @brief Enable/disable data ready interrupt. 01017 * If the DMP is on, the DMP interrupt is enabled. Otherwise, the data ready 01018 * interrupt is used. 01019 * @param[in] enable 1 to enable interrupt. 01020 * @return 0 if successful. 01021 */ 01022 static int set_int_enable(unsigned char enable) 01023 { 01024 unsigned char tmp; 01025 01026 if (st.chip_cfg.dmp_on) { 01027 if (enable) 01028 tmp = BIT_DMP_INT_EN; 01029 else 01030 tmp = 0x00; 01031 if (i2c_write(st.hw->addr, st.reg->int_enable, 1, &tmp)) 01032 return -1; 01033 st.chip_cfg.int_enable = tmp; 01034 } else { 01035 if (!st.chip_cfg.sensors) 01036 return -1; 01037 if (enable && st.chip_cfg.int_enable) 01038 return 0; 01039 if (enable) 01040 tmp = BIT_DATA_RDY_EN; 01041 else 01042 tmp = 0x00; 01043 if (i2c_write(st.hw->addr, st.reg->int_enable, 1, &tmp)) 01044 return -1; 01045 st.chip_cfg.int_enable = tmp; 01046 } 01047 return 0; 01048 } 01049 01050 /** 01051 * @brief Register dump for testing. 01052 * @return 0 if successful. 01053 */ 01054 int mpu_reg_dump(void) 01055 { 01056 unsigned char ii; 01057 unsigned char data; 01058 01059 for (ii = 0; ii < st.hw->num_reg; ii++) { 01060 if (ii == st.reg->fifo_r_w || ii == st.reg->mem_r_w) 01061 continue; 01062 if (i2c_read(st.hw->addr, ii, 1, &data)) 01063 return -1; 01064 //("%#5x: %#5x\r\n", ii, data); 01065 } 01066 return 0; 01067 } 01068 01069 /** 01070 * @brief Read from a single register. 01071 * NOTE: The memory and FIFO read/write registers cannot be accessed. 01072 * @param[in] reg Register address. 01073 * @param[out] data Register data. 01074 * @return 0 if successful. 01075 */ 01076 int mpu_read_reg(unsigned char reg, unsigned char *data) 01077 { 01078 if (reg == st.reg->fifo_r_w || reg == st.reg->mem_r_w) 01079 return -1; 01080 if (reg >= st.hw->num_reg) 01081 return -1; 01082 return i2c_read(st.hw->addr, reg, 1, data); 01083 } 01084 01085 /** 01086 * @brief Initialize hardware. 01087 * Initial configuration:\n 01088 * Gyro FSR: +/- 2000DPS\n 01089 * Accel FSR +/- 2G\n 01090 * DLPF: 42Hz\n 01091 * FIFO rate: 50Hz\n 01092 * Clock source: Gyro PLL\n 01093 * FIFO: Disabled.\n 01094 * Data ready interrupt: Disabled, active low, unlatched. 01095 * @param[in] int_param Platform-specific parameters to interrupt API. 01096 * @return 0 if successful. 01097 */ 01098 int mpu_init(void) 01099 { 01100 unsigned char data[6], rev; 01101 01102 /* Reset device. */ 01103 data[0] = BIT_RESET; 01104 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 1, data)) 01105 return -1; 01106 delay_ms(100); 01107 01108 /* Wake up chip. */ 01109 data[0] = 0x00; 01110 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 1, data)) 01111 return -1; 01112 01113 #if defined MPU6050 01114 /* Check product revision. */ 01115 if (i2c_read(st.hw->addr, st.reg->accel_offs, 6, data)) 01116 return -1; 01117 rev = ((data[5] & 0x01) << 2) | ((data[3] & 0x01) << 1) | 01118 (data[1] & 0x01); 01119 01120 if (rev) { 01121 /* Congrats, these parts are better. */ 01122 if (rev == 1) 01123 st.chip_cfg.accel_half = 1; 01124 else if (rev == 2) 01125 st.chip_cfg.accel_half = 0; 01126 else { 01127 //("Unsupported software product rev %d.\n", rev); 01128 return -1; 01129 } 01130 } else { 01131 if (i2c_read(st.hw->addr, st.reg->prod_id, 1, data)) 01132 return -1; 01133 rev = data[0] & 0x0F; 01134 if (!rev) { 01135 //("Product ID read as 0 indicates device is either " 01136 //"incompatible or an MPU3050.\n"); 01137 return -1; 01138 } else if (rev == 4) { 01139 //("Half sensitivity part found.\n"); 01140 st.chip_cfg.accel_half = 1; 01141 } else 01142 st.chip_cfg.accel_half = 0; 01143 } 01144 #elif defined MPU6500 01145 #define MPU6500_MEM_REV_ADDR (0x17) 01146 if (mpu_read_mem(MPU6500_MEM_REV_ADDR, 1, &rev)) 01147 return -1; 01148 if (rev == 0x1) 01149 st.chip_cfg.accel_half = 0; 01150 else { 01151 //("Unsupported software product rev %d.\n", rev); 01152 return -1; 01153 } 01154 01155 /* MPU6500 shares 4kB of memory between the DMP and the FIFO. Since the 01156 * first 3kB are needed by the DMP, we'll use the last 1kB for the FIFO. 01157 */ 01158 data[0] = BIT_FIFO_SIZE_1024 | 0x8; 01159 if (i2c_write(st.hw->addr, st.reg->accel_cfg2, 1, data)) 01160 return -1; 01161 #endif 01162 01163 /* Set to invalid values to ensure no I2C writes are skipped. */ 01164 st.chip_cfg.sensors = 0xFF; 01165 st.chip_cfg.gyro_fsr = 0xFF; 01166 st.chip_cfg.accel_fsr = 0xFF; 01167 st.chip_cfg.lpf = 0xFF; 01168 st.chip_cfg.sample_rate = 0xFFFF; 01169 st.chip_cfg.fifo_enable = 0xFF; 01170 st.chip_cfg.bypass_mode = 0xFF; 01171 #ifdef AK89xx_SECONDARY 01172 st.chip_cfg.compass_sample_rate = 0xFFFF; 01173 #endif 01174 /* mpu_set_sensors always preserves this setting. */ 01175 st.chip_cfg.clk_src = INV_CLK_PLL; 01176 /* Handled in next call to mpu_set_bypass. */ 01177 st.chip_cfg.active_low_int = 1; 01178 st.chip_cfg.latched_int = 0; 01179 st.chip_cfg.int_motion_only = 0; 01180 st.chip_cfg.lp_accel_mode = 0; 01181 memset(&st.chip_cfg.cache, 0, sizeof(st.chip_cfg.cache)); 01182 st.chip_cfg.dmp_on = 0; 01183 st.chip_cfg.dmp_loaded = 0; 01184 st.chip_cfg.dmp_sample_rate = 0; 01185 01186 if (mpu_set_gyro_fsr(2000)) 01187 return -1; 01188 if (mpu_set_accel_fsr(2)) 01189 return -1; 01190 if (mpu_set_lpf(42)) 01191 return -1; 01192 if (mpu_set_sample_rate(50)) 01193 return -1; 01194 if (mpu_configure_fifo(0)) 01195 return -1; 01196 01197 // if (int_param) 01198 // reg_int_cb(int_param); 01199 01200 #ifdef AK89xx_SECONDARY 01201 setup_compass(); 01202 if (mpu_set_compass_sample_rate(10)) 01203 return -1; 01204 #else 01205 /* Already disabled by setup_compass. */ 01206 if (mpu_set_bypass(0)) 01207 return -1; 01208 #endif 01209 01210 mpu_set_sensors(0); 01211 return 0; 01212 } 01213 01214 /** 01215 * @brief Enter low-power accel-only mode. 01216 * In low-power accel mode, the chip goes to sleep and only wakes up to sample 01217 * the accelerometer at one of the following frequencies: 01218 * \n MPU6050: 1.25Hz, 5Hz, 20Hz, 40Hz 01219 * \n MPU6500: 1.25Hz, 2.5Hz, 5Hz, 10Hz, 20Hz, 40Hz, 80Hz, 160Hz, 320Hz, 640Hz 01220 * \n If the requested rate is not one listed above, the device will be set to 01221 * the next highest rate. Requesting a rate above the maximum supported 01222 * frequency will result in an error. 01223 * \n To select a fractional wake-up frequency, round down the value passed to 01224 * @e rate. 01225 * @param[in] rate Minimum sampling rate, or zero to disable LP 01226 * accel mode. 01227 * @return 0 if successful. 01228 */ 01229 int mpu_lp_accel_mode(unsigned char rate) 01230 { 01231 unsigned char tmp[2]; 01232 01233 if (rate > 40) 01234 return -1; 01235 01236 if (!rate) { 01237 mpu_set_int_latched(0); 01238 tmp[0] = 0; 01239 tmp[1] = BIT_STBY_XYZG; 01240 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 2, tmp)) 01241 return -1; 01242 st.chip_cfg.lp_accel_mode = 0; 01243 return 0; 01244 } 01245 /* For LP accel, we automatically configure the hardware to produce latched 01246 * interrupts. In LP accel mode, the hardware cycles into sleep mode before 01247 * it gets a chance to deassert the interrupt pin; therefore, we shift this 01248 * responsibility over to the MCU. 01249 * 01250 * Any register read will clear the interrupt. 01251 */ 01252 mpu_set_int_latched(1); 01253 #if defined MPU6050 01254 tmp[0] = BIT_LPA_CYCLE; 01255 if (rate == 1) { 01256 tmp[1] = INV_LPA_1_25HZ; 01257 mpu_set_lpf(5); 01258 } else if (rate <= 5) { 01259 tmp[1] = INV_LPA_5HZ; 01260 mpu_set_lpf(5); 01261 } else if (rate <= 20) { 01262 tmp[1] = INV_LPA_20HZ; 01263 mpu_set_lpf(10); 01264 } else { 01265 tmp[1] = INV_LPA_40HZ; 01266 mpu_set_lpf(20); 01267 } 01268 tmp[1] = (tmp[1] << 6) | BIT_STBY_XYZG; 01269 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 2, tmp)) 01270 return -1; 01271 #elif defined MPU6500 01272 /* Set wake frequency. */ 01273 if (rate == 1) 01274 tmp[0] = INV_LPA_1_25HZ; 01275 else if (rate == 2) 01276 tmp[0] = INV_LPA_2_5HZ; 01277 else if (rate <= 5) 01278 tmp[0] = INV_LPA_5HZ; 01279 else if (rate <= 10) 01280 tmp[0] = INV_LPA_10HZ; 01281 else if (rate <= 20) 01282 tmp[0] = INV_LPA_20HZ; 01283 else if (rate <= 40) 01284 tmp[0] = INV_LPA_40HZ; 01285 else if (rate <= 80) 01286 tmp[0] = INV_LPA_80HZ; 01287 else if (rate <= 160) 01288 tmp[0] = INV_LPA_160HZ; 01289 else if (rate <= 320) 01290 tmp[0] = INV_LPA_320HZ; 01291 else 01292 tmp[0] = INV_LPA_640HZ; 01293 if (i2c_write(st.hw->addr, st.reg->lp_accel_odr, 1, tmp)) 01294 return -1; 01295 tmp[0] = BIT_LPA_CYCLE; 01296 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 1, tmp)) 01297 return -1; 01298 #endif 01299 st.chip_cfg.sensors = INV_XYZ_ACCEL; 01300 st.chip_cfg.clk_src = 0; 01301 st.chip_cfg.lp_accel_mode = 1; 01302 mpu_configure_fifo(0); 01303 01304 return 0; 01305 } 01306 01307 /** 01308 * @brief Read raw gyro data directly from the registers. 01309 * @param[out] data Raw data in hardware units. 01310 * @param[out] timestamp Timestamp in milliseconds. Null if not needed. 01311 * @return 0 if successful. 01312 */ 01313 int mpu_get_gyro_reg(short *data, unsigned long *timestamp) 01314 { 01315 unsigned char tmp[6]; 01316 01317 if (!(st.chip_cfg.sensors & INV_XYZ_GYRO)) 01318 return -1; 01319 01320 if (i2c_read(st.hw->addr, st.reg->raw_gyro, 6, tmp)) 01321 return -1; 01322 data[0] = (tmp[0] << 8) | tmp[1]; 01323 data[1] = (tmp[2] << 8) | tmp[3]; 01324 data[2] = (tmp[4] << 8) | tmp[5]; 01325 if (timestamp) 01326 get_ms(timestamp); 01327 return 0; 01328 } 01329 01330 /** 01331 * @brief Read raw accel data directly from the registers. 01332 * @param[out] data Raw data in hardware units. 01333 * @param[out] timestamp Timestamp in milliseconds. Null if not needed. 01334 * @return 0 if successful. 01335 */ 01336 int mpu_get_accel_reg(short *data, unsigned long *timestamp) 01337 { 01338 unsigned char tmp[6]; 01339 01340 if (!(st.chip_cfg.sensors & INV_XYZ_ACCEL)) 01341 return -1; 01342 01343 if (i2c_read(st.hw->addr, st.reg->raw_accel, 6, tmp)) 01344 return -1; 01345 data[0] = (tmp[0] << 8) | tmp[1]; 01346 data[1] = (tmp[2] << 8) | tmp[3]; 01347 data[2] = (tmp[4] << 8) | tmp[5]; 01348 if (timestamp) 01349 get_ms(timestamp); 01350 return 0; 01351 } 01352 01353 /** 01354 * @brief Read temperature data directly from the registers. 01355 * @param[out] data Data in q16 format. 01356 * @param[out] timestamp Timestamp in milliseconds. Null if not needed. 01357 * @return 0 if successful. 01358 */ 01359 int mpu_get_temperature(long *data, unsigned long *timestamp) 01360 { 01361 unsigned char tmp[2]; 01362 short raw; 01363 01364 if (!(st.chip_cfg.sensors)) 01365 return -1; 01366 01367 if (i2c_read(st.hw->addr, st.reg->temp, 2, tmp)) 01368 return -1; 01369 raw = (tmp[0] << 8) | tmp[1]; 01370 if (timestamp) 01371 get_ms(timestamp); 01372 01373 data[0] = (long)((35 + ((raw - (float)st.hw->temp_offset) / st.hw->temp_sens)) * 65536L); 01374 return 0; 01375 } 01376 01377 /** 01378 * @brief Push biases to the accel bias registers. 01379 * This function expects biases relative to the current sensor output, and 01380 * these biases will be added to the factory-supplied values. 01381 * @param[in] accel_bias New biases. 01382 * @return 0 if successful. 01383 */ 01384 int mpu_set_accel_bias(const long *accel_bias) 01385 { 01386 unsigned char data[6]; 01387 short accel_hw[3]; 01388 short got_accel[3]; 01389 short fg[3]; 01390 01391 if (!accel_bias) 01392 return -1; 01393 if (!accel_bias[0] && !accel_bias[1] && !accel_bias[2]) 01394 return 0; 01395 01396 if (i2c_read(st.hw->addr, 3, 3, data)) 01397 return -1; 01398 fg[0] = ((data[0] >> 4) + 8) & 0xf; 01399 fg[1] = ((data[1] >> 4) + 8) & 0xf; 01400 fg[2] = ((data[2] >> 4) + 8) & 0xf; 01401 01402 accel_hw[0] = (short)(accel_bias[0] * 2 / (64 + fg[0])); 01403 accel_hw[1] = (short)(accel_bias[1] * 2 / (64 + fg[1])); 01404 accel_hw[2] = (short)(accel_bias[2] * 2 / (64 + fg[2])); 01405 01406 if (i2c_read(st.hw->addr, 0x06, 6, data)) 01407 return -1; 01408 01409 got_accel[0] = ((short)data[0] << 8) | data[1]; 01410 got_accel[1] = ((short)data[2] << 8) | data[3]; 01411 got_accel[2] = ((short)data[4] << 8) | data[5]; 01412 01413 accel_hw[0] += got_accel[0]; 01414 accel_hw[1] += got_accel[1]; 01415 accel_hw[2] += got_accel[2]; 01416 01417 data[0] = (accel_hw[0] >> 8) & 0xff; 01418 data[1] = (accel_hw[0]) & 0xff; 01419 data[2] = (accel_hw[1] >> 8) & 0xff; 01420 data[3] = (accel_hw[1]) & 0xff; 01421 data[4] = (accel_hw[2] >> 8) & 0xff; 01422 data[5] = (accel_hw[2]) & 0xff; 01423 01424 if (i2c_write(st.hw->addr, 0x06, 6, data)) 01425 return -1; 01426 return 0; 01427 } 01428 01429 /** 01430 * @brief Reset FIFO read/write pointers. 01431 * @return 0 if successful. 01432 */ 01433 int mpu_reset_fifo(void) 01434 { 01435 unsigned char data; 01436 01437 if (!(st.chip_cfg.sensors)) 01438 return -1; 01439 01440 data = 0; 01441 if (i2c_write(st.hw->addr, st.reg->int_enable, 1, &data)) 01442 return -1; 01443 if (i2c_write(st.hw->addr, st.reg->fifo_en, 1, &data)) 01444 return -1; 01445 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, &data)) 01446 return -1; 01447 01448 if (st.chip_cfg.dmp_on) { 01449 data = BIT_FIFO_RST | BIT_DMP_RST; 01450 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, &data)) 01451 return -1; 01452 delay_ms(50); 01453 data = BIT_DMP_EN | BIT_FIFO_EN; 01454 if (st.chip_cfg.sensors & INV_XYZ_COMPASS) 01455 data |= BIT_AUX_IF_EN; 01456 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, &data)) 01457 return -1; 01458 if (st.chip_cfg.int_enable) 01459 data = BIT_DMP_INT_EN; 01460 else 01461 data = 0; 01462 if (i2c_write(st.hw->addr, st.reg->int_enable, 1, &data)) 01463 return -1; 01464 data = 0; 01465 if (i2c_write(st.hw->addr, st.reg->fifo_en, 1, &data)) 01466 return -1; 01467 } else { 01468 data = BIT_FIFO_RST; 01469 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, &data)) 01470 return -1; 01471 if (st.chip_cfg.bypass_mode || !(st.chip_cfg.sensors & INV_XYZ_COMPASS)) 01472 data = BIT_FIFO_EN; 01473 else 01474 data = BIT_FIFO_EN | BIT_AUX_IF_EN; 01475 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, &data)) 01476 return -1; 01477 delay_ms(50); 01478 if (st.chip_cfg.int_enable) 01479 data = BIT_DATA_RDY_EN; 01480 else 01481 data = 0; 01482 if (i2c_write(st.hw->addr, st.reg->int_enable, 1, &data)) 01483 return -1; 01484 if (i2c_write(st.hw->addr, st.reg->fifo_en, 1, &st.chip_cfg.fifo_enable)) 01485 return -1; 01486 } 01487 return 0; 01488 } 01489 01490 /** 01491 * @brief Get the gyro full-scale range. 01492 * @param[out] fsr Current full-scale range. 01493 * @return 0 if successful. 01494 */ 01495 int mpu_get_gyro_fsr(unsigned short *fsr) 01496 { 01497 switch (st.chip_cfg.gyro_fsr) { 01498 case INV_FSR_250DPS: 01499 fsr[0] = 250; 01500 break; 01501 case INV_FSR_500DPS: 01502 fsr[0] = 500; 01503 break; 01504 case INV_FSR_1000DPS: 01505 fsr[0] = 1000; 01506 break; 01507 case INV_FSR_2000DPS: 01508 fsr[0] = 2000; 01509 break; 01510 default: 01511 fsr[0] = 0; 01512 break; 01513 } 01514 return 0; 01515 } 01516 01517 /** 01518 * @brief Set the gyro full-scale range. 01519 * @param[in] fsr Desired full-scale range. 01520 * @return 0 if successful. 01521 */ 01522 int mpu_set_gyro_fsr(unsigned short fsr) 01523 { 01524 unsigned char data; 01525 01526 if (!(st.chip_cfg.sensors)) 01527 return -1; 01528 01529 switch (fsr) { 01530 case 250: 01531 data = INV_FSR_250DPS << 3; 01532 break; 01533 case 500: 01534 data = INV_FSR_500DPS << 3; 01535 break; 01536 case 1000: 01537 data = INV_FSR_1000DPS << 3; 01538 break; 01539 case 2000: 01540 data = INV_FSR_2000DPS << 3; 01541 break; 01542 default: 01543 return -1; 01544 } 01545 01546 if (st.chip_cfg.gyro_fsr == (data >> 3)) 01547 return 0; 01548 if (i2c_write(st.hw->addr, st.reg->gyro_cfg, 1, &data)) 01549 return -1; 01550 st.chip_cfg.gyro_fsr = data >> 3; 01551 return 0; 01552 } 01553 01554 /** 01555 * @brief Get the accel full-scale range. 01556 * @param[out] fsr Current full-scale range. 01557 * @return 0 if successful. 01558 */ 01559 int mpu_get_accel_fsr(unsigned char *fsr) 01560 { 01561 switch (st.chip_cfg.accel_fsr) { 01562 case INV_FSR_2G: 01563 fsr[0] = 2; 01564 break; 01565 case INV_FSR_4G: 01566 fsr[0] = 4; 01567 break; 01568 case INV_FSR_8G: 01569 fsr[0] = 8; 01570 break; 01571 case INV_FSR_16G: 01572 fsr[0] = 16; 01573 break; 01574 default: 01575 return -1; 01576 } 01577 if (st.chip_cfg.accel_half) 01578 fsr[0] <<= 1; 01579 return 0; 01580 } 01581 01582 /** 01583 * @brief Set the accel full-scale range. 01584 * @param[in] fsr Desired full-scale range. 01585 * @return 0 if successful. 01586 */ 01587 int mpu_set_accel_fsr(unsigned char fsr) 01588 { 01589 unsigned char data; 01590 01591 if (!(st.chip_cfg.sensors)) 01592 return -1; 01593 01594 switch (fsr) { 01595 case 2: 01596 data = INV_FSR_2G << 3; 01597 break; 01598 case 4: 01599 data = INV_FSR_4G << 3; 01600 break; 01601 case 8: 01602 data = INV_FSR_8G << 3; 01603 break; 01604 case 16: 01605 data = INV_FSR_16G << 3; 01606 break; 01607 default: 01608 return -1; 01609 } 01610 01611 if (st.chip_cfg.accel_fsr == (data >> 3)) 01612 return 0; 01613 if (i2c_write(st.hw->addr, st.reg->accel_cfg, 1, &data)) 01614 return -1; 01615 st.chip_cfg.accel_fsr = data >> 3; 01616 return 0; 01617 } 01618 01619 /** 01620 * @brief Get the current DLPF setting. 01621 * @param[out] lpf Current LPF setting. 01622 * 0 if successful. 01623 */ 01624 int mpu_get_lpf(unsigned short *lpf) 01625 { 01626 switch (st.chip_cfg.lpf) { 01627 case INV_FILTER_188HZ: 01628 lpf[0] = 188; 01629 break; 01630 case INV_FILTER_98HZ: 01631 lpf[0] = 98; 01632 break; 01633 case INV_FILTER_42HZ: 01634 lpf[0] = 42; 01635 break; 01636 case INV_FILTER_20HZ: 01637 lpf[0] = 20; 01638 break; 01639 case INV_FILTER_10HZ: 01640 lpf[0] = 10; 01641 break; 01642 case INV_FILTER_5HZ: 01643 lpf[0] = 5; 01644 break; 01645 case INV_FILTER_256HZ_NOLPF2: 01646 case INV_FILTER_2100HZ_NOLPF: 01647 default: 01648 lpf[0] = 0; 01649 break; 01650 } 01651 return 0; 01652 } 01653 01654 /** 01655 * @brief Set digital low pass filter. 01656 * The following LPF settings are supported: 188, 98, 42, 20, 10, 5. 01657 * @param[in] lpf Desired LPF setting. 01658 * @return 0 if successful. 01659 */ 01660 int mpu_set_lpf(unsigned short lpf) 01661 { 01662 unsigned char data; 01663 01664 if (!(st.chip_cfg.sensors)) 01665 return -1; 01666 01667 if (lpf >= 188) 01668 data = INV_FILTER_188HZ; 01669 else if (lpf >= 98) 01670 data = INV_FILTER_98HZ; 01671 else if (lpf >= 42) 01672 data = INV_FILTER_42HZ; 01673 else if (lpf >= 20) 01674 data = INV_FILTER_20HZ; 01675 else if (lpf >= 10) 01676 data = INV_FILTER_10HZ; 01677 else 01678 data = INV_FILTER_5HZ; 01679 01680 if (st.chip_cfg.lpf == data) 01681 return 0; 01682 if (i2c_write(st.hw->addr, st.reg->lpf, 1, &data)) 01683 return -1; 01684 st.chip_cfg.lpf = data; 01685 return 0; 01686 } 01687 01688 /** 01689 * @brief Get sampling rate. 01690 * @param[out] rate Current sampling rate (Hz). 01691 * @return 0 if successful. 01692 */ 01693 int mpu_get_sample_rate(unsigned short *rate) 01694 { 01695 if (st.chip_cfg.dmp_on) 01696 return -1; 01697 else 01698 rate[0] = st.chip_cfg.sample_rate; 01699 return 0; 01700 } 01701 01702 /** 01703 * @brief Set sampling rate. 01704 * Sampling rate must be between 4Hz and 1kHz. 01705 * @param[in] rate Desired sampling rate (Hz). 01706 * @return 0 if successful. 01707 */ 01708 int mpu_set_sample_rate(unsigned short rate) 01709 { 01710 unsigned char data; 01711 01712 if (!(st.chip_cfg.sensors)) 01713 return -1; 01714 01715 if (st.chip_cfg.dmp_on) 01716 return -1; 01717 else { 01718 if (st.chip_cfg.lp_accel_mode) { 01719 if (rate && (rate <= 40)) { 01720 /* Just stay in low-power accel mode. */ 01721 mpu_lp_accel_mode(rate); 01722 return 0; 01723 } 01724 /* Requested rate exceeds the allowed frequencies in LP accel mode, 01725 * switch back to full-power mode. 01726 */ 01727 mpu_lp_accel_mode(0); 01728 } 01729 if (rate < 4) 01730 rate = 4; 01731 else if (rate > 1000) 01732 rate = 1000; 01733 01734 data = 1000 / rate - 1; 01735 if (i2c_write(st.hw->addr, st.reg->rate_div, 1, &data)) 01736 return -1; 01737 01738 st.chip_cfg.sample_rate = 1000 / (1 + data); 01739 01740 #ifdef AK89xx_SECONDARY 01741 mpu_set_compass_sample_rate(min(st.chip_cfg.compass_sample_rate, MAX_COMPASS_SAMPLE_RATE)); 01742 #endif 01743 01744 /* Automatically set LPF to 1/2 sampling rate. */ 01745 mpu_set_lpf(st.chip_cfg.sample_rate >> 1); 01746 return 0; 01747 } 01748 } 01749 01750 /** 01751 * @brief Get compass sampling rate. 01752 * @param[out] rate Current compass sampling rate (Hz). 01753 * @return 0 if successful. 01754 */ 01755 int mpu_get_compass_sample_rate(unsigned short *rate) 01756 { 01757 #ifdef AK89xx_SECONDARY 01758 rate[0] = st.chip_cfg.compass_sample_rate; 01759 return 0; 01760 #else 01761 rate[0] = 0; 01762 return -1; 01763 #endif 01764 } 01765 01766 /** 01767 * @brief Set compass sampling rate. 01768 * The compass on the auxiliary I2C bus is read by the MPU hardware at a 01769 * maximum of 100Hz. The actual rate can be set to a fraction of the gyro 01770 * sampling rate. 01771 * 01772 * \n WARNING: The new rate may be different than what was requested. Call 01773 * mpu_get_compass_sample_rate to check the actual setting. 01774 * @param[in] rate Desired compass sampling rate (Hz). 01775 * @return 0 if successful. 01776 */ 01777 int mpu_set_compass_sample_rate(unsigned short rate) 01778 { 01779 #ifdef AK89xx_SECONDARY 01780 unsigned char div; 01781 if (!rate || rate > st.chip_cfg.sample_rate || rate > MAX_COMPASS_SAMPLE_RATE) 01782 return -1; 01783 01784 div = st.chip_cfg.sample_rate / rate - 1; 01785 if (i2c_write(st.hw->addr, st.reg->s4_ctrl, 1, &div)) 01786 return -1; 01787 st.chip_cfg.compass_sample_rate = st.chip_cfg.sample_rate / (div + 1); 01788 return 0; 01789 #else 01790 return -1; 01791 #endif 01792 } 01793 01794 /** 01795 * @brief Get gyro sensitivity scale factor. 01796 * @param[out] sens Conversion from hardware units to dps. 01797 * @return 0 if successful. 01798 */ 01799 int mpu_get_gyro_sens(float *sens) 01800 { 01801 switch (st.chip_cfg.gyro_fsr) { 01802 case INV_FSR_250DPS: 01803 sens[0] = 131.f; 01804 break; 01805 case INV_FSR_500DPS: 01806 sens[0] = 65.5f; 01807 break; 01808 case INV_FSR_1000DPS: 01809 sens[0] = 32.8f; 01810 break; 01811 case INV_FSR_2000DPS: 01812 sens[0] = 16.4f; 01813 break; 01814 default: 01815 return -1; 01816 } 01817 return 0; 01818 } 01819 01820 /** 01821 * @brief Get accel sensitivity scale factor. 01822 * @param[out] sens Conversion from hardware units to g's. 01823 * @return 0 if successful. 01824 */ 01825 int mpu_get_accel_sens(unsigned short *sens) 01826 { 01827 switch (st.chip_cfg.accel_fsr) { 01828 case INV_FSR_2G: 01829 sens[0] = 16384; 01830 break; 01831 case INV_FSR_4G: 01832 sens[0] = 8092; 01833 break; 01834 case INV_FSR_8G: 01835 sens[0] = 4096; 01836 break; 01837 case INV_FSR_16G: 01838 sens[0] = 2048; 01839 break; 01840 default: 01841 return -1; 01842 } 01843 if (st.chip_cfg.accel_half) 01844 sens[0] >>= 1; 01845 return 0; 01846 } 01847 01848 /** 01849 * @brief Get current FIFO configuration. 01850 * @e sensors can contain a combination of the following flags: 01851 * \n INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO 01852 * \n INV_XYZ_GYRO 01853 * \n INV_XYZ_ACCEL 01854 * @param[out] sensors Mask of sensors in FIFO. 01855 * @return 0 if successful. 01856 */ 01857 int mpu_get_fifo_config(unsigned char *sensors) 01858 { 01859 sensors[0] = st.chip_cfg.fifo_enable; 01860 return 0; 01861 } 01862 01863 /** 01864 * @brief Select which sensors are pushed to FIFO. 01865 * @e sensors can contain a combination of the following flags: 01866 * \n INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO 01867 * \n INV_XYZ_GYRO 01868 * \n INV_XYZ_ACCEL 01869 * @param[in] sensors Mask of sensors to push to FIFO. 01870 * @return 0 if successful. 01871 */ 01872 int mpu_configure_fifo(unsigned char sensors) 01873 { 01874 unsigned char prev; 01875 int result = 0; 01876 01877 /* Compass data isn't going into the FIFO. Stop trying. */ 01878 sensors &= ~INV_XYZ_COMPASS; 01879 01880 if (st.chip_cfg.dmp_on) 01881 return 0; 01882 else { 01883 if (!(st.chip_cfg.sensors)) 01884 return -1; 01885 prev = st.chip_cfg.fifo_enable; 01886 st.chip_cfg.fifo_enable = sensors & st.chip_cfg.sensors; 01887 if (st.chip_cfg.fifo_enable != sensors) 01888 /* You're not getting what you asked for. Some sensors are 01889 * asleep. 01890 */ 01891 result = -1; 01892 else 01893 result = 0; 01894 if (sensors || st.chip_cfg.lp_accel_mode) 01895 set_int_enable(1); 01896 else 01897 set_int_enable(0); 01898 if (sensors) { 01899 if (mpu_reset_fifo()) { 01900 st.chip_cfg.fifo_enable = prev; 01901 return -1; 01902 } 01903 } 01904 } 01905 01906 return result; 01907 } 01908 01909 /** 01910 * @brief Get current power state. 01911 * @param[in] power_on 1 if turned on, 0 if suspended. 01912 * @return 0 if successful. 01913 */ 01914 int mpu_get_power_state(unsigned char *power_on) 01915 { 01916 if (st.chip_cfg.sensors) 01917 power_on[0] = 1; 01918 else 01919 power_on[0] = 0; 01920 return 0; 01921 } 01922 01923 /** 01924 * @brief Turn specific sensors on/off. 01925 * @e sensors can contain a combination of the following flags: 01926 * \n INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO 01927 * \n INV_XYZ_GYRO 01928 * \n INV_XYZ_ACCEL 01929 * \n INV_XYZ_COMPASS 01930 * @param[in] sensors Mask of sensors to wake. 01931 * @return 0 if successful. 01932 */ 01933 int mpu_set_sensors(unsigned char sensors) 01934 { 01935 unsigned char data; 01936 #ifdef AK89xx_SECONDARY 01937 unsigned char user_ctrl; 01938 #endif 01939 01940 if (sensors & INV_XYZ_GYRO) 01941 data = INV_CLK_PLL; 01942 else if (sensors) 01943 data = 0; 01944 else 01945 data = BIT_SLEEP; 01946 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 1, &data)) { 01947 st.chip_cfg.sensors = 0; 01948 return -1; 01949 } 01950 st.chip_cfg.clk_src = data & ~BIT_SLEEP; 01951 01952 data = 0; 01953 if (!(sensors & INV_X_GYRO)) 01954 data |= BIT_STBY_XG; 01955 if (!(sensors & INV_Y_GYRO)) 01956 data |= BIT_STBY_YG; 01957 if (!(sensors & INV_Z_GYRO)) 01958 data |= BIT_STBY_ZG; 01959 if (!(sensors & INV_XYZ_ACCEL)) 01960 data |= BIT_STBY_XYZA; 01961 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_2, 1, &data)) { 01962 st.chip_cfg.sensors = 0; 01963 return -1; 01964 } 01965 01966 if (sensors && (sensors != INV_XYZ_ACCEL)) 01967 /* Latched interrupts only used in LP accel mode. */ 01968 mpu_set_int_latched(0); 01969 01970 #ifdef AK89xx_SECONDARY 01971 #ifdef AK89xx_BYPASS 01972 if (sensors & INV_XYZ_COMPASS) 01973 mpu_set_bypass(1); 01974 else 01975 mpu_set_bypass(0); 01976 #else 01977 if (i2c_read(st.hw->addr, st.reg->user_ctrl, 1, &user_ctrl)) 01978 return -1; 01979 /* Handle AKM power management. */ 01980 if (sensors & INV_XYZ_COMPASS) { 01981 data = AKM_SINGLE_MEASUREMENT; 01982 user_ctrl |= BIT_AUX_IF_EN; 01983 } else { 01984 data = AKM_POWER_DOWN; 01985 user_ctrl &= ~BIT_AUX_IF_EN; 01986 } 01987 if (st.chip_cfg.dmp_on) 01988 user_ctrl |= BIT_DMP_EN; 01989 else 01990 user_ctrl &= ~BIT_DMP_EN; 01991 if (i2c_write(st.hw->addr, st.reg->s1_do, 1, &data)) 01992 return -1; 01993 /* Enable/disable I2C master mode. */ 01994 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, &user_ctrl)) 01995 return -1; 01996 #endif 01997 #endif 01998 01999 st.chip_cfg.sensors = sensors; 02000 st.chip_cfg.lp_accel_mode = 0; 02001 delay_ms(50); 02002 return 0; 02003 } 02004 02005 /** 02006 * @brief Read the MPU interrupt status registers. 02007 * @param[out] status Mask of interrupt bits. 02008 * @return 0 if successful. 02009 */ 02010 int mpu_get_int_status(short *status) 02011 { 02012 unsigned char tmp[2]; 02013 if (!st.chip_cfg.sensors) 02014 return -1; 02015 if (i2c_read(st.hw->addr, st.reg->dmp_int_status, 2, tmp)) 02016 return -1; 02017 status[0] = (tmp[0] << 8) | tmp[1]; 02018 return 0; 02019 } 02020 02021 /** 02022 * @brief Get one packet from the FIFO. 02023 * If @e sensors does not contain a particular sensor, disregard the data 02024 * returned to that pointer. 02025 * \n @e sensors can contain a combination of the following flags: 02026 * \n INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO 02027 * \n INV_XYZ_GYRO 02028 * \n INV_XYZ_ACCEL 02029 * \n If the FIFO has no new data, @e sensors will be zero. 02030 * \n If the FIFO is disabled, @e sensors will be zero and this function will 02031 * return a non-zero error code. 02032 * @param[out] gyro Gyro data in hardware units. 02033 * @param[out] accel Accel data in hardware units. 02034 * @param[out] timestamp Timestamp in milliseconds. 02035 * @param[out] sensors Mask of sensors read from FIFO. 02036 * @param[out] more Number of remaining packets. 02037 * @return 0 if successful. 02038 */ 02039 int mpu_read_fifo(short *gyro, short *accel, unsigned long *timestamp, 02040 unsigned char *sensors, unsigned char *more) 02041 { 02042 /* Assumes maximum packet size is gyro (6) + accel (6). */ 02043 unsigned char data[MAX_PACKET_LENGTH]; 02044 unsigned char packet_size = 0; 02045 unsigned short fifo_count, index = 0; 02046 02047 if (st.chip_cfg.dmp_on) 02048 return -1; 02049 02050 sensors[0] = 0; 02051 if (!st.chip_cfg.sensors) 02052 return -1; 02053 if (!st.chip_cfg.fifo_enable) 02054 return -1; 02055 02056 if (st.chip_cfg.fifo_enable & INV_X_GYRO) 02057 packet_size += 2; 02058 if (st.chip_cfg.fifo_enable & INV_Y_GYRO) 02059 packet_size += 2; 02060 if (st.chip_cfg.fifo_enable & INV_Z_GYRO) 02061 packet_size += 2; 02062 if (st.chip_cfg.fifo_enable & INV_XYZ_ACCEL) 02063 packet_size += 6; 02064 02065 if (i2c_read(st.hw->addr, st.reg->fifo_count_h, 2, data)) 02066 return -1; 02067 fifo_count = (data[0] << 8) | data[1]; 02068 if (fifo_count < packet_size) 02069 return 0; 02070 // //("FIFO count: %hd\n", fifo_count); 02071 if (fifo_count > (st.hw->max_fifo >> 1)) { 02072 /* FIFO is 50% full, better check overflow bit. */ 02073 if (i2c_read(st.hw->addr, st.reg->int_status, 1, data)) 02074 return -1; 02075 if (data[0] & BIT_FIFO_OVERFLOW) { 02076 mpu_reset_fifo(); 02077 return -2; 02078 } 02079 } 02080 get_ms((unsigned long*)timestamp); 02081 02082 if (i2c_read(st.hw->addr, st.reg->fifo_r_w, packet_size, data)) 02083 return -1; 02084 more[0] = fifo_count / packet_size - 1; 02085 sensors[0] = 0; 02086 02087 if ((index != packet_size) && st.chip_cfg.fifo_enable & INV_XYZ_ACCEL) { 02088 accel[0] = (data[index+0] << 8) | data[index+1]; 02089 accel[1] = (data[index+2] << 8) | data[index+3]; 02090 accel[2] = (data[index+4] << 8) | data[index+5]; 02091 sensors[0] |= INV_XYZ_ACCEL; 02092 index += 6; 02093 } 02094 if ((index != packet_size) && st.chip_cfg.fifo_enable & INV_X_GYRO) { 02095 gyro[0] = (data[index+0] << 8) | data[index+1]; 02096 sensors[0] |= INV_X_GYRO; 02097 index += 2; 02098 } 02099 if ((index != packet_size) && st.chip_cfg.fifo_enable & INV_Y_GYRO) { 02100 gyro[1] = (data[index+0] << 8) | data[index+1]; 02101 sensors[0] |= INV_Y_GYRO; 02102 index += 2; 02103 } 02104 if ((index != packet_size) && st.chip_cfg.fifo_enable & INV_Z_GYRO) { 02105 gyro[2] = (data[index+0] << 8) | data[index+1]; 02106 sensors[0] |= INV_Z_GYRO; 02107 index += 2; 02108 } 02109 02110 return 0; 02111 } 02112 02113 /** 02114 * @brief Get one unparsed packet from the FIFO. 02115 * This function should be used if the packet is to be parsed elsewhere. 02116 * @param[in] length Length of one FIFO packet. 02117 * @param[in] data FIFO packet. 02118 * @param[in] more Number of remaining packets. 02119 */ 02120 int mpu_read_fifo_stream(unsigned short length, unsigned char *data, 02121 unsigned char *more) 02122 { 02123 unsigned char tmp[2]; 02124 unsigned short fifo_count; 02125 if (!st.chip_cfg.dmp_on) 02126 return -1; 02127 if (!st.chip_cfg.sensors) 02128 return -1; 02129 02130 if (i2c_read(st.hw->addr, st.reg->fifo_count_h, 2, tmp)) 02131 return -1; 02132 fifo_count = (tmp[0] << 8) | tmp[1]; 02133 if (fifo_count < length) { 02134 more[0] = 0; 02135 return -1; 02136 } 02137 if (fifo_count > (st.hw->max_fifo >> 1)) { 02138 /* FIFO is 50% full, better check overflow bit. */ 02139 if (i2c_read(st.hw->addr, st.reg->int_status, 1, tmp)) 02140 return -1; 02141 if (tmp[0] & BIT_FIFO_OVERFLOW) { 02142 mpu_reset_fifo(); 02143 return -2; 02144 } 02145 } 02146 02147 if (i2c_read(st.hw->addr, st.reg->fifo_r_w, length, data)) 02148 return -1; 02149 more[0] = fifo_count / length - 1; 02150 return 0; 02151 } 02152 02153 /** 02154 * @brief Set device to bypass mode. 02155 * @param[in] bypass_on 1 to enable bypass mode. 02156 * @return 0 if successful. 02157 */ 02158 int mpu_set_bypass(unsigned char bypass_on) 02159 { 02160 unsigned char tmp; 02161 02162 if (st.chip_cfg.bypass_mode == bypass_on) 02163 return 0; 02164 02165 if (bypass_on) { 02166 if (i2c_read(st.hw->addr, st.reg->user_ctrl, 1, &tmp)) 02167 return -1; 02168 tmp &= ~BIT_AUX_IF_EN; 02169 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, &tmp)) 02170 return -1; 02171 delay_ms(3); 02172 tmp = BIT_BYPASS_EN; 02173 if (st.chip_cfg.active_low_int) 02174 tmp |= BIT_ACTL; 02175 if (st.chip_cfg.latched_int) 02176 tmp |= BIT_LATCH_EN | BIT_ANY_RD_CLR; 02177 if (i2c_write(st.hw->addr, st.reg->int_pin_cfg, 1, &tmp)) 02178 return -1; 02179 } else { 02180 /* Enable I2C master mode if compass is being used. */ 02181 if (i2c_read(st.hw->addr, st.reg->user_ctrl, 1, &tmp)) 02182 return -1; 02183 if (st.chip_cfg.sensors & INV_XYZ_COMPASS) 02184 tmp |= BIT_AUX_IF_EN; 02185 else 02186 tmp &= ~BIT_AUX_IF_EN; 02187 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, &tmp)) 02188 return -1; 02189 delay_ms(3); 02190 if (st.chip_cfg.active_low_int) 02191 tmp = BIT_ACTL; 02192 else 02193 tmp = 0; 02194 if (st.chip_cfg.latched_int) 02195 tmp |= BIT_LATCH_EN | BIT_ANY_RD_CLR; 02196 if (i2c_write(st.hw->addr, st.reg->int_pin_cfg, 1, &tmp)) 02197 return -1; 02198 } 02199 st.chip_cfg.bypass_mode = bypass_on; 02200 return 0; 02201 } 02202 02203 /** 02204 * @brief Set interrupt level. 02205 * @param[in] active_low 1 for active low, 0 for active high. 02206 * @return 0 if successful. 02207 */ 02208 int mpu_set_int_level(unsigned char active_low) 02209 { 02210 st.chip_cfg.active_low_int = active_low; 02211 return 0; 02212 } 02213 02214 /** 02215 * @brief Enable latched interrupts. 02216 * Any MPU register will clear the interrupt. 02217 * @param[in] enable 1 to enable, 0 to disable. 02218 * @return 0 if successful. 02219 */ 02220 int mpu_set_int_latched(unsigned char enable) 02221 { 02222 unsigned char tmp; 02223 if (st.chip_cfg.latched_int == enable) 02224 return 0; 02225 02226 if (enable) 02227 tmp = BIT_LATCH_EN | BIT_ANY_RD_CLR; 02228 else 02229 tmp = 0; 02230 if (st.chip_cfg.bypass_mode) 02231 tmp |= BIT_BYPASS_EN; 02232 if (st.chip_cfg.active_low_int) 02233 tmp |= BIT_ACTL; 02234 if (i2c_write(st.hw->addr, st.reg->int_pin_cfg, 1, &tmp)) 02235 return -1; 02236 st.chip_cfg.latched_int = enable; 02237 return 0; 02238 } 02239 02240 #ifdef MPU6050 02241 static int get_accel_prod_shift(float *st_shift) 02242 { 02243 unsigned char tmp[4], shift_code[3], ii; 02244 02245 if (i2c_read(st.hw->addr, 0x0D, 4, tmp)) 02246 return 0x07; 02247 02248 shift_code[0] = ((tmp[0] & 0xE0) >> 3) | ((tmp[3] & 0x30) >> 4); 02249 shift_code[1] = ((tmp[1] & 0xE0) >> 3) | ((tmp[3] & 0x0C) >> 2); 02250 shift_code[2] = ((tmp[2] & 0xE0) >> 3) | (tmp[3] & 0x03); 02251 for (ii = 0; ii < 3; ii++) { 02252 if (!shift_code[ii]) { 02253 st_shift[ii] = 0.f; 02254 continue; 02255 } 02256 /* Equivalent to.. 02257 * st_shift[ii] = 0.34f * powf(0.92f/0.34f, (shift_code[ii]-1) / 30.f) 02258 */ 02259 st_shift[ii] = 0.34f; 02260 while (--shift_code[ii]) 02261 st_shift[ii] *= 1.034f; 02262 } 02263 return 0; 02264 } 02265 02266 static int accel_self_test(long *bias_regular, long *bias_st) 02267 { 02268 int jj, result = 0; 02269 float st_shift[3], st_shift_cust, st_shift_var; 02270 02271 get_accel_prod_shift(st_shift); 02272 for(jj = 0; jj < 3; jj++) { 02273 st_shift_cust = labs(bias_regular[jj] - bias_st[jj]) / 65536.f; 02274 if (st_shift[jj]) { 02275 st_shift_var = st_shift_cust / st_shift[jj] - 1.f; 02276 if (fabs(st_shift_var) > test.max_accel_var) 02277 result |= 1 << jj; 02278 } else if ((st_shift_cust < test.min_g) || 02279 (st_shift_cust > test.max_g)) 02280 result |= 1 << jj; 02281 } 02282 02283 return result; 02284 } 02285 02286 static int gyro_self_test(long *bias_regular, long *bias_st) 02287 { 02288 int jj, result = 0; 02289 unsigned char tmp[3]; 02290 float st_shift, st_shift_cust, st_shift_var; 02291 02292 if (i2c_read(st.hw->addr, 0x0D, 3, tmp)) 02293 return 0x07; 02294 02295 tmp[0] &= 0x1F; 02296 tmp[1] &= 0x1F; 02297 tmp[2] &= 0x1F; 02298 02299 for (jj = 0; jj < 3; jj++) { 02300 st_shift_cust = labs(bias_regular[jj] - bias_st[jj]) / 65536.f; 02301 if (tmp[jj]) { 02302 st_shift = 3275.f / test.gyro_sens; 02303 while (--tmp[jj]) 02304 st_shift *= 1.046f; 02305 st_shift_var = st_shift_cust / st_shift - 1.f; 02306 if (fabs(st_shift_var) > test.max_gyro_var) 02307 result |= 1 << jj; 02308 } else if ((st_shift_cust < test.min_dps) || 02309 (st_shift_cust > test.max_dps)) 02310 result |= 1 << jj; 02311 } 02312 return result; 02313 } 02314 02315 #ifdef AK89xx_SECONDARY 02316 static int compass_self_test(void) 02317 { 02318 unsigned char tmp[6]; 02319 unsigned char tries = 10; 02320 int result = 0x07; 02321 short data; 02322 02323 mpu_set_bypass(1); 02324 02325 tmp[0] = AKM_POWER_DOWN; 02326 if (i2c_write(st.chip_cfg.compass_addr, AKM_REG_CNTL, 1, tmp)) 02327 return 0x07; 02328 tmp[0] = AKM_BIT_SELF_TEST; 02329 if (i2c_write(st.chip_cfg.compass_addr, AKM_REG_ASTC, 1, tmp)) 02330 goto AKM_restore; 02331 tmp[0] = AKM_MODE_SELF_TEST; 02332 if (i2c_write(st.chip_cfg.compass_addr, AKM_REG_CNTL, 1, tmp)) 02333 goto AKM_restore; 02334 02335 do { 02336 delay_ms(10); 02337 if (i2c_read(st.chip_cfg.compass_addr, AKM_REG_ST1, 1, tmp)) 02338 goto AKM_restore; 02339 if (tmp[0] & AKM_DATA_READY) 02340 break; 02341 } while (tries--); 02342 if (!(tmp[0] & AKM_DATA_READY)) 02343 goto AKM_restore; 02344 02345 if (i2c_read(st.chip_cfg.compass_addr, AKM_REG_HXL, 6, tmp)) 02346 goto AKM_restore; 02347 02348 result = 0; 02349 data = (short)(tmp[1] << 8) | tmp[0]; 02350 if ((data > 100) || (data < -100)) 02351 result |= 0x01; 02352 data = (short)(tmp[3] << 8) | tmp[2]; 02353 if ((data > 100) || (data < -100)) 02354 result |= 0x02; 02355 data = (short)(tmp[5] << 8) | tmp[4]; 02356 if ((data > -300) || (data < -1000)) 02357 result |= 0x04; 02358 02359 AKM_restore: 02360 tmp[0] = 0 | SUPPORTS_AK89xx_HIGH_SENS; 02361 i2c_write(st.chip_cfg.compass_addr, AKM_REG_ASTC, 1, tmp); 02362 tmp[0] = SUPPORTS_AK89xx_HIGH_SENS; 02363 i2c_write(st.chip_cfg.compass_addr, AKM_REG_CNTL, 1, tmp); 02364 mpu_set_bypass(0); 02365 return result; 02366 } 02367 #endif 02368 #endif 02369 02370 static int get_st_biases(long *gyro, long *accel, unsigned char hw_test) 02371 { 02372 unsigned char data[MAX_PACKET_LENGTH]; 02373 unsigned char packet_count, ii; 02374 unsigned short fifo_count; 02375 02376 data[0] = 0x01; 02377 data[1] = 0; 02378 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 2, data)) 02379 return -1; 02380 delay_ms(200); 02381 data[0] = 0; 02382 if (i2c_write(st.hw->addr, st.reg->int_enable, 1, data)) 02383 return -1; 02384 if (i2c_write(st.hw->addr, st.reg->fifo_en, 1, data)) 02385 return -1; 02386 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 1, data)) 02387 return -1; 02388 if (i2c_write(st.hw->addr, st.reg->i2c_mst, 1, data)) 02389 return -1; 02390 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, data)) 02391 return -1; 02392 data[0] = BIT_FIFO_RST | BIT_DMP_RST; 02393 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, data)) 02394 return -1; 02395 delay_ms(15); 02396 data[0] = st.test->reg_lpf; 02397 if (i2c_write(st.hw->addr, st.reg->lpf, 1, data)) 02398 return -1; 02399 data[0] = st.test->reg_rate_div; 02400 if (i2c_write(st.hw->addr, st.reg->rate_div, 1, data)) 02401 return -1; 02402 if (hw_test) 02403 data[0] = st.test->reg_gyro_fsr | 0xE0; 02404 else 02405 data[0] = st.test->reg_gyro_fsr; 02406 if (i2c_write(st.hw->addr, st.reg->gyro_cfg, 1, data)) 02407 return -1; 02408 02409 if (hw_test) 02410 data[0] = st.test->reg_accel_fsr | 0xE0; 02411 else 02412 data[0] = test.reg_accel_fsr; 02413 if (i2c_write(st.hw->addr, st.reg->accel_cfg, 1, data)) 02414 return -1; 02415 if (hw_test) 02416 delay_ms(200); 02417 02418 /* Fill FIFO for test.wait_ms milliseconds. */ 02419 data[0] = BIT_FIFO_EN; 02420 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 1, data)) 02421 return -1; 02422 02423 data[0] = INV_XYZ_GYRO | INV_XYZ_ACCEL; 02424 if (i2c_write(st.hw->addr, st.reg->fifo_en, 1, data)) 02425 return -1; 02426 delay_ms(test.wait_ms); 02427 data[0] = 0; 02428 if (i2c_write(st.hw->addr, st.reg->fifo_en, 1, data)) 02429 return -1; 02430 02431 if (i2c_read(st.hw->addr, st.reg->fifo_count_h, 2, data)) 02432 return -1; 02433 02434 fifo_count = (data[0] << 8) | data[1]; 02435 packet_count = fifo_count / MAX_PACKET_LENGTH; 02436 gyro[0] = gyro[1] = gyro[2] = 0; 02437 accel[0] = accel[1] = accel[2] = 0; 02438 02439 for (ii = 0; ii < packet_count; ii++) { 02440 short accel_cur[3], gyro_cur[3]; 02441 if (i2c_read(st.hw->addr, st.reg->fifo_r_w, MAX_PACKET_LENGTH, data)) 02442 return -1; 02443 accel_cur[0] = ((short)data[0] << 8) | data[1]; 02444 accel_cur[1] = ((short)data[2] << 8) | data[3]; 02445 accel_cur[2] = ((short)data[4] << 8) | data[5]; 02446 accel[0] += (long)accel_cur[0]; 02447 accel[1] += (long)accel_cur[1]; 02448 accel[2] += (long)accel_cur[2]; 02449 gyro_cur[0] = (((short)data[6] << 8) | data[7]); 02450 gyro_cur[1] = (((short)data[8] << 8) | data[9]); 02451 gyro_cur[2] = (((short)data[10] << 8) | data[11]); 02452 gyro[0] += (long)gyro_cur[0]; 02453 gyro[1] += (long)gyro_cur[1]; 02454 gyro[2] += (long)gyro_cur[2]; 02455 } 02456 #ifdef EMPL_NO_64BIT 02457 gyro[0] = (long)(((float)gyro[0]*65536.f) / test.gyro_sens / packet_count); 02458 gyro[1] = (long)(((float)gyro[1]*65536.f) / test.gyro_sens / packet_count); 02459 gyro[2] = (long)(((float)gyro[2]*65536.f) / test.gyro_sens / packet_count); 02460 if (has_accel) { 02461 accel[0] = (long)(((float)accel[0]*65536.f) / test.accel_sens / 02462 packet_count); 02463 accel[1] = (long)(((float)accel[1]*65536.f) / test.accel_sens / 02464 packet_count); 02465 accel[2] = (long)(((float)accel[2]*65536.f) / test.accel_sens / 02466 packet_count); 02467 /* Don't remove gravity! */ 02468 accel[2] -= 65536L; 02469 } 02470 #else 02471 gyro[0] = (long)(((long long)gyro[0]<<16) / test.gyro_sens / packet_count); 02472 gyro[1] = (long)(((long long)gyro[1]<<16) / test.gyro_sens / packet_count); 02473 gyro[2] = (long)(((long long)gyro[2]<<16) / test.gyro_sens / packet_count); 02474 accel[0] = (long)(((long long)accel[0]<<16) / test.accel_sens / 02475 packet_count); 02476 accel[1] = (long)(((long long)accel[1]<<16) / test.accel_sens / 02477 packet_count); 02478 accel[2] = (long)(((long long)accel[2]<<16) / test.accel_sens / 02479 packet_count); 02480 /* Don't remove gravity! */ 02481 if (accel[2] > 0L) 02482 accel[2] -= 65536L; 02483 else 02484 accel[2] += 65536L; 02485 #endif 02486 02487 return 0; 02488 } 02489 02490 /** 02491 * @brief Trigger gyro/accel/compass self-test. 02492 * On success/error, the self-test returns a mask representing the sensor(s) 02493 * that failed. For each bit, a one (1) represents a "pass" case; conversely, 02494 * a zero (0) indicates a failure. 02495 * 02496 * \n The mask is defined as follows: 02497 * \n Bit 0: Gyro. 02498 * \n Bit 1: Accel. 02499 * \n Bit 2: Compass. 02500 * 02501 * \n Currently, the hardware self-test is unsupported for MPU6500. However, 02502 * this function can still be used to obtain the accel and gyro biases. 02503 * 02504 * \n This function must be called with the device either face-up or face-down 02505 * (z-axis is parallel to gravity). 02506 * @param[out] gyro Gyro biases in q16 format. 02507 * @param[out] accel Accel biases (if applicable) in q16 format. 02508 * @return Result mask (see above). 02509 */ 02510 int mpu_run_self_test(long *gyro, long *accel) 02511 { 02512 #ifdef MPU6050 02513 const unsigned char tries = 2; 02514 long gyro_st[3], accel_st[3]; 02515 unsigned char accel_result, gyro_result; 02516 #ifdef AK89xx_SECONDARY 02517 unsigned char compass_result; 02518 #endif 02519 int ii; 02520 #endif 02521 int result; 02522 unsigned char accel_fsr, fifo_sensors, sensors_on; 02523 unsigned short gyro_fsr, sample_rate, lpf; 02524 unsigned char dmp_was_on; 02525 02526 if (st.chip_cfg.dmp_on) { 02527 mpu_set_dmp_state(0); 02528 dmp_was_on = 1; 02529 } else 02530 dmp_was_on = 0; 02531 02532 /* Get initial settings. */ 02533 mpu_get_gyro_fsr(&gyro_fsr); 02534 mpu_get_accel_fsr(&accel_fsr); 02535 mpu_get_lpf(&lpf); 02536 mpu_get_sample_rate(&sample_rate); 02537 sensors_on = st.chip_cfg.sensors; 02538 mpu_get_fifo_config(&fifo_sensors); 02539 02540 /* For older chips, the self-test will be different. */ 02541 #if defined MPU6050 02542 for (ii = 0; ii < tries; ii++) 02543 if (!get_st_biases(gyro, accel, 0)) 02544 break; 02545 if (ii == tries) { 02546 /* If we reach this point, we most likely encountered an I2C error. 02547 * We'll just report an error for all three sensors. 02548 */ 02549 result = 0; 02550 goto restore; 02551 } 02552 for (ii = 0; ii < tries; ii++) 02553 if (!get_st_biases(gyro_st, accel_st, 1)) 02554 break; 02555 if (ii == tries) { 02556 /* Again, probably an I2C error. */ 02557 result = 0; 02558 goto restore; 02559 } 02560 accel_result = accel_self_test(accel, accel_st); 02561 gyro_result = gyro_self_test(gyro, gyro_st); 02562 02563 result = 0; 02564 if (!gyro_result) 02565 result |= 0x01; 02566 if (!accel_result) 02567 result |= 0x02; 02568 02569 #ifdef AK89xx_SECONDARY 02570 compass_result = compass_self_test(); 02571 if (!compass_result) 02572 result |= 0x04; 02573 #endif 02574 restore: 02575 #elif defined MPU6500 02576 /* For now, this function will return a "pass" result for all three sensors 02577 * for compatibility with current test applications. 02578 */ 02579 get_st_biases(gyro, accel, 0); 02580 result = 0x7; 02581 #endif 02582 /* Set to invalid values to ensure no I2C writes are skipped. */ 02583 st.chip_cfg.gyro_fsr = 0xFF; 02584 st.chip_cfg.accel_fsr = 0xFF; 02585 st.chip_cfg.lpf = 0xFF; 02586 st.chip_cfg.sample_rate = 0xFFFF; 02587 st.chip_cfg.sensors = 0xFF; 02588 st.chip_cfg.fifo_enable = 0xFF; 02589 st.chip_cfg.clk_src = INV_CLK_PLL; 02590 mpu_set_gyro_fsr(gyro_fsr); 02591 mpu_set_accel_fsr(accel_fsr); 02592 mpu_set_lpf(lpf); 02593 mpu_set_sample_rate(sample_rate); 02594 mpu_set_sensors(sensors_on); 02595 mpu_configure_fifo(fifo_sensors); 02596 02597 if (dmp_was_on) 02598 mpu_set_dmp_state(1); 02599 02600 return result; 02601 } 02602 02603 /** 02604 * @brief Write to the DMP memory. 02605 * This function prevents I2C writes past the bank boundaries. The DMP memory 02606 * is only accessible when the chip is awake. 02607 * @param[in] mem_addr Memory location (bank << 8 | start address) 02608 * @param[in] length Number of bytes to write. 02609 * @param[in] data Bytes to write to memory. 02610 * @return 0 if successful. 02611 */ 02612 int mpu_write_mem(unsigned short mem_addr, unsigned short length, 02613 unsigned char *data) 02614 { 02615 unsigned char tmp[2]; 02616 02617 if (!data) 02618 return -1; 02619 if (!st.chip_cfg.sensors) 02620 return -1; 02621 02622 tmp[0] = (unsigned char)(mem_addr >> 8); 02623 tmp[1] = (unsigned char)(mem_addr & 0xFF); 02624 02625 /* Check bank boundaries. */ 02626 if (tmp[1] + length > st.hw->bank_size) 02627 return -1; 02628 02629 if (i2c_write(st.hw->addr, st.reg->bank_sel, 2, tmp)) 02630 return -1; 02631 if (i2c_write(st.hw->addr, st.reg->mem_r_w, length, data)) 02632 return -1; 02633 return 0; 02634 } 02635 02636 /** 02637 * @brief Read from the DMP memory. 02638 * This function prevents I2C reads past the bank boundaries. The DMP memory 02639 * is only accessible when the chip is awake. 02640 * @param[in] mem_addr Memory location (bank << 8 | start address) 02641 * @param[in] length Number of bytes to read. 02642 * @param[out] data Bytes read from memory. 02643 * @return 0 if successful. 02644 */ 02645 int mpu_read_mem(unsigned short mem_addr, unsigned short length, 02646 unsigned char *data) 02647 { 02648 unsigned char tmp[2]; 02649 02650 if (!data) 02651 return -1; 02652 if (!st.chip_cfg.sensors) 02653 return -1; 02654 02655 tmp[0] = (unsigned char)(mem_addr >> 8); 02656 tmp[1] = (unsigned char)(mem_addr & 0xFF); 02657 02658 /* Check bank boundaries. */ 02659 if (tmp[1] + length > st.hw->bank_size) 02660 return -1; 02661 02662 if (i2c_write(st.hw->addr, st.reg->bank_sel, 2, tmp)) 02663 return -1; 02664 if (i2c_read(st.hw->addr, st.reg->mem_r_w, length, data)) 02665 return -1; 02666 return 0; 02667 } 02668 02669 /** 02670 * @brief Load and verify DMP image. 02671 * @param[in] length Length of DMP image. 02672 * @param[in] firmware DMP code. 02673 * @param[in] start_addr Starting address of DMP code memory. 02674 * @param[in] sample_rate Fixed sampling rate used when DMP is enabled. 02675 * @return 0 if successful. 02676 */ 02677 int mpu_load_firmware(unsigned short length, const unsigned char *firmware, 02678 unsigned short start_addr, unsigned short sample_rate) 02679 { 02680 unsigned short ii; 02681 unsigned short this_write; 02682 /* Must divide evenly into st.hw->bank_size to avoid bank crossings. */ 02683 #define LOAD_CHUNK (16) 02684 unsigned char cur[LOAD_CHUNK], tmp[2]; 02685 02686 if (st.chip_cfg.dmp_loaded) 02687 /* DMP should only be loaded once. */ 02688 return -1; 02689 02690 if (!firmware) 02691 return -1; 02692 for (ii = 0; ii < length; ii += this_write) { 02693 this_write = min(LOAD_CHUNK, length - ii); 02694 if (mpu_write_mem(ii, this_write, (unsigned char*)&firmware[ii])) 02695 return -1; 02696 if (mpu_read_mem(ii, this_write, cur)) 02697 return -1; 02698 if (memcmp(firmware+ii, cur, this_write)) 02699 return -2; 02700 } 02701 02702 /* Set program start address. */ 02703 tmp[0] = start_addr >> 8; 02704 tmp[1] = start_addr & 0xFF; 02705 if (i2c_write(st.hw->addr, st.reg->prgm_start_h, 2, tmp)) 02706 return -1; 02707 02708 st.chip_cfg.dmp_loaded = 1; 02709 st.chip_cfg.dmp_sample_rate = sample_rate; 02710 return 0; 02711 } 02712 02713 /** 02714 * @brief Enable/disable DMP support. 02715 * @param[in] enable 1 to turn on the DMP. 02716 * @return 0 if successful. 02717 */ 02718 int mpu_set_dmp_state(unsigned char enable) 02719 { 02720 unsigned char tmp; 02721 if (st.chip_cfg.dmp_on == enable) 02722 return 0; 02723 02724 if (enable) { 02725 if (!st.chip_cfg.dmp_loaded) 02726 return -1; 02727 /* Disable data ready interrupt. */ 02728 set_int_enable(0); 02729 /* Disable bypass mode. */ 02730 mpu_set_bypass(0); 02731 /* Keep constant sample rate, FIFO rate controlled by DMP. */ 02732 mpu_set_sample_rate(st.chip_cfg.dmp_sample_rate); 02733 /* Remove FIFO elements. */ 02734 tmp = 0; 02735 i2c_write(st.hw->addr, 0x23, 1, &tmp); 02736 st.chip_cfg.dmp_on = 1; 02737 /* Enable DMP interrupt. */ 02738 set_int_enable(1); 02739 mpu_reset_fifo(); 02740 } else { 02741 /* Disable DMP interrupt. */ 02742 set_int_enable(0); 02743 /* Restore FIFO settings. */ 02744 tmp = st.chip_cfg.fifo_enable; 02745 i2c_write(st.hw->addr, 0x23, 1, &tmp); 02746 st.chip_cfg.dmp_on = 0; 02747 mpu_reset_fifo(); 02748 } 02749 return 0; 02750 } 02751 02752 /** 02753 * @brief Get DMP state. 02754 * @param[out] enabled 1 if enabled. 02755 * @return 0 if successful. 02756 */ 02757 int mpu_get_dmp_state(unsigned char *enabled) 02758 { 02759 enabled[0] = st.chip_cfg.dmp_on; 02760 return 0; 02761 } 02762 02763 02764 /* This initialization is similar to the one in ak8975.c. */ 02765 int setup_compass(void) 02766 { 02767 #ifdef AK89xx_SECONDARY 02768 unsigned char data[4], akm_addr; 02769 02770 mpu_set_bypass(1); 02771 02772 /* Find compass. Possible addresses range from 0x0C to 0x0F. */ 02773 for (akm_addr = 0x0C; akm_addr <= 0x0F; akm_addr++) { 02774 int result; 02775 result = i2c_read(akm_addr, AKM_REG_WHOAMI, 1, data); 02776 if (!result && (data[0] == AKM_WHOAMI)) 02777 break; 02778 } 02779 02780 if (akm_addr > 0x0F) { 02781 /* TODO: Handle this case in all compass-related functions. */ 02782 //("Compass not found.\n"); 02783 return -1; 02784 } 02785 02786 st.chip_cfg.compass_addr = akm_addr; 02787 02788 data[0] = AKM_POWER_DOWN; 02789 if (i2c_write(st.chip_cfg.compass_addr, AKM_REG_CNTL, 1, data)) 02790 return -1; 02791 delay_ms(1); 02792 02793 data[0] = AKM_FUSE_ROM_ACCESS; 02794 if (i2c_write(st.chip_cfg.compass_addr, AKM_REG_CNTL, 1, data)) 02795 return -1; 02796 delay_ms(1); 02797 02798 /* Get sensitivity adjustment data from fuse ROM. */ 02799 if (i2c_read(st.chip_cfg.compass_addr, AKM_REG_ASAX, 3, data)) 02800 return -1; 02801 st.chip_cfg.mag_sens_adj[0] = (long)data[0] + 128; 02802 st.chip_cfg.mag_sens_adj[1] = (long)data[1] + 128; 02803 st.chip_cfg.mag_sens_adj[2] = (long)data[2] + 128; 02804 02805 data[0] = AKM_POWER_DOWN; 02806 if (i2c_write(st.chip_cfg.compass_addr, AKM_REG_CNTL, 1, data)) 02807 return -1; 02808 delay_ms(1); 02809 02810 mpu_set_bypass(0); 02811 02812 /* Set up master mode, master clock, and ES bit. */ 02813 data[0] = 0x40; 02814 if (i2c_write(st.hw->addr, st.reg->i2c_mst, 1, data)) 02815 return -1; 02816 02817 /* Slave 0 reads from AKM data registers. */ 02818 data[0] = BIT_I2C_READ | st.chip_cfg.compass_addr; 02819 if (i2c_write(st.hw->addr, st.reg->s0_addr, 1, data)) 02820 return -1; 02821 02822 /* Compass reads start at this register. */ 02823 data[0] = AKM_REG_ST1; 02824 if (i2c_write(st.hw->addr, st.reg->s0_reg, 1, data)) 02825 return -1; 02826 02827 /* Enable slave 0, 8-byte reads. */ 02828 data[0] = BIT_SLAVE_EN | 8; 02829 if (i2c_write(st.hw->addr, st.reg->s0_ctrl, 1, data)) 02830 return -1; 02831 02832 /* Slave 1 changes AKM measurement mode. */ 02833 data[0] = st.chip_cfg.compass_addr; 02834 if (i2c_write(st.hw->addr, st.reg->s1_addr, 1, data)) 02835 return -1; 02836 02837 /* AKM measurement mode register. */ 02838 data[0] = AKM_REG_CNTL; 02839 if (i2c_write(st.hw->addr, st.reg->s1_reg, 1, data)) 02840 return -1; 02841 02842 /* Enable slave 1, 1-byte writes. */ 02843 data[0] = BIT_SLAVE_EN | 1; 02844 if (i2c_write(st.hw->addr, st.reg->s1_ctrl, 1, data)) 02845 return -1; 02846 02847 /* Set slave 1 data. */ 02848 data[0] = AKM_SINGLE_MEASUREMENT; 02849 if (i2c_write(st.hw->addr, st.reg->s1_do, 1, data)) 02850 return -1; 02851 02852 /* Trigger slave 0 and slave 1 actions at each sample. */ 02853 data[0] = 0x03; 02854 if (i2c_write(st.hw->addr, st.reg->i2c_delay_ctrl, 1, data)) 02855 return -1; 02856 02857 #ifdef MPU9150 02858 /* For the MPU9150, the auxiliary I2C bus needs to be set to VDD. */ 02859 data[0] = BIT_I2C_MST_VDDIO; 02860 if (i2c_write(st.hw->addr, st.reg->yg_offs_tc, 1, data)) 02861 return -1; 02862 #endif 02863 02864 return 0; 02865 #else 02866 return -1; 02867 #endif 02868 } 02869 02870 /** 02871 * @brief Read raw compass data. 02872 * @param[out] data Raw data in hardware units. 02873 * @param[out] timestamp Timestamp in milliseconds. Null if not needed. 02874 * @return 0 if successful. 02875 */ 02876 int mpu_get_compass_reg(short *data, unsigned long *timestamp) 02877 { 02878 #ifdef AK89xx_SECONDARY 02879 unsigned char tmp[9]; 02880 02881 if (!(st.chip_cfg.sensors & INV_XYZ_COMPASS)) 02882 return -1; 02883 02884 #ifdef AK89xx_BYPASS 02885 if (i2c_read(st.chip_cfg.compass_addr, AKM_REG_ST1, 8, tmp)) 02886 return -1; 02887 tmp[8] = AKM_SINGLE_MEASUREMENT; 02888 if (i2c_write(st.chip_cfg.compass_addr, AKM_REG_CNTL, 1, tmp+8)) 02889 return -1; 02890 #else 02891 if (i2c_read(st.hw->addr, st.reg->raw_compass, 8, tmp)) 02892 return -1; 02893 #endif 02894 02895 #if defined AK8975_SECONDARY 02896 /* AK8975 doesn't have the overrun error bit. */ 02897 if (!(tmp[0] & AKM_DATA_READY)) 02898 return -2; 02899 if ((tmp[7] & AKM_OVERFLOW) || (tmp[7] & AKM_DATA_ERROR)) 02900 return -3; 02901 #elif defined AK8963_SECONDARY 02902 /* AK8963 doesn't have the data read error bit. */ 02903 if (!(tmp[0] & AKM_DATA_READY) || (tmp[0] & AKM_DATA_OVERRUN)) 02904 return -2; 02905 if (tmp[7] & AKM_OVERFLOW) 02906 return -3; 02907 #endif 02908 data[0] = (tmp[2] << 8) | tmp[1]; 02909 data[1] = (tmp[4] << 8) | tmp[3]; 02910 data[2] = (tmp[6] << 8) | tmp[5]; 02911 02912 data[0] = ((long)data[0] * st.chip_cfg.mag_sens_adj[0]) >> 8; 02913 data[1] = ((long)data[1] * st.chip_cfg.mag_sens_adj[1]) >> 8; 02914 data[2] = ((long)data[2] * st.chip_cfg.mag_sens_adj[2]) >> 8; 02915 02916 if (timestamp) 02917 get_ms(timestamp); 02918 return 0; 02919 #else 02920 return -1; 02921 #endif 02922 } 02923 02924 /** 02925 * @brief Get the compass full-scale range. 02926 * @param[out] fsr Current full-scale range. 02927 * @return 0 if successful. 02928 */ 02929 int mpu_get_compass_fsr(unsigned short *fsr) 02930 { 02931 #ifdef AK89xx_SECONDARY 02932 fsr[0] = st.hw->compass_fsr; 02933 return 0; 02934 #else 02935 return -1; 02936 #endif 02937 } 02938 02939 /** 02940 * @brief Enters LP accel motion interrupt mode. 02941 * The behavior of this feature is very different between the MPU6050 and the 02942 * MPU6500. Each chip's version of this feature is explained below. 02943 * 02944 * \n MPU6050: 02945 * \n When this mode is first enabled, the hardware captures a single accel 02946 * sample, and subsequent samples are compared with this one to determine if 02947 * the device is in motion. Therefore, whenever this "locked" sample needs to 02948 * be changed, this function must be called again. 02949 * 02950 * \n The hardware motion threshold can be between 32mg and 8160mg in 32mg 02951 * increments. 02952 * 02953 * \n Low-power accel mode supports the following frequencies: 02954 * \n 1.25Hz, 5Hz, 20Hz, 40Hz 02955 * 02956 * \n MPU6500: 02957 * \n Unlike the MPU6050 version, the hardware does not "lock in" a reference 02958 * sample. The hardware monitors the accel data and detects any large change 02959 * over a short period of time. 02960 * 02961 * \n The hardware motion threshold can be between 4mg and 1020mg in 4mg 02962 * increments. 02963 * 02964 * \n MPU6500 Low-power accel mode supports the following frequencies: 02965 * \n 1.25Hz, 2.5Hz, 5Hz, 10Hz, 20Hz, 40Hz, 80Hz, 160Hz, 320Hz, 640Hz 02966 * 02967 * \n\n NOTES: 02968 * \n The driver will round down @e thresh to the nearest supported value if 02969 * an unsupported threshold is selected. 02970 * \n To select a fractional wake-up frequency, round down the value passed to 02971 * @e lpa_freq. 02972 * \n The MPU6500 does not support a delay parameter. If this function is used 02973 * for the MPU6500, the value passed to @e time will be ignored. 02974 * \n To disable this mode, set @e lpa_freq to zero. The driver will restore 02975 * the previous configuration. 02976 * 02977 * @param[in] thresh Motion threshold in mg. 02978 * @param[in] time Duration in milliseconds that the accel data must 02979 * exceed @e thresh before motion is reported. 02980 * @param[in] lpa_freq Minimum sampling rate, or zero to disable. 02981 * @return 0 if successful. 02982 */ 02983 int mpu_lp_motion_interrupt(unsigned short thresh, unsigned char time, 02984 unsigned char lpa_freq) 02985 { 02986 unsigned char data[3]; 02987 02988 if (lpa_freq) { 02989 unsigned char thresh_hw; 02990 02991 #if defined MPU6050 02992 /* TODO: Make these const/#defines. */ 02993 /* 1LSb = 32mg. */ 02994 if (thresh > 8160) 02995 thresh_hw = 255; 02996 else if (thresh < 32) 02997 thresh_hw = 1; 02998 else 02999 thresh_hw = thresh >> 5; 03000 #elif defined MPU6500 03001 /* 1LSb = 4mg. */ 03002 if (thresh > 1020) 03003 thresh_hw = 255; 03004 else if (thresh < 4) 03005 thresh_hw = 1; 03006 else 03007 thresh_hw = thresh >> 2; 03008 #endif 03009 03010 if (!time) 03011 /* Minimum duration must be 1ms. */ 03012 time = 1; 03013 03014 #if defined MPU6050 03015 if (lpa_freq > 40) 03016 #elif defined MPU6500 03017 if (lpa_freq > 640) 03018 #endif 03019 /* At this point, the chip has not been re-configured, so the 03020 * function can safely exit. 03021 */ 03022 return -1; 03023 03024 if (!st.chip_cfg.int_motion_only) { 03025 /* Store current settings for later. */ 03026 if (st.chip_cfg.dmp_on) { 03027 mpu_set_dmp_state(0); 03028 st.chip_cfg.cache.dmp_on = 1; 03029 } else 03030 st.chip_cfg.cache.dmp_on = 0; 03031 mpu_get_gyro_fsr(&st.chip_cfg.cache.gyro_fsr); 03032 mpu_get_accel_fsr(&st.chip_cfg.cache.accel_fsr); 03033 mpu_get_lpf(&st.chip_cfg.cache.lpf); 03034 mpu_get_sample_rate(&st.chip_cfg.cache.sample_rate); 03035 st.chip_cfg.cache.sensors_on = st.chip_cfg.sensors; 03036 mpu_get_fifo_config(&st.chip_cfg.cache.fifo_sensors); 03037 } 03038 03039 #ifdef MPU6050 03040 /* Disable hardware interrupts for now. */ 03041 set_int_enable(0); 03042 03043 /* Enter full-power accel-only mode. */ 03044 mpu_lp_accel_mode(0); 03045 03046 /* Override current LPF (and HPF) settings to obtain a valid accel 03047 * reading. 03048 */ 03049 data[0] = INV_FILTER_256HZ_NOLPF2; 03050 if (i2c_write(st.hw->addr, st.reg->lpf, 1, data)) 03051 return -1; 03052 03053 /* NOTE: Digital high pass filter should be configured here. Since this 03054 * driver doesn't modify those bits anywhere, they should already be 03055 * cleared by default. 03056 */ 03057 03058 /* Configure the device to send motion interrupts. */ 03059 /* Enable motion interrupt. */ 03060 data[0] = BIT_MOT_INT_EN; 03061 if (i2c_write(st.hw->addr, st.reg->int_enable, 1, data)) 03062 goto lp_int_restore; 03063 03064 /* Set motion interrupt parameters. */ 03065 data[0] = thresh_hw; 03066 data[1] = time; 03067 if (i2c_write(st.hw->addr, st.reg->motion_thr, 2, data)) 03068 goto lp_int_restore; 03069 03070 /* Force hardware to "lock" current accel sample. */ 03071 delay_ms(5); 03072 data[0] = (st.chip_cfg.accel_fsr << 3) | BITS_HPF; 03073 if (i2c_write(st.hw->addr, st.reg->accel_cfg, 1, data)) 03074 goto lp_int_restore; 03075 03076 /* Set up LP accel mode. */ 03077 data[0] = BIT_LPA_CYCLE; 03078 if (lpa_freq == 1) 03079 data[1] = INV_LPA_1_25HZ; 03080 else if (lpa_freq <= 5) 03081 data[1] = INV_LPA_5HZ; 03082 else if (lpa_freq <= 20) 03083 data[1] = INV_LPA_20HZ; 03084 else 03085 data[1] = INV_LPA_40HZ; 03086 data[1] = (data[1] << 6) | BIT_STBY_XYZG; 03087 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 2, data)) 03088 goto lp_int_restore; 03089 03090 st.chip_cfg.int_motion_only = 1; 03091 return 0; 03092 #elif defined MPU6500 03093 /* Disable hardware interrupts. */ 03094 set_int_enable(0); 03095 03096 /* Enter full-power accel-only mode, no FIFO/DMP. */ 03097 data[0] = 0; 03098 data[1] = 0; 03099 data[2] = BIT_STBY_XYZG; 03100 if (i2c_write(st.hw->addr, st.reg->user_ctrl, 3, data)) 03101 goto lp_int_restore; 03102 03103 /* Set motion threshold. */ 03104 data[0] = thresh_hw; 03105 if (i2c_write(st.hw->addr, st.reg->motion_thr, 1, data)) 03106 goto lp_int_restore; 03107 03108 /* Set wake frequency. */ 03109 if (lpa_freq == 1) 03110 data[0] = INV_LPA_1_25HZ; 03111 else if (lpa_freq == 2) 03112 data[0] = INV_LPA_2_5HZ; 03113 else if (lpa_freq <= 5) 03114 data[0] = INV_LPA_5HZ; 03115 else if (lpa_freq <= 10) 03116 data[0] = INV_LPA_10HZ; 03117 else if (lpa_freq <= 20) 03118 data[0] = INV_LPA_20HZ; 03119 else if (lpa_freq <= 40) 03120 data[0] = INV_LPA_40HZ; 03121 else if (lpa_freq <= 80) 03122 data[0] = INV_LPA_80HZ; 03123 else if (lpa_freq <= 160) 03124 data[0] = INV_LPA_160HZ; 03125 else if (lpa_freq <= 320) 03126 data[0] = INV_LPA_320HZ; 03127 else 03128 data[0] = INV_LPA_640HZ; 03129 if (i2c_write(st.hw->addr, st.reg->lp_accel_odr, 1, data)) 03130 goto lp_int_restore; 03131 03132 /* Enable motion interrupt (MPU6500 version). */ 03133 data[0] = BITS_WOM_EN; 03134 if (i2c_write(st.hw->addr, st.reg->accel_intel, 1, data)) 03135 goto lp_int_restore; 03136 03137 /* Enable cycle mode. */ 03138 data[0] = BIT_LPA_CYCLE; 03139 if (i2c_write(st.hw->addr, st.reg->pwr_mgmt_1, 1, data)) 03140 goto lp_int_restore; 03141 03142 /* Enable interrupt. */ 03143 data[0] = BIT_MOT_INT_EN; 03144 if (i2c_write(st.hw->addr, st.reg->int_enable, 1, data)) 03145 goto lp_int_restore; 03146 03147 st.chip_cfg.int_motion_only = 1; 03148 return 0; 03149 #endif 03150 } else { 03151 /* Don't "restore" the previous state if no state has been saved. */ 03152 int ii; 03153 char *cache_ptr = (char*)&st.chip_cfg.cache; 03154 for (ii = 0; ii < sizeof(st.chip_cfg.cache); ii++) { 03155 if (cache_ptr[ii] != 0) 03156 goto lp_int_restore; 03157 } 03158 /* If we reach this point, motion interrupt mode hasn't been used yet. */ 03159 return -1; 03160 } 03161 lp_int_restore: 03162 /* Set to invalid values to ensure no I2C writes are skipped. */ 03163 st.chip_cfg.gyro_fsr = 0xFF; 03164 st.chip_cfg.accel_fsr = 0xFF; 03165 st.chip_cfg.lpf = 0xFF; 03166 st.chip_cfg.sample_rate = 0xFFFF; 03167 st.chip_cfg.sensors = 0xFF; 03168 st.chip_cfg.fifo_enable = 0xFF; 03169 st.chip_cfg.clk_src = INV_CLK_PLL; 03170 mpu_set_sensors(st.chip_cfg.cache.sensors_on); 03171 mpu_set_gyro_fsr(st.chip_cfg.cache.gyro_fsr); 03172 mpu_set_accel_fsr(st.chip_cfg.cache.accel_fsr); 03173 mpu_set_lpf(st.chip_cfg.cache.lpf); 03174 mpu_set_sample_rate(st.chip_cfg.cache.sample_rate); 03175 mpu_configure_fifo(st.chip_cfg.cache.fifo_sensors); 03176 03177 if (st.chip_cfg.cache.dmp_on) 03178 mpu_set_dmp_state(1); 03179 03180 #ifdef MPU6500 03181 /* Disable motion interrupt (MPU6500 version). */ 03182 data[0] = 0; 03183 if (i2c_write(st.hw->addr, st.reg->accel_intel, 1, data)) 03184 goto lp_int_restore; 03185 #endif 03186 03187 st.chip_cfg.int_motion_only = 0; 03188 return 0; 03189 } 03190 ////////////////////////////////////////////////////////////////////////////////// 03191 //添加的代码部分 03192 ////////////////////////////////////////////////////////////////////////////////// 03193 //本程序只供学习使用,未经作者许可,不得用于其它任何用途 03194 //ALIENTEK STM32开发板 03195 //MPU6050 DMP 驱动代码 03196 //正点原子@ALIENTEK 03197 //技术论坛:www.openedv.com 03198 //创建日期:2015/1/17 03199 //版本:V1.0 03200 //版权所有,盗版必究。 03201 //Copyright(C) 广州市星翼电子科技有限公司 2009-2019 03202 //All rights reserved 03203 ////////////////////////////////////////////////////////////////////////////////// 03204 03205 //q30格式,long转float时的除数. 03206 #define q30 1073741824.0f 03207 03208 //陀螺仪方向设置 03209 static signed char gyro_orientation[9] = { 1, 0, 0, 03210 0, 1, 0, 03211 0, 0, 1}; 03212 //MPU6050自测试 03213 //返回值:0,正常 03214 // 其他,失败 03215 unsigned char run_self_test(void) 03216 { 03217 int result; 03218 //char test_packet[4] = {0}; 03219 long gyro[3], accel[3]; 03220 result = mpu_run_self_test(gyro, accel); 03221 if (result == 0x3) 03222 { 03223 /* Test passed. We can trust the gyro data here, so let's push it down 03224 * to the DMP. 03225 */ 03226 float sens; 03227 unsigned short accel_sens; 03228 mpu_get_gyro_sens(&sens); 03229 gyro[0] = (long)(gyro[0] * sens); 03230 gyro[1] = (long)(gyro[1] * sens); 03231 gyro[2] = (long)(gyro[2] * sens); 03232 dmp_set_gyro_bias(gyro); 03233 mpu_get_accel_sens(&accel_sens); 03234 accel[0] *= accel_sens; 03235 accel[1] *= accel_sens; 03236 accel[2] *= accel_sens; 03237 dmp_set_accel_bias(accel); 03238 return 0; 03239 }else return 1; 03240 } 03241 //陀螺仪方向控制 03242 unsigned short inv_orientation_matrix_to_scalar( 03243 const signed char *mtx) 03244 { 03245 unsigned short scalar; 03246 /* 03247 XYZ 010_001_000 Identity Matrix 03248 XZY 001_010_000 03249 YXZ 010_000_001 03250 YZX 000_010_001 03251 ZXY 001_000_010 03252 ZYX 000_001_010 03253 */ 03254 03255 scalar = inv_row_2_scale(mtx); 03256 scalar |= inv_row_2_scale(mtx + 3) << 3; 03257 scalar |= inv_row_2_scale(mtx + 6) << 6; 03258 03259 03260 return scalar; 03261 } 03262 //方向转换 03263 unsigned short inv_row_2_scale(const signed char *row) 03264 { 03265 unsigned short b; 03266 03267 if (row[0] > 0) 03268 b = 0; 03269 else if (row[0] < 0) 03270 b = 4; 03271 else if (row[1] > 0) 03272 b = 1; 03273 else if (row[1] < 0) 03274 b = 5; 03275 else if (row[2] > 0) 03276 b = 2; 03277 else if (row[2] < 0) 03278 b = 6; 03279 else 03280 b = 7; // error 03281 return b; 03282 } 03283 //空函数,未用到. 03284 void mget_ms(unsigned long *time) 03285 { 03286 03287 } 03288 //mpu6050,dmp初始化 03289 //返回值:0,正常 03290 // 其他,失败 03291 unsigned char mpu_dmp_init(void) 03292 { 03293 unsigned char res=0; 03294 MPU_IIC_Init(); //初始化IIC总线 03295 if(mpu_init()==0) //初始化MPU6050 03296 { 03297 res=mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL);//设置所需要的传感器 03298 if(res)return 1; 03299 res=mpu_configure_fifo(INV_XYZ_GYRO|INV_XYZ_ACCEL);//设置FIFO 03300 if(res)return 2; 03301 res=mpu_set_sample_rate(DEFAULT_MPU_HZ); //设置采样率 03302 if(res)return 3; 03303 res=dmp_load_motion_driver_firmware(); //加载dmp固件 03304 if(res)return 4; 03305 res=dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation));//设置陀螺仪方向 03306 if(res)return 5; 03307 res=dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP| //设置dmp功能 03308 DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO| 03309 DMP_FEATURE_GYRO_CAL); 03310 if(res)return 6; 03311 res=dmp_set_fifo_rate(DEFAULT_MPU_HZ); //设置DMP输出速率(最大不超过200Hz) 03312 if(res)return 7; 03313 res=run_self_test(); //自检 03314 if(res)return 8; 03315 res=mpu_set_dmp_state(1); //使能DMP 03316 if(res)return 9; 03317 }else return 10; 03318 return 0; 03319 } 03320 //得到dmp处理后的数据(注意,本函数需要比较多堆栈,局部变量有点多) 03321 //pitch:俯仰角 精度:0.1° 范围:-90.0° <---> +90.0° 03322 //roll:横滚角 精度:0.1° 范围:-180.0°<---> +180.0° 03323 //yaw:航向角 精度:0.1° 范围:-180.0°<---> +180.0° 03324 //返回值:0,正常 03325 // 其他,失败 03326 unsigned char mpu_dmp_get_data(float *pitch,float *roll,float *yaw) 03327 { 03328 float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f; 03329 unsigned long sensor_timestamp; 03330 short gyro[3], accel[3], sensors; 03331 unsigned char more; 03332 long quat[4]; 03333 if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))return 1; 03334 /* Gyro and accel data are written to the FIFO by the DMP in chip frame and hardware units. 03335 * This behavior is convenient because it keeps the gyro and accel outputs of dmp_read_fifo and mpu_read_fifo consistent. 03336 **/ 03337 /*if (sensors & INV_XYZ_GYRO ) 03338 send_packet(PACKET_TYPE_GYRO, gyro); 03339 if (sensors & INV_XYZ_ACCEL) 03340 send_packet(PACKET_TYPE_ACCEL, accel); */ 03341 /* Unlike gyro and accel, quaternions are written to the FIFO in the body frame, q30. 03342 * The orientation is set by the scalar passed to dmp_set_orientation during initialization. 03343 **/ 03344 if(sensors&INV_WXYZ_QUAT) 03345 { 03346 q0 = quat[0] / q30; //q30格式转换为浮点数 03347 q1 = quat[1] / q30; 03348 q2 = quat[2] / q30; 03349 q3 = quat[3] / q30; 03350 //计算得到俯仰角/横滚角/航向角 03351 *pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch 03352 *roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll 03353 *yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3; //yaw 03354 }else return 2; 03355 return 0; 03356 } 03357 03358 //定义目标板采用MSP430 03359 #define MOTION_DRIVER_TARGET_MSP430 03360 03361 /* The following functions must be defined for this platform: 03362 * i2c_write(unsigned char slave_addr, unsigned char reg_addr, 03363 * unsigned char length, unsigned char const *data) 03364 * i2c_read(unsigned char slave_addr, unsigned char reg_addr, 03365 * unsigned char length, unsigned char *data) 03366 * delay_ms(unsigned long num_ms) 03367 * get_ms(unsigned long *count) 03368 */ 03369 #if defined MOTION_DRIVER_TARGET_MSP430 03370 //#include "msp430.h" 03371 //#include "msp430_clock.h" 03372 //#define delay_ms delay_ms 03373 #define get_ms mget_ms 03374 //#define // printf 03375 //#define // printf 03376 03377 #elif defined EMPL_TARGET_MSP430 03378 #include "msp430.h" 03379 #include "msp430_clock.h" 03380 #include "log.h" 03381 #define delay_ms msp430_delay_ms 03382 #define get_ms msp430_get_clock_ms 03383 //#define // MPL_LOGI 03384 //#define // MPL_LOGE 03385 03386 #elif defined EMPL_TARGET_UC3L0 03387 /* Instead of using the standard TWI driver from the ASF library, we're using 03388 * a TWI driver that follows the slave address + register address convention. 03389 */ 03390 #include "delay.h" 03391 #include "sysclk.h" 03392 #include "log.h" 03393 #include "uc3l0_clock.h" 03394 /* delay_ms is a function already defined in ASF. */ 03395 #define get_ms uc3l0_get_clock_ms 03396 //#define // MPL_LOGI 03397 //#define // MPL_LOGE 03398 03399 #else 03400 #error Gyro driver is missing the system layer implementations. 03401 #endif 03402 03403 /* These defines are copied from dmpDefaultMPU6050.c in the general MPL 03404 * releases. These defines may change for each DMP image, so be sure to modify 03405 * these values when switching to a new image. 03406 */ 03407 #define CFG_LP_QUAT (2712) 03408 #define END_ORIENT_TEMP (1866) 03409 #define CFG_27 (2742) 03410 #define CFG_20 (2224) 03411 #define CFG_23 (2745) 03412 #define CFG_FIFO_ON_EVENT (2690) 03413 #define END_PREDICTION_UPDATE (1761) 03414 #define CGNOTICE_INTR (2620) 03415 #define X_GRT_Y_TMP (1358) 03416 #define CFG_DR_INT (1029) 03417 #define CFG_AUTH (1035) 03418 #define UPDATE_PROP_ROT (1835) 03419 #define END_COMPARE_Y_X_TMP2 (1455) 03420 #define SKIP_X_GRT_Y_TMP (1359) 03421 #define SKIP_END_COMPARE (1435) 03422 #define FCFG_3 (1088) 03423 #define FCFG_2 (1066) 03424 #define FCFG_1 (1062) 03425 #define END_COMPARE_Y_X_TMP3 (1434) 03426 #define FCFG_7 (1073) 03427 #define FCFG_6 (1106) 03428 #define FLAT_STATE_END (1713) 03429 #define SWING_END_4 (1616) 03430 #define SWING_END_2 (1565) 03431 #define SWING_END_3 (1587) 03432 #define SWING_END_1 (1550) 03433 #define CFG_8 (2718) 03434 #define CFG_15 (2727) 03435 #define CFG_16 (2746) 03436 #define CFG_EXT_GYRO_BIAS (1189) 03437 #define END_COMPARE_Y_X_TMP (1407) 03438 #define DO_NOT_UPDATE_PROP_ROT (1839) 03439 #define CFG_7 (1205) 03440 #define FLAT_STATE_END_TEMP (1683) 03441 #define END_COMPARE_Y_X (1484) 03442 #define SKIP_SWING_END_1 (1551) 03443 #define SKIP_SWING_END_3 (1588) 03444 #define SKIP_SWING_END_2 (1566) 03445 #define TILTG75_START (1672) 03446 #define CFG_6 (2753) 03447 #define TILTL75_END (1669) 03448 #define END_ORIENT (1884) 03449 #define CFG_FLICK_IN (2573) 03450 #define TILTL75_START (1643) 03451 #define CFG_MOTION_BIAS (1208) 03452 #define X_GRT_Y (1408) 03453 #define TEMPLABEL (2324) 03454 #define CFG_ANDROID_ORIENT_INT (1853) 03455 #define CFG_GYRO_RAW_DATA (2722) 03456 #define X_GRT_Y_TMP2 (1379) 03457 03458 #define D_0_22 (22+512) 03459 #define D_0_24 (24+512) 03460 03461 #define D_0_36 (36) 03462 #define D_0_52 (52) 03463 #define D_0_96 (96) 03464 #define D_0_104 (104) 03465 #define D_0_108 (108) 03466 #define D_0_163 (163) 03467 #define D_0_188 (188) 03468 #define D_0_192 (192) 03469 #define D_0_224 (224) 03470 #define D_0_228 (228) 03471 #define D_0_232 (232) 03472 #define D_0_236 (236) 03473 03474 #define D_1_2 (256 + 2) 03475 #define D_1_4 (256 + 4) 03476 #define D_1_8 (256 + 8) 03477 #define D_1_10 (256 + 10) 03478 #define D_1_24 (256 + 24) 03479 #define D_1_28 (256 + 28) 03480 #define D_1_36 (256 + 36) 03481 #define D_1_40 (256 + 40) 03482 #define D_1_44 (256 + 44) 03483 #define D_1_72 (256 + 72) 03484 #define D_1_74 (256 + 74) 03485 #define D_1_79 (256 + 79) 03486 #define D_1_88 (256 + 88) 03487 #define D_1_90 (256 + 90) 03488 #define D_1_92 (256 + 92) 03489 #define D_1_96 (256 + 96) 03490 #define D_1_98 (256 + 98) 03491 #define D_1_106 (256 + 106) 03492 #define D_1_108 (256 + 108) 03493 #define D_1_112 (256 + 112) 03494 #define D_1_128 (256 + 144) 03495 #define D_1_152 (256 + 12) 03496 #define D_1_160 (256 + 160) 03497 #define D_1_176 (256 + 176) 03498 #define D_1_178 (256 + 178) 03499 #define D_1_218 (256 + 218) 03500 #define D_1_232 (256 + 232) 03501 #define D_1_236 (256 + 236) 03502 #define D_1_240 (256 + 240) 03503 #define D_1_244 (256 + 244) 03504 #define D_1_250 (256 + 250) 03505 #define D_1_252 (256 + 252) 03506 #define D_2_12 (512 + 12) 03507 #define D_2_96 (512 + 96) 03508 #define D_2_108 (512 + 108) 03509 #define D_2_208 (512 + 208) 03510 #define D_2_224 (512 + 224) 03511 #define D_2_236 (512 + 236) 03512 #define D_2_244 (512 + 244) 03513 #define D_2_248 (512 + 248) 03514 #define D_2_252 (512 + 252) 03515 03516 #define CPASS_BIAS_X (35 * 16 + 4) 03517 #define CPASS_BIAS_Y (35 * 16 + 8) 03518 #define CPASS_BIAS_Z (35 * 16 + 12) 03519 #define CPASS_MTX_00 (36 * 16) 03520 #define CPASS_MTX_01 (36 * 16 + 4) 03521 #define CPASS_MTX_02 (36 * 16 + 8) 03522 #define CPASS_MTX_10 (36 * 16 + 12) 03523 #define CPASS_MTX_11 (37 * 16) 03524 #define CPASS_MTX_12 (37 * 16 + 4) 03525 #define CPASS_MTX_20 (37 * 16 + 8) 03526 #define CPASS_MTX_21 (37 * 16 + 12) 03527 #define CPASS_MTX_22 (43 * 16 + 12) 03528 #define D_EXT_GYRO_BIAS_X (61 * 16) 03529 #define D_EXT_GYRO_BIAS_Y (61 * 16) + 4 03530 #define D_EXT_GYRO_BIAS_Z (61 * 16) + 8 03531 #define D_ACT0 (40 * 16) 03532 #define D_ACSX (40 * 16 + 4) 03533 #define D_ACSY (40 * 16 + 8) 03534 #define D_ACSZ (40 * 16 + 12) 03535 03536 #define FLICK_MSG (45 * 16 + 4) 03537 #define FLICK_COUNTER (45 * 16 + 8) 03538 #define FLICK_LOWER (45 * 16 + 12) 03539 #define FLICK_UPPER (46 * 16 + 12) 03540 03541 #define D_AUTH_OUT (992) 03542 #define D_AUTH_IN (996) 03543 #define D_AUTH_A (1000) 03544 #define D_AUTH_B (1004) 03545 03546 #define D_PEDSTD_BP_B (768 + 0x1C) 03547 #define D_PEDSTD_HP_A (768 + 0x78) 03548 #define D_PEDSTD_HP_B (768 + 0x7C) 03549 #define D_PEDSTD_BP_A4 (768 + 0x40) 03550 #define D_PEDSTD_BP_A3 (768 + 0x44) 03551 #define D_PEDSTD_BP_A2 (768 + 0x48) 03552 #define D_PEDSTD_BP_A1 (768 + 0x4C) 03553 #define D_PEDSTD_INT_THRSH (768 + 0x68) 03554 #define D_PEDSTD_CLIP (768 + 0x6C) 03555 #define D_PEDSTD_SB (768 + 0x28) 03556 #define D_PEDSTD_SB_TIME (768 + 0x2C) 03557 #define D_PEDSTD_PEAKTHRSH (768 + 0x98) 03558 #define D_PEDSTD_TIML (768 + 0x2A) 03559 #define D_PEDSTD_TIMH (768 + 0x2E) 03560 #define D_PEDSTD_PEAK (768 + 0X94) 03561 #define D_PEDSTD_STEPCTR (768 + 0x60) 03562 #define D_PEDSTD_TIMECTR (964) 03563 #define D_PEDSTD_DECI (768 + 0xA0) 03564 03565 #define D_HOST_NO_MOT (976) 03566 #define D_ACCEL_BIAS (660) 03567 03568 #define D_ORIENT_GAP (76) 03569 03570 #define D_TILT0_H (48) 03571 #define D_TILT0_L (50) 03572 #define D_TILT1_H (52) 03573 #define D_TILT1_L (54) 03574 #define D_TILT2_H (56) 03575 #define D_TILT2_L (58) 03576 #define D_TILT3_H (60) 03577 #define D_TILT3_L (62) 03578 03579 #define DMP_CODE_SIZE (3062) 03580 03581 static const unsigned char dmp_memory[DMP_CODE_SIZE] = { 03582 /* bank # 0 */ 03583 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 03584 0x00, 0x65, 0x00, 0x54, 0xff, 0xef, 0x00, 0x00, 0xfa, 0x80, 0x00, 0x0b, 0x12, 0x82, 0x00, 0x01, 03585 0x03, 0x0c, 0x30, 0xc3, 0x0e, 0x8c, 0x8c, 0xe9, 0x14, 0xd5, 0x40, 0x02, 0x13, 0x71, 0x0f, 0x8e, 03586 0x38, 0x83, 0xf8, 0x83, 0x30, 0x00, 0xf8, 0x83, 0x25, 0x8e, 0xf8, 0x83, 0x30, 0x00, 0xf8, 0x83, 03587 0xff, 0xff, 0xff, 0xff, 0x0f, 0xfe, 0xa9, 0xd6, 0x24, 0x00, 0x04, 0x00, 0x1a, 0x82, 0x79, 0xa1, 03588 0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x38, 0x83, 0x6f, 0xa2, 03589 0x00, 0x3e, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xca, 0xe3, 0x09, 0x3e, 0x80, 0x00, 0x00, 03590 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 03591 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x6e, 0x00, 0x00, 0x06, 0x92, 0x0a, 0x16, 0xc0, 0xdf, 03592 0xff, 0xff, 0x02, 0x56, 0xfd, 0x8c, 0xd3, 0x77, 0xff, 0xe1, 0xc4, 0x96, 0xe0, 0xc5, 0xbe, 0xaa, 03593 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x2b, 0x00, 0x00, 0x16, 0x57, 0x00, 0x00, 0x03, 0x59, 03594 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xfa, 0x00, 0x02, 0x6c, 0x1d, 0x00, 0x00, 0x00, 0x00, 03595 0x3f, 0xff, 0xdf, 0xeb, 0x00, 0x3e, 0xb3, 0xb6, 0x00, 0x0d, 0x22, 0x78, 0x00, 0x00, 0x2f, 0x3c, 03596 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x42, 0xb5, 0x00, 0x00, 0x39, 0xa2, 0x00, 0x00, 0xb3, 0x65, 03597 0xd9, 0x0e, 0x9f, 0xc9, 0x1d, 0xcf, 0x4c, 0x34, 0x30, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 03598 0x3b, 0xb6, 0x7a, 0xe8, 0x00, 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03599 /* bank # 1 */ 03600 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0xfa, 0x92, 0x10, 0x00, 0x22, 0x5e, 0x00, 0x0d, 0x22, 0x9f, 03601 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0xff, 0x46, 0x00, 0x00, 0x63, 0xd4, 0x00, 0x00, 03602 0x10, 0x00, 0x00, 0x00, 0x04, 0xd6, 0x00, 0x00, 0x04, 0xcc, 0x00, 0x00, 0x04, 0xcc, 0x00, 0x00, 03603 0x00, 0x00, 0x10, 0x72, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03604 0x00, 0x06, 0x00, 0x02, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 03605 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x64, 0x00, 0x20, 0x00, 0x00, 03606 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 03607 0x00, 0x00, 0x00, 0x32, 0xf8, 0x98, 0x00, 0x00, 0xff, 0x65, 0x00, 0x00, 0x83, 0x0f, 0x00, 0x00, 03608 0xff, 0x9b, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03609 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03610 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 03611 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xb2, 0x6a, 0x00, 0x02, 0x00, 0x00, 03612 0x00, 0x01, 0xfb, 0x83, 0x00, 0x68, 0x00, 0x00, 0x00, 0xd9, 0xfc, 0x00, 0x7c, 0xf1, 0xff, 0x83, 03613 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x64, 0x03, 0xe8, 0x00, 0x64, 0x00, 0x28, 03614 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 03615 0x00, 0x00, 0x10, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x10, 0x00, 03616 /* bank # 2 */ 03617 0x00, 0x28, 0x00, 0x00, 0xff, 0xff, 0x45, 0x81, 0xff, 0xff, 0xfa, 0x72, 0x00, 0x00, 0x00, 0x00, 03618 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x05, 0x00, 0x05, 0xba, 0xc6, 0x00, 0x47, 0x78, 0xa2, 03619 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14, 03620 0x00, 0x00, 0x25, 0x4d, 0x00, 0x2f, 0x70, 0x6d, 0x00, 0x00, 0x05, 0xae, 0x00, 0x0c, 0x02, 0xd0, 03621 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03622 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03623 0x00, 0x64, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03625 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03626 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03628 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03629 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 03630 0x00, 0x00, 0x0a, 0xc7, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xff, 0xff, 0xff, 0x9c, 03631 0x00, 0x00, 0x0b, 0x2b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64, 03632 0xff, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03633 /* bank # 3 */ 03634 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03635 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x24, 0x26, 0xd3, 03636 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x96, 0x00, 0x3c, 03637 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03638 0x0c, 0x0a, 0x4e, 0x68, 0xcd, 0xcf, 0x77, 0x09, 0x50, 0x16, 0x67, 0x59, 0xc6, 0x19, 0xce, 0x82, 03639 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03640 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xd7, 0x84, 0x00, 0x03, 0x00, 0x00, 0x00, 03641 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x93, 0x8f, 0x9d, 0x1e, 0x1b, 0x1c, 0x19, 03642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03643 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x18, 0x85, 0x00, 0x00, 0x40, 0x00, 03644 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03645 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03646 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03647 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03648 0x00, 0x00, 0x00, 0x00, 0x67, 0x7d, 0xdf, 0x7e, 0x72, 0x90, 0x2e, 0x55, 0x4c, 0xf6, 0xe6, 0x88, 03649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 03650 03651 /* bank # 4 */ 03652 0xd8, 0xdc, 0xb4, 0xb8, 0xb0, 0xd8, 0xb9, 0xab, 0xf3, 0xf8, 0xfa, 0xb3, 0xb7, 0xbb, 0x8e, 0x9e, 03653 0xae, 0xf1, 0x32, 0xf5, 0x1b, 0xf1, 0xb4, 0xb8, 0xb0, 0x80, 0x97, 0xf1, 0xa9, 0xdf, 0xdf, 0xdf, 03654 0xaa, 0xdf, 0xdf, 0xdf, 0xf2, 0xaa, 0xc5, 0xcd, 0xc7, 0xa9, 0x0c, 0xc9, 0x2c, 0x97, 0xf1, 0xa9, 03655 0x89, 0x26, 0x46, 0x66, 0xb2, 0x89, 0x99, 0xa9, 0x2d, 0x55, 0x7d, 0xb0, 0xb0, 0x8a, 0xa8, 0x96, 03656 0x36, 0x56, 0x76, 0xf1, 0xba, 0xa3, 0xb4, 0xb2, 0x80, 0xc0, 0xb8, 0xa8, 0x97, 0x11, 0xb2, 0x83, 03657 0x98, 0xba, 0xa3, 0xf0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xb2, 0xb9, 0xb4, 0x98, 0x83, 0xf1, 03658 0xa3, 0x29, 0x55, 0x7d, 0xba, 0xb5, 0xb1, 0xa3, 0x83, 0x93, 0xf0, 0x00, 0x28, 0x50, 0xf5, 0xb2, 03659 0xb6, 0xaa, 0x83, 0x93, 0x28, 0x54, 0x7c, 0xf1, 0xb9, 0xa3, 0x82, 0x93, 0x61, 0xba, 0xa2, 0xda, 03660 0xde, 0xdf, 0xdb, 0x81, 0x9a, 0xb9, 0xae, 0xf5, 0x60, 0x68, 0x70, 0xf1, 0xda, 0xba, 0xa2, 0xdf, 03661 0xd9, 0xba, 0xa2, 0xfa, 0xb9, 0xa3, 0x82, 0x92, 0xdb, 0x31, 0xba, 0xa2, 0xd9, 0xba, 0xa2, 0xf8, 03662 0xdf, 0x85, 0xa4, 0xd0, 0xc1, 0xbb, 0xad, 0x83, 0xc2, 0xc5, 0xc7, 0xb8, 0xa2, 0xdf, 0xdf, 0xdf, 03663 0xba, 0xa0, 0xdf, 0xdf, 0xdf, 0xd8, 0xd8, 0xf1, 0xb8, 0xaa, 0xb3, 0x8d, 0xb4, 0x98, 0x0d, 0x35, 03664 0x5d, 0xb2, 0xb6, 0xba, 0xaf, 0x8c, 0x96, 0x19, 0x8f, 0x9f, 0xa7, 0x0e, 0x16, 0x1e, 0xb4, 0x9a, 03665 0xb8, 0xaa, 0x87, 0x2c, 0x54, 0x7c, 0xba, 0xa4, 0xb0, 0x8a, 0xb6, 0x91, 0x32, 0x56, 0x76, 0xb2, 03666 0x84, 0x94, 0xa4, 0xc8, 0x08, 0xcd, 0xd8, 0xb8, 0xb4, 0xb0, 0xf1, 0x99, 0x82, 0xa8, 0x2d, 0x55, 03667 0x7d, 0x98, 0xa8, 0x0e, 0x16, 0x1e, 0xa2, 0x2c, 0x54, 0x7c, 0x92, 0xa4, 0xf0, 0x2c, 0x50, 0x78, 03668 /* bank # 5 */ 03669 0xf1, 0x84, 0xa8, 0x98, 0xc4, 0xcd, 0xfc, 0xd8, 0x0d, 0xdb, 0xa8, 0xfc, 0x2d, 0xf3, 0xd9, 0xba, 03670 0xa6, 0xf8, 0xda, 0xba, 0xa6, 0xde, 0xd8, 0xba, 0xb2, 0xb6, 0x86, 0x96, 0xa6, 0xd0, 0xf3, 0xc8, 03671 0x41, 0xda, 0xa6, 0xc8, 0xf8, 0xd8, 0xb0, 0xb4, 0xb8, 0x82, 0xa8, 0x92, 0xf5, 0x2c, 0x54, 0x88, 03672 0x98, 0xf1, 0x35, 0xd9, 0xf4, 0x18, 0xd8, 0xf1, 0xa2, 0xd0, 0xf8, 0xf9, 0xa8, 0x84, 0xd9, 0xc7, 03673 0xdf, 0xf8, 0xf8, 0x83, 0xc5, 0xda, 0xdf, 0x69, 0xdf, 0x83, 0xc1, 0xd8, 0xf4, 0x01, 0x14, 0xf1, 03674 0xa8, 0x82, 0x4e, 0xa8, 0x84, 0xf3, 0x11, 0xd1, 0x82, 0xf5, 0xd9, 0x92, 0x28, 0x97, 0x88, 0xf1, 03675 0x09, 0xf4, 0x1c, 0x1c, 0xd8, 0x84, 0xa8, 0xf3, 0xc0, 0xf9, 0xd1, 0xd9, 0x97, 0x82, 0xf1, 0x29, 03676 0xf4, 0x0d, 0xd8, 0xf3, 0xf9, 0xf9, 0xd1, 0xd9, 0x82, 0xf4, 0xc2, 0x03, 0xd8, 0xde, 0xdf, 0x1a, 03677 0xd8, 0xf1, 0xa2, 0xfa, 0xf9, 0xa8, 0x84, 0x98, 0xd9, 0xc7, 0xdf, 0xf8, 0xf8, 0xf8, 0x83, 0xc7, 03678 0xda, 0xdf, 0x69, 0xdf, 0xf8, 0x83, 0xc3, 0xd8, 0xf4, 0x01, 0x14, 0xf1, 0x98, 0xa8, 0x82, 0x2e, 03679 0xa8, 0x84, 0xf3, 0x11, 0xd1, 0x82, 0xf5, 0xd9, 0x92, 0x50, 0x97, 0x88, 0xf1, 0x09, 0xf4, 0x1c, 03680 0xd8, 0x84, 0xa8, 0xf3, 0xc0, 0xf8, 0xf9, 0xd1, 0xd9, 0x97, 0x82, 0xf1, 0x49, 0xf4, 0x0d, 0xd8, 03681 0xf3, 0xf9, 0xf9, 0xd1, 0xd9, 0x82, 0xf4, 0xc4, 0x03, 0xd8, 0xde, 0xdf, 0xd8, 0xf1, 0xad, 0x88, 03682 0x98, 0xcc, 0xa8, 0x09, 0xf9, 0xd9, 0x82, 0x92, 0xa8, 0xf5, 0x7c, 0xf1, 0x88, 0x3a, 0xcf, 0x94, 03683 0x4a, 0x6e, 0x98, 0xdb, 0x69, 0x31, 0xda, 0xad, 0xf2, 0xde, 0xf9, 0xd8, 0x87, 0x95, 0xa8, 0xf2, 03684 0x21, 0xd1, 0xda, 0xa5, 0xf9, 0xf4, 0x17, 0xd9, 0xf1, 0xae, 0x8e, 0xd0, 0xc0, 0xc3, 0xae, 0x82, 03685 /* bank # 6 */ 03686 0xc6, 0x84, 0xc3, 0xa8, 0x85, 0x95, 0xc8, 0xa5, 0x88, 0xf2, 0xc0, 0xf1, 0xf4, 0x01, 0x0e, 0xf1, 03687 0x8e, 0x9e, 0xa8, 0xc6, 0x3e, 0x56, 0xf5, 0x54, 0xf1, 0x88, 0x72, 0xf4, 0x01, 0x15, 0xf1, 0x98, 03688 0x45, 0x85, 0x6e, 0xf5, 0x8e, 0x9e, 0x04, 0x88, 0xf1, 0x42, 0x98, 0x5a, 0x8e, 0x9e, 0x06, 0x88, 03689 0x69, 0xf4, 0x01, 0x1c, 0xf1, 0x98, 0x1e, 0x11, 0x08, 0xd0, 0xf5, 0x04, 0xf1, 0x1e, 0x97, 0x02, 03690 0x02, 0x98, 0x36, 0x25, 0xdb, 0xf9, 0xd9, 0x85, 0xa5, 0xf3, 0xc1, 0xda, 0x85, 0xa5, 0xf3, 0xdf, 03691 0xd8, 0x85, 0x95, 0xa8, 0xf3, 0x09, 0xda, 0xa5, 0xfa, 0xd8, 0x82, 0x92, 0xa8, 0xf5, 0x78, 0xf1, 03692 0x88, 0x1a, 0x84, 0x9f, 0x26, 0x88, 0x98, 0x21, 0xda, 0xf4, 0x1d, 0xf3, 0xd8, 0x87, 0x9f, 0x39, 03693 0xd1, 0xaf, 0xd9, 0xdf, 0xdf, 0xfb, 0xf9, 0xf4, 0x0c, 0xf3, 0xd8, 0xfa, 0xd0, 0xf8, 0xda, 0xf9, 03694 0xf9, 0xd0, 0xdf, 0xd9, 0xf9, 0xd8, 0xf4, 0x0b, 0xd8, 0xf3, 0x87, 0x9f, 0x39, 0xd1, 0xaf, 0xd9, 03695 0xdf, 0xdf, 0xf4, 0x1d, 0xf3, 0xd8, 0xfa, 0xfc, 0xa8, 0x69, 0xf9, 0xf9, 0xaf, 0xd0, 0xda, 0xde, 03696 0xfa, 0xd9, 0xf8, 0x8f, 0x9f, 0xa8, 0xf1, 0xcc, 0xf3, 0x98, 0xdb, 0x45, 0xd9, 0xaf, 0xdf, 0xd0, 03697 0xf8, 0xd8, 0xf1, 0x8f, 0x9f, 0xa8, 0xca, 0xf3, 0x88, 0x09, 0xda, 0xaf, 0x8f, 0xcb, 0xf8, 0xd8, 03698 0xf2, 0xad, 0x97, 0x8d, 0x0c, 0xd9, 0xa5, 0xdf, 0xf9, 0xba, 0xa6, 0xf3, 0xfa, 0xf4, 0x12, 0xf2, 03699 0xd8, 0x95, 0x0d, 0xd1, 0xd9, 0xba, 0xa6, 0xf3, 0xfa, 0xda, 0xa5, 0xf2, 0xc1, 0xba, 0xa6, 0xf3, 03700 0xdf, 0xd8, 0xf1, 0xba, 0xb2, 0xb6, 0x86, 0x96, 0xa6, 0xd0, 0xca, 0xf3, 0x49, 0xda, 0xa6, 0xcb, 03701 0xf8, 0xd8, 0xb0, 0xb4, 0xb8, 0xd8, 0xad, 0x84, 0xf2, 0xc0, 0xdf, 0xf1, 0x8f, 0xcb, 0xc3, 0xa8, 03702 /* bank # 7 */ 03703 0xb2, 0xb6, 0x86, 0x96, 0xc8, 0xc1, 0xcb, 0xc3, 0xf3, 0xb0, 0xb4, 0x88, 0x98, 0xa8, 0x21, 0xdb, 03704 0x71, 0x8d, 0x9d, 0x71, 0x85, 0x95, 0x21, 0xd9, 0xad, 0xf2, 0xfa, 0xd8, 0x85, 0x97, 0xa8, 0x28, 03705 0xd9, 0xf4, 0x08, 0xd8, 0xf2, 0x8d, 0x29, 0xda, 0xf4, 0x05, 0xd9, 0xf2, 0x85, 0xa4, 0xc2, 0xf2, 03706 0xd8, 0xa8, 0x8d, 0x94, 0x01, 0xd1, 0xd9, 0xf4, 0x11, 0xf2, 0xd8, 0x87, 0x21, 0xd8, 0xf4, 0x0a, 03707 0xd8, 0xf2, 0x84, 0x98, 0xa8, 0xc8, 0x01, 0xd1, 0xd9, 0xf4, 0x11, 0xd8, 0xf3, 0xa4, 0xc8, 0xbb, 03708 0xaf, 0xd0, 0xf2, 0xde, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xd8, 0xf1, 0xb8, 0xf6, 03709 0xb5, 0xb9, 0xb0, 0x8a, 0x95, 0xa3, 0xde, 0x3c, 0xa3, 0xd9, 0xf8, 0xd8, 0x5c, 0xa3, 0xd9, 0xf8, 03710 0xd8, 0x7c, 0xa3, 0xd9, 0xf8, 0xd8, 0xf8, 0xf9, 0xd1, 0xa5, 0xd9, 0xdf, 0xda, 0xfa, 0xd8, 0xb1, 03711 0x85, 0x30, 0xf7, 0xd9, 0xde, 0xd8, 0xf8, 0x30, 0xad, 0xda, 0xde, 0xd8, 0xf2, 0xb4, 0x8c, 0x99, 03712 0xa3, 0x2d, 0x55, 0x7d, 0xa0, 0x83, 0xdf, 0xdf, 0xdf, 0xb5, 0x91, 0xa0, 0xf6, 0x29, 0xd9, 0xfb, 03713 0xd8, 0xa0, 0xfc, 0x29, 0xd9, 0xfa, 0xd8, 0xa0, 0xd0, 0x51, 0xd9, 0xf8, 0xd8, 0xfc, 0x51, 0xd9, 03714 0xf9, 0xd8, 0x79, 0xd9, 0xfb, 0xd8, 0xa0, 0xd0, 0xfc, 0x79, 0xd9, 0xfa, 0xd8, 0xa1, 0xf9, 0xf9, 03715 0xf9, 0xf9, 0xf9, 0xa0, 0xda, 0xdf, 0xdf, 0xdf, 0xd8, 0xa1, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xac, 03716 0xde, 0xf8, 0xad, 0xde, 0x83, 0x93, 0xac, 0x2c, 0x54, 0x7c, 0xf1, 0xa8, 0xdf, 0xdf, 0xdf, 0xf6, 03717 0x9d, 0x2c, 0xda, 0xa0, 0xdf, 0xd9, 0xfa, 0xdb, 0x2d, 0xf8, 0xd8, 0xa8, 0x50, 0xda, 0xa0, 0xd0, 03718 0xde, 0xd9, 0xd0, 0xf8, 0xf8, 0xf8, 0xdb, 0x55, 0xf8, 0xd8, 0xa8, 0x78, 0xda, 0xa0, 0xd0, 0xdf, 03719 /* bank # 8 */ 03720 0xd9, 0xd0, 0xfa, 0xf8, 0xf8, 0xf8, 0xf8, 0xdb, 0x7d, 0xf8, 0xd8, 0x9c, 0xa8, 0x8c, 0xf5, 0x30, 03721 0xdb, 0x38, 0xd9, 0xd0, 0xde, 0xdf, 0xa0, 0xd0, 0xde, 0xdf, 0xd8, 0xa8, 0x48, 0xdb, 0x58, 0xd9, 03722 0xdf, 0xd0, 0xde, 0xa0, 0xdf, 0xd0, 0xde, 0xd8, 0xa8, 0x68, 0xdb, 0x70, 0xd9, 0xdf, 0xdf, 0xa0, 03723 0xdf, 0xdf, 0xd8, 0xf1, 0xa8, 0x88, 0x90, 0x2c, 0x54, 0x7c, 0x98, 0xa8, 0xd0, 0x5c, 0x38, 0xd1, 03724 0xda, 0xf2, 0xae, 0x8c, 0xdf, 0xf9, 0xd8, 0xb0, 0x87, 0xa8, 0xc1, 0xc1, 0xb1, 0x88, 0xa8, 0xc6, 03725 0xf9, 0xf9, 0xda, 0x36, 0xd8, 0xa8, 0xf9, 0xda, 0x36, 0xd8, 0xa8, 0xf9, 0xda, 0x36, 0xd8, 0xa8, 03726 0xf9, 0xda, 0x36, 0xd8, 0xa8, 0xf9, 0xda, 0x36, 0xd8, 0xf7, 0x8d, 0x9d, 0xad, 0xf8, 0x18, 0xda, 03727 0xf2, 0xae, 0xdf, 0xd8, 0xf7, 0xad, 0xfa, 0x30, 0xd9, 0xa4, 0xde, 0xf9, 0xd8, 0xf2, 0xae, 0xde, 03728 0xfa, 0xf9, 0x83, 0xa7, 0xd9, 0xc3, 0xc5, 0xc7, 0xf1, 0x88, 0x9b, 0xa7, 0x7a, 0xad, 0xf7, 0xde, 03729 0xdf, 0xa4, 0xf8, 0x84, 0x94, 0x08, 0xa7, 0x97, 0xf3, 0x00, 0xae, 0xf2, 0x98, 0x19, 0xa4, 0x88, 03730 0xc6, 0xa3, 0x94, 0x88, 0xf6, 0x32, 0xdf, 0xf2, 0x83, 0x93, 0xdb, 0x09, 0xd9, 0xf2, 0xaa, 0xdf, 03731 0xd8, 0xd8, 0xae, 0xf8, 0xf9, 0xd1, 0xda, 0xf3, 0xa4, 0xde, 0xa7, 0xf1, 0x88, 0x9b, 0x7a, 0xd8, 03732 0xf3, 0x84, 0x94, 0xae, 0x19, 0xf9, 0xda, 0xaa, 0xf1, 0xdf, 0xd8, 0xa8, 0x81, 0xc0, 0xc3, 0xc5, 03733 0xc7, 0xa3, 0x92, 0x83, 0xf6, 0x28, 0xad, 0xde, 0xd9, 0xf8, 0xd8, 0xa3, 0x50, 0xad, 0xd9, 0xf8, 03734 0xd8, 0xa3, 0x78, 0xad, 0xd9, 0xf8, 0xd8, 0xf8, 0xf9, 0xd1, 0xa1, 0xda, 0xde, 0xc3, 0xc5, 0xc7, 03735 0xd8, 0xa1, 0x81, 0x94, 0xf8, 0x18, 0xf2, 0xb0, 0x89, 0xac, 0xc3, 0xc5, 0xc7, 0xf1, 0xd8, 0xb8, 03736 /* bank # 9 */ 03737 0xb4, 0xb0, 0x97, 0x86, 0xa8, 0x31, 0x9b, 0x06, 0x99, 0x07, 0xab, 0x97, 0x28, 0x88, 0x9b, 0xf0, 03738 0x0c, 0x20, 0x14, 0x40, 0xb0, 0xb4, 0xb8, 0xf0, 0xa8, 0x8a, 0x9a, 0x28, 0x50, 0x78, 0xb7, 0x9b, 03739 0xa8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, 0xf1, 0xbb, 0xab, 03740 0x88, 0x00, 0x2c, 0x54, 0x7c, 0xf0, 0xb3, 0x8b, 0xb8, 0xa8, 0x04, 0x28, 0x50, 0x78, 0xf1, 0xb0, 03741 0x88, 0xb4, 0x97, 0x26, 0xa8, 0x59, 0x98, 0xbb, 0xab, 0xb3, 0x8b, 0x02, 0x26, 0x46, 0x66, 0xb0, 03742 0xb8, 0xf0, 0x8a, 0x9c, 0xa8, 0x29, 0x51, 0x79, 0x8b, 0x29, 0x51, 0x79, 0x8a, 0x24, 0x70, 0x59, 03743 0x8b, 0x20, 0x58, 0x71, 0x8a, 0x44, 0x69, 0x38, 0x8b, 0x39, 0x40, 0x68, 0x8a, 0x64, 0x48, 0x31, 03744 0x8b, 0x30, 0x49, 0x60, 0x88, 0xf1, 0xac, 0x00, 0x2c, 0x54, 0x7c, 0xf0, 0x8c, 0xa8, 0x04, 0x28, 03745 0x50, 0x78, 0xf1, 0x88, 0x97, 0x26, 0xa8, 0x59, 0x98, 0xac, 0x8c, 0x02, 0x26, 0x46, 0x66, 0xf0, 03746 0x89, 0x9c, 0xa8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, 0xa9, 03747 0x88, 0x09, 0x20, 0x59, 0x70, 0xab, 0x11, 0x38, 0x40, 0x69, 0xa8, 0x19, 0x31, 0x48, 0x60, 0x8c, 03748 0xa8, 0x3c, 0x41, 0x5c, 0x20, 0x7c, 0x00, 0xf1, 0x87, 0x98, 0x19, 0x86, 0xa8, 0x6e, 0x76, 0x7e, 03749 0xa9, 0x99, 0x88, 0x2d, 0x55, 0x7d, 0xd8, 0xb1, 0xb5, 0xb9, 0xa3, 0xdf, 0xdf, 0xdf, 0xae, 0xd0, 03750 0xdf, 0xaa, 0xd0, 0xde, 0xf2, 0xab, 0xf8, 0xf9, 0xd9, 0xb0, 0x87, 0xc4, 0xaa, 0xf1, 0xdf, 0xdf, 03751 0xbb, 0xaf, 0xdf, 0xdf, 0xb9, 0xd8, 0xb1, 0xf1, 0xa3, 0x97, 0x8e, 0x60, 0xdf, 0xb0, 0x84, 0xf2, 03752 0xc8, 0xf8, 0xf9, 0xd9, 0xde, 0xd8, 0x93, 0x85, 0xf1, 0x4a, 0xb1, 0x83, 0xa3, 0x08, 0xb5, 0x83, 03753 /* bank # 10 */ 03754 0x9a, 0x08, 0x10, 0xb7, 0x9f, 0x10, 0xd8, 0xf1, 0xb0, 0xba, 0xae, 0xb0, 0x8a, 0xc2, 0xb2, 0xb6, 03755 0x8e, 0x9e, 0xf1, 0xfb, 0xd9, 0xf4, 0x1d, 0xd8, 0xf9, 0xd9, 0x0c, 0xf1, 0xd8, 0xf8, 0xf8, 0xad, 03756 0x61, 0xd9, 0xae, 0xfb, 0xd8, 0xf4, 0x0c, 0xf1, 0xd8, 0xf8, 0xf8, 0xad, 0x19, 0xd9, 0xae, 0xfb, 03757 0xdf, 0xd8, 0xf4, 0x16, 0xf1, 0xd8, 0xf8, 0xad, 0x8d, 0x61, 0xd9, 0xf4, 0xf4, 0xac, 0xf5, 0x9c, 03758 0x9c, 0x8d, 0xdf, 0x2b, 0xba, 0xb6, 0xae, 0xfa, 0xf8, 0xf4, 0x0b, 0xd8, 0xf1, 0xae, 0xd0, 0xf8, 03759 0xad, 0x51, 0xda, 0xae, 0xfa, 0xf8, 0xf1, 0xd8, 0xb9, 0xb1, 0xb6, 0xa3, 0x83, 0x9c, 0x08, 0xb9, 03760 0xb1, 0x83, 0x9a, 0xb5, 0xaa, 0xc0, 0xfd, 0x30, 0x83, 0xb7, 0x9f, 0x10, 0xb5, 0x8b, 0x93, 0xf2, 03761 0x02, 0x02, 0xd1, 0xab, 0xda, 0xde, 0xd8, 0xf1, 0xb0, 0x80, 0xba, 0xab, 0xc0, 0xc3, 0xb2, 0x84, 03762 0xc1, 0xc3, 0xd8, 0xb1, 0xb9, 0xf3, 0x8b, 0xa3, 0x91, 0xb6, 0x09, 0xb4, 0xd9, 0xab, 0xde, 0xb0, 03763 0x87, 0x9c, 0xb9, 0xa3, 0xdd, 0xf1, 0xb3, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0xb0, 0x87, 0xa3, 0xa3, 03764 0xa3, 0xa3, 0xb2, 0x8b, 0xb6, 0x9b, 0xf2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 03765 0xa3, 0xf1, 0xb0, 0x87, 0xb5, 0x9a, 0xa3, 0xf3, 0x9b, 0xa3, 0xa3, 0xdc, 0xba, 0xac, 0xdf, 0xb9, 03766 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 03767 0xd8, 0xd8, 0xd8, 0xbb, 0xb3, 0xb7, 0xf1, 0xaa, 0xf9, 0xda, 0xff, 0xd9, 0x80, 0x9a, 0xaa, 0x28, 03768 0xb4, 0x80, 0x98, 0xa7, 0x20, 0xb7, 0x97, 0x87, 0xa8, 0x66, 0x88, 0xf0, 0x79, 0x51, 0xf1, 0x90, 03769 0x2c, 0x87, 0x0c, 0xa7, 0x81, 0x97, 0x62, 0x93, 0xf0, 0x71, 0x71, 0x60, 0x85, 0x94, 0x01, 0x29, 03770 /* bank # 11 */ 03771 0x51, 0x79, 0x90, 0xa5, 0xf1, 0x28, 0x4c, 0x6c, 0x87, 0x0c, 0x95, 0x18, 0x85, 0x78, 0xa3, 0x83, 03772 0x90, 0x28, 0x4c, 0x6c, 0x88, 0x6c, 0xd8, 0xf3, 0xa2, 0x82, 0x00, 0xf2, 0x10, 0xa8, 0x92, 0x19, 03773 0x80, 0xa2, 0xf2, 0xd9, 0x26, 0xd8, 0xf1, 0x88, 0xa8, 0x4d, 0xd9, 0x48, 0xd8, 0x96, 0xa8, 0x39, 03774 0x80, 0xd9, 0x3c, 0xd8, 0x95, 0x80, 0xa8, 0x39, 0xa6, 0x86, 0x98, 0xd9, 0x2c, 0xda, 0x87, 0xa7, 03775 0x2c, 0xd8, 0xa8, 0x89, 0x95, 0x19, 0xa9, 0x80, 0xd9, 0x38, 0xd8, 0xa8, 0x89, 0x39, 0xa9, 0x80, 03776 0xda, 0x3c, 0xd8, 0xa8, 0x2e, 0xa8, 0x39, 0x90, 0xd9, 0x0c, 0xd8, 0xa8, 0x95, 0x31, 0x98, 0xd9, 03777 0x0c, 0xd8, 0xa8, 0x09, 0xd9, 0xff, 0xd8, 0x01, 0xda, 0xff, 0xd8, 0x95, 0x39, 0xa9, 0xda, 0x26, 03778 0xff, 0xd8, 0x90, 0xa8, 0x0d, 0x89, 0x99, 0xa8, 0x10, 0x80, 0x98, 0x21, 0xda, 0x2e, 0xd8, 0x89, 03779 0x99, 0xa8, 0x31, 0x80, 0xda, 0x2e, 0xd8, 0xa8, 0x86, 0x96, 0x31, 0x80, 0xda, 0x2e, 0xd8, 0xa8, 03780 0x87, 0x31, 0x80, 0xda, 0x2e, 0xd8, 0xa8, 0x82, 0x92, 0xf3, 0x41, 0x80, 0xf1, 0xd9, 0x2e, 0xd8, 03781 0xa8, 0x82, 0xf3, 0x19, 0x80, 0xf1, 0xd9, 0x2e, 0xd8, 0x82, 0xac, 0xf3, 0xc0, 0xa2, 0x80, 0x22, 03782 0xf1, 0xa6, 0x2e, 0xa7, 0x2e, 0xa9, 0x22, 0x98, 0xa8, 0x29, 0xda, 0xac, 0xde, 0xff, 0xd8, 0xa2, 03783 0xf2, 0x2a, 0xf1, 0xa9, 0x2e, 0x82, 0x92, 0xa8, 0xf2, 0x31, 0x80, 0xa6, 0x96, 0xf1, 0xd9, 0x00, 03784 0xac, 0x8c, 0x9c, 0x0c, 0x30, 0xac, 0xde, 0xd0, 0xde, 0xff, 0xd8, 0x8c, 0x9c, 0xac, 0xd0, 0x10, 03785 0xac, 0xde, 0x80, 0x92, 0xa2, 0xf2, 0x4c, 0x82, 0xa8, 0xf1, 0xca, 0xf2, 0x35, 0xf1, 0x96, 0x88, 03786 0xa6, 0xd9, 0x00, 0xd8, 0xf1, 0xff 03787 }; 03788 03789 static const unsigned short sStartAddress = 0x0400; 03790 03791 /* END OF SECTION COPIED FROM dmpDefaultMPU6050.c */ 03792 03793 #define INT_SRC_TAP (0x01) 03794 #define INT_SRC_ANDROID_ORIENT (0x08) 03795 03796 #define DMP_FEATURE_SEND_ANY_GYRO (DMP_FEATURE_SEND_RAW_GYRO | \ 03797 DMP_FEATURE_SEND_CAL_GYRO) 03798 03799 #define MAX_PACKET_LENGTH_2 (32) //前面已经有一个定义了你,避免冲突改成2 03800 03801 #define DMP_SAMPLE_RATE (200) 03802 #define GYRO_SF (46850825LL * 200 / DMP_SAMPLE_RATE) 03803 03804 #define FIFO_CORRUPTION_CHECK 03805 #ifdef FIFO_CORRUPTION_CHECK 03806 #define QUAT_ERROR_THRESH (1L<<24) 03807 #define QUAT_MAG_SQ_NORMALIZED (1L<<28) 03808 #define QUAT_MAG_SQ_MIN (QUAT_MAG_SQ_NORMALIZED - QUAT_ERROR_THRESH) 03809 #define QUAT_MAG_SQ_MAX (QUAT_MAG_SQ_NORMALIZED + QUAT_ERROR_THRESH) 03810 #endif 03811 03812 struct dmp_s { 03813 void (*tap_cb)(unsigned char count, unsigned char direction); 03814 void (*android_orient_cb)(unsigned char orientation); 03815 unsigned short orient; 03816 unsigned short feature_mask; 03817 unsigned short fifo_rate; 03818 unsigned char packet_length; 03819 }; 03820 03821 //static struct dmp_s dmp = { 03822 // .tap_cb = NULL, 03823 // .android_orient_cb = NULL, 03824 // .orient = 0, 03825 // .feature_mask = 0, 03826 // .fifo_rate = 0, 03827 // .packet_length = 0 03828 //}; 03829 03830 static struct dmp_s dmp={ 03831 NULL, 03832 NULL, 03833 0, 03834 0, 03835 0, 03836 0 03837 }; 03838 03839 /** 03840 * @brief Load the DMP with this image. 03841 * @return 0 if successful. 03842 */ 03843 int dmp_load_motion_driver_firmware(void) 03844 { 03845 return mpu_load_firmware(DMP_CODE_SIZE, dmp_memory, sStartAddress, 03846 DMP_SAMPLE_RATE); 03847 } 03848 03849 /** 03850 * @brief Push gyro and accel orientation to the DMP. 03851 * The orientation is represented here as the output of 03852 * @e inv_orientation_matrix_to_scalar. 03853 * @param[in] orient Gyro and accel orientation in body frame. 03854 * @return 0 if successful. 03855 */ 03856 int dmp_set_orientation(unsigned short orient) 03857 { 03858 unsigned char gyro_regs[3], accel_regs[3]; 03859 const unsigned char gyro_axes[3] = {DINA4C, DINACD, DINA6C}; 03860 const unsigned char accel_axes[3] = {DINA0C, DINAC9, DINA2C}; 03861 const unsigned char gyro_sign[3] = {DINA36, DINA56, DINA76}; 03862 const unsigned char accel_sign[3] = {DINA26, DINA46, DINA66}; 03863 03864 gyro_regs[0] = gyro_axes[orient & 3]; 03865 gyro_regs[1] = gyro_axes[(orient >> 3) & 3]; 03866 gyro_regs[2] = gyro_axes[(orient >> 6) & 3]; 03867 accel_regs[0] = accel_axes[orient & 3]; 03868 accel_regs[1] = accel_axes[(orient >> 3) & 3]; 03869 accel_regs[2] = accel_axes[(orient >> 6) & 3]; 03870 03871 /* Chip-to-body, axes only. */ 03872 if (mpu_write_mem(FCFG_1, 3, gyro_regs)) 03873 return -1; 03874 if (mpu_write_mem(FCFG_2, 3, accel_regs)) 03875 return -1; 03876 03877 memcpy(gyro_regs, gyro_sign, 3); 03878 memcpy(accel_regs, accel_sign, 3); 03879 if (orient & 4) { 03880 gyro_regs[0] |= 1; 03881 accel_regs[0] |= 1; 03882 } 03883 if (orient & 0x20) { 03884 gyro_regs[1] |= 1; 03885 accel_regs[1] |= 1; 03886 } 03887 if (orient & 0x100) { 03888 gyro_regs[2] |= 1; 03889 accel_regs[2] |= 1; 03890 } 03891 03892 /* Chip-to-body, sign only. */ 03893 if (mpu_write_mem(FCFG_3, 3, gyro_regs)) 03894 return -1; 03895 if (mpu_write_mem(FCFG_7, 3, accel_regs)) 03896 return -1; 03897 dmp.orient = orient; 03898 return 0; 03899 } 03900 03901 /** 03902 * @brief Push gyro biases to the DMP. 03903 * Because the gyro integration is handled in the DMP, any gyro biases 03904 * calculated by the MPL should be pushed down to DMP memory to remove 03905 * 3-axis quaternion drift. 03906 * \n NOTE: If the DMP-based gyro calibration is enabled, the DMP will 03907 * overwrite the biases written to this location once a new one is computed. 03908 * @param[in] bias Gyro biases in q16. 03909 * @return 0 if successful. 03910 */ 03911 int dmp_set_gyro_bias(long *bias) 03912 { 03913 long gyro_bias_body[3]; 03914 unsigned char regs[4]; 03915 03916 gyro_bias_body[0] = bias[dmp.orient & 3]; 03917 if (dmp.orient & 4) 03918 gyro_bias_body[0] *= -1; 03919 gyro_bias_body[1] = bias[(dmp.orient >> 3) & 3]; 03920 if (dmp.orient & 0x20) 03921 gyro_bias_body[1] *= -1; 03922 gyro_bias_body[2] = bias[(dmp.orient >> 6) & 3]; 03923 if (dmp.orient & 0x100) 03924 gyro_bias_body[2] *= -1; 03925 03926 #ifdef EMPL_NO_64BIT 03927 gyro_bias_body[0] = (long)(((float)gyro_bias_body[0] * GYRO_SF) / 1073741824.f); 03928 gyro_bias_body[1] = (long)(((float)gyro_bias_body[1] * GYRO_SF) / 1073741824.f); 03929 gyro_bias_body[2] = (long)(((float)gyro_bias_body[2] * GYRO_SF) / 1073741824.f); 03930 #else 03931 gyro_bias_body[0] = (long)(((long long)gyro_bias_body[0] * GYRO_SF) >> 30); 03932 gyro_bias_body[1] = (long)(((long long)gyro_bias_body[1] * GYRO_SF) >> 30); 03933 gyro_bias_body[2] = (long)(((long long)gyro_bias_body[2] * GYRO_SF) >> 30); 03934 #endif 03935 03936 regs[0] = (unsigned char)((gyro_bias_body[0] >> 24) & 0xFF); 03937 regs[1] = (unsigned char)((gyro_bias_body[0] >> 16) & 0xFF); 03938 regs[2] = (unsigned char)((gyro_bias_body[0] >> 8) & 0xFF); 03939 regs[3] = (unsigned char)(gyro_bias_body[0] & 0xFF); 03940 if (mpu_write_mem(D_EXT_GYRO_BIAS_X, 4, regs)) 03941 return -1; 03942 03943 regs[0] = (unsigned char)((gyro_bias_body[1] >> 24) & 0xFF); 03944 regs[1] = (unsigned char)((gyro_bias_body[1] >> 16) & 0xFF); 03945 regs[2] = (unsigned char)((gyro_bias_body[1] >> 8) & 0xFF); 03946 regs[3] = (unsigned char)(gyro_bias_body[1] & 0xFF); 03947 if (mpu_write_mem(D_EXT_GYRO_BIAS_Y, 4, regs)) 03948 return -1; 03949 03950 regs[0] = (unsigned char)((gyro_bias_body[2] >> 24) & 0xFF); 03951 regs[1] = (unsigned char)((gyro_bias_body[2] >> 16) & 0xFF); 03952 regs[2] = (unsigned char)((gyro_bias_body[2] >> 8) & 0xFF); 03953 regs[3] = (unsigned char)(gyro_bias_body[2] & 0xFF); 03954 return mpu_write_mem(D_EXT_GYRO_BIAS_Z, 4, regs); 03955 } 03956 03957 /** 03958 * @brief Push accel biases to the DMP. 03959 * These biases will be removed from the DMP 6-axis quaternion. 03960 * @param[in] bias Accel biases in q16. 03961 * @return 0 if successful. 03962 */ 03963 int dmp_set_accel_bias(long *bias) 03964 { 03965 long accel_bias_body[3]; 03966 unsigned char regs[12]; 03967 long long accel_sf; 03968 unsigned short accel_sens; 03969 03970 mpu_get_accel_sens(&accel_sens); 03971 accel_sf = (long long)accel_sens << 15; 03972 //__no_operation(); 03973 03974 accel_bias_body[0] = bias[dmp.orient & 3]; 03975 if (dmp.orient & 4) 03976 accel_bias_body[0] *= -1; 03977 accel_bias_body[1] = bias[(dmp.orient >> 3) & 3]; 03978 if (dmp.orient & 0x20) 03979 accel_bias_body[1] *= -1; 03980 accel_bias_body[2] = bias[(dmp.orient >> 6) & 3]; 03981 if (dmp.orient & 0x100) 03982 accel_bias_body[2] *= -1; 03983 03984 #ifdef EMPL_NO_64BIT 03985 accel_bias_body[0] = (long)(((float)accel_bias_body[0] * accel_sf) / 1073741824.f); 03986 accel_bias_body[1] = (long)(((float)accel_bias_body[1] * accel_sf) / 1073741824.f); 03987 accel_bias_body[2] = (long)(((float)accel_bias_body[2] * accel_sf) / 1073741824.f); 03988 #else 03989 accel_bias_body[0] = (long)(((long long)accel_bias_body[0] * accel_sf) >> 30); 03990 accel_bias_body[1] = (long)(((long long)accel_bias_body[1] * accel_sf) >> 30); 03991 accel_bias_body[2] = (long)(((long long)accel_bias_body[2] * accel_sf) >> 30); 03992 #endif 03993 03994 regs[0] = (unsigned char)((accel_bias_body[0] >> 24) & 0xFF); 03995 regs[1] = (unsigned char)((accel_bias_body[0] >> 16) & 0xFF); 03996 regs[2] = (unsigned char)((accel_bias_body[0] >> 8) & 0xFF); 03997 regs[3] = (unsigned char)(accel_bias_body[0] & 0xFF); 03998 regs[4] = (unsigned char)((accel_bias_body[1] >> 24) & 0xFF); 03999 regs[5] = (unsigned char)((accel_bias_body[1] >> 16) & 0xFF); 04000 regs[6] = (unsigned char)((accel_bias_body[1] >> 8) & 0xFF); 04001 regs[7] = (unsigned char)(accel_bias_body[1] & 0xFF); 04002 regs[8] = (unsigned char)((accel_bias_body[2] >> 24) & 0xFF); 04003 regs[9] = (unsigned char)((accel_bias_body[2] >> 16) & 0xFF); 04004 regs[10] = (unsigned char)((accel_bias_body[2] >> 8) & 0xFF); 04005 regs[11] = (unsigned char)(accel_bias_body[2] & 0xFF); 04006 return mpu_write_mem(D_ACCEL_BIAS, 12, regs); 04007 } 04008 04009 /** 04010 * @brief Set DMP output rate. 04011 * Only used when DMP is on. 04012 * @param[in] rate Desired fifo rate (Hz). 04013 * @return 0 if successful. 04014 */ 04015 int dmp_set_fifo_rate(unsigned short rate) 04016 { 04017 const unsigned char regs_end[12] = {DINAFE, DINAF2, DINAAB, 04018 0xc4, DINAAA, DINAF1, DINADF, DINADF, 0xBB, 0xAF, DINADF, DINADF}; 04019 unsigned short div; 04020 unsigned char tmp[8]; 04021 04022 if (rate > DMP_SAMPLE_RATE) 04023 return -1; 04024 div = DMP_SAMPLE_RATE / rate - 1; 04025 tmp[0] = (unsigned char)((div >> 8) & 0xFF); 04026 tmp[1] = (unsigned char)(div & 0xFF); 04027 if (mpu_write_mem(D_0_22, 2, tmp)) 04028 return -1; 04029 if (mpu_write_mem(CFG_6, 12, (unsigned char*)regs_end)) 04030 return -1; 04031 04032 dmp.fifo_rate = rate; 04033 return 0; 04034 } 04035 04036 /** 04037 * @brief Get DMP output rate. 04038 * @param[out] rate Current fifo rate (Hz). 04039 * @return 0 if successful. 04040 */ 04041 int dmp_get_fifo_rate(unsigned short *rate) 04042 { 04043 rate[0] = dmp.fifo_rate; 04044 return 0; 04045 } 04046 04047 /** 04048 * @brief Set tap threshold for a specific axis. 04049 * @param[in] axis 1, 2, and 4 for XYZ accel, respectively. 04050 * @param[in] thresh Tap threshold, in mg/ms. 04051 * @return 0 if successful. 04052 */ 04053 int dmp_set_tap_thresh(unsigned char axis, unsigned short thresh) 04054 { 04055 unsigned char tmp[4], accel_fsr; 04056 float scaled_thresh; 04057 unsigned short dmp_thresh, dmp_thresh_2; 04058 if (!(axis & TAP_XYZ) || thresh > 1600) 04059 return -1; 04060 04061 scaled_thresh = (float)thresh / DMP_SAMPLE_RATE; 04062 04063 mpu_get_accel_fsr(&accel_fsr); 04064 switch (accel_fsr) { 04065 case 2: 04066 dmp_thresh = (unsigned short)(scaled_thresh * 16384); 04067 /* dmp_thresh * 0.75 */ 04068 dmp_thresh_2 = (unsigned short)(scaled_thresh * 12288); 04069 break; 04070 case 4: 04071 dmp_thresh = (unsigned short)(scaled_thresh * 8192); 04072 /* dmp_thresh * 0.75 */ 04073 dmp_thresh_2 = (unsigned short)(scaled_thresh * 6144); 04074 break; 04075 case 8: 04076 dmp_thresh = (unsigned short)(scaled_thresh * 4096); 04077 /* dmp_thresh * 0.75 */ 04078 dmp_thresh_2 = (unsigned short)(scaled_thresh * 3072); 04079 break; 04080 case 16: 04081 dmp_thresh = (unsigned short)(scaled_thresh * 2048); 04082 /* dmp_thresh * 0.75 */ 04083 dmp_thresh_2 = (unsigned short)(scaled_thresh * 1536); 04084 break; 04085 default: 04086 return -1; 04087 } 04088 tmp[0] = (unsigned char)(dmp_thresh >> 8); 04089 tmp[1] = (unsigned char)(dmp_thresh & 0xFF); 04090 tmp[2] = (unsigned char)(dmp_thresh_2 >> 8); 04091 tmp[3] = (unsigned char)(dmp_thresh_2 & 0xFF); 04092 04093 if (axis & TAP_X) { 04094 if (mpu_write_mem(DMP_TAP_THX, 2, tmp)) 04095 return -1; 04096 if (mpu_write_mem(D_1_36, 2, tmp+2)) 04097 return -1; 04098 } 04099 if (axis & TAP_Y) { 04100 if (mpu_write_mem(DMP_TAP_THY, 2, tmp)) 04101 return -1; 04102 if (mpu_write_mem(D_1_40, 2, tmp+2)) 04103 return -1; 04104 } 04105 if (axis & TAP_Z) { 04106 if (mpu_write_mem(DMP_TAP_THZ, 2, tmp)) 04107 return -1; 04108 if (mpu_write_mem(D_1_44, 2, tmp+2)) 04109 return -1; 04110 } 04111 return 0; 04112 } 04113 04114 /** 04115 * @brief Set which axes will register a tap. 04116 * @param[in] axis 1, 2, and 4 for XYZ, respectively. 04117 * @return 0 if successful. 04118 */ 04119 int dmp_set_tap_axes(unsigned char axis) 04120 { 04121 unsigned char tmp = 0; 04122 04123 if (axis & TAP_X) 04124 tmp |= 0x30; 04125 if (axis & TAP_Y) 04126 tmp |= 0x0C; 04127 if (axis & TAP_Z) 04128 tmp |= 0x03; 04129 return mpu_write_mem(D_1_72, 1, &tmp); 04130 } 04131 04132 /** 04133 * @brief Set minimum number of taps needed for an interrupt. 04134 * @param[in] min_taps Minimum consecutive taps (1-4). 04135 * @return 0 if successful. 04136 */ 04137 int dmp_set_tap_count(unsigned char min_taps) 04138 { 04139 unsigned char tmp; 04140 04141 if (min_taps < 1) 04142 min_taps = 1; 04143 else if (min_taps > 4) 04144 min_taps = 4; 04145 04146 tmp = min_taps - 1; 04147 return mpu_write_mem(D_1_79, 1, &tmp); 04148 } 04149 04150 /** 04151 * @brief Set length between valid taps. 04152 * @param[in] time Milliseconds between taps. 04153 * @return 0 if successful. 04154 */ 04155 int dmp_set_tap_time(unsigned short time) 04156 { 04157 unsigned short dmp_time; 04158 unsigned char tmp[2]; 04159 04160 dmp_time = time / (1000 / DMP_SAMPLE_RATE); 04161 tmp[0] = (unsigned char)(dmp_time >> 8); 04162 tmp[1] = (unsigned char)(dmp_time & 0xFF); 04163 return mpu_write_mem(DMP_TAPW_MIN, 2, tmp); 04164 } 04165 04166 /** 04167 * @brief Set max time between taps to register as a multi-tap. 04168 * @param[in] time Max milliseconds between taps. 04169 * @return 0 if successful. 04170 */ 04171 int dmp_set_tap_time_multi(unsigned short time) 04172 { 04173 unsigned short dmp_time; 04174 unsigned char tmp[2]; 04175 04176 dmp_time = time / (1000 / DMP_SAMPLE_RATE); 04177 tmp[0] = (unsigned char)(dmp_time >> 8); 04178 tmp[1] = (unsigned char)(dmp_time & 0xFF); 04179 return mpu_write_mem(D_1_218, 2, tmp); 04180 } 04181 04182 /** 04183 * @brief Set shake rejection threshold. 04184 * If the DMP detects a gyro sample larger than @e thresh, taps are rejected. 04185 * @param[in] sf Gyro scale factor. 04186 * @param[in] thresh Gyro threshold in dps. 04187 * @return 0 if successful. 04188 */ 04189 int dmp_set_shake_reject_thresh(long sf, unsigned short thresh) 04190 { 04191 unsigned char tmp[4]; 04192 long thresh_scaled = sf / 1000 * thresh; 04193 tmp[0] = (unsigned char)(((long)thresh_scaled >> 24) & 0xFF); 04194 tmp[1] = (unsigned char)(((long)thresh_scaled >> 16) & 0xFF); 04195 tmp[2] = (unsigned char)(((long)thresh_scaled >> 8) & 0xFF); 04196 tmp[3] = (unsigned char)((long)thresh_scaled & 0xFF); 04197 return mpu_write_mem(D_1_92, 4, tmp); 04198 } 04199 04200 /** 04201 * @brief Set shake rejection time. 04202 * Sets the length of time that the gyro must be outside of the threshold set 04203 * by @e gyro_set_shake_reject_thresh before taps are rejected. A mandatory 04204 * 60 ms is added to this parameter. 04205 * @param[in] time Time in milliseconds. 04206 * @return 0 if successful. 04207 */ 04208 int dmp_set_shake_reject_time(unsigned short time) 04209 { 04210 unsigned char tmp[2]; 04211 04212 time /= (1000 / DMP_SAMPLE_RATE); 04213 tmp[0] = time >> 8; 04214 tmp[1] = time & 0xFF; 04215 return mpu_write_mem(D_1_90,2,tmp); 04216 } 04217 04218 /** 04219 * @brief Set shake rejection timeout. 04220 * Sets the length of time after a shake rejection that the gyro must stay 04221 * inside of the threshold before taps can be detected again. A mandatory 04222 * 60 ms is added to this parameter. 04223 * @param[in] time Time in milliseconds. 04224 * @return 0 if successful. 04225 */ 04226 int dmp_set_shake_reject_timeout(unsigned short time) 04227 { 04228 unsigned char tmp[2]; 04229 04230 time /= (1000 / DMP_SAMPLE_RATE); 04231 tmp[0] = time >> 8; 04232 tmp[1] = time & 0xFF; 04233 return mpu_write_mem(D_1_88,2,tmp); 04234 } 04235 04236 /** 04237 * @brief Get current step count. 04238 * @param[out] count Number of steps detected. 04239 * @return 0 if successful. 04240 */ 04241 int dmp_get_pedometer_step_count(unsigned long *count) 04242 { 04243 unsigned char tmp[4]; 04244 if (!count) 04245 return -1; 04246 04247 if (mpu_read_mem(D_PEDSTD_STEPCTR, 4, tmp)) 04248 return -1; 04249 04250 count[0] = ((unsigned long)tmp[0] << 24) | ((unsigned long)tmp[1] << 16) | 04251 ((unsigned long)tmp[2] << 8) | tmp[3]; 04252 return 0; 04253 } 04254 04255 /** 04256 * @brief Overwrite current step count. 04257 * WARNING: This function writes to DMP memory and could potentially encounter 04258 * a race condition if called while the pedometer is enabled. 04259 * @param[in] count New step count. 04260 * @return 0 if successful. 04261 */ 04262 int dmp_set_pedometer_step_count(unsigned long count) 04263 { 04264 unsigned char tmp[4]; 04265 04266 tmp[0] = (unsigned char)((count >> 24) & 0xFF); 04267 tmp[1] = (unsigned char)((count >> 16) & 0xFF); 04268 tmp[2] = (unsigned char)((count >> 8) & 0xFF); 04269 tmp[3] = (unsigned char)(count & 0xFF); 04270 return mpu_write_mem(D_PEDSTD_STEPCTR, 4, tmp); 04271 } 04272 04273 /** 04274 * @brief Get duration of walking time. 04275 * @param[in] time Walk time in milliseconds. 04276 * @return 0 if successful. 04277 */ 04278 int dmp_get_pedometer_walk_time(unsigned long *time) 04279 { 04280 unsigned char tmp[4]; 04281 if (!time) 04282 return -1; 04283 04284 if (mpu_read_mem(D_PEDSTD_TIMECTR, 4, tmp)) 04285 return -1; 04286 04287 time[0] = (((unsigned long)tmp[0] << 24) | ((unsigned long)tmp[1] << 16) | 04288 ((unsigned long)tmp[2] << 8) | tmp[3]) * 20; 04289 return 0; 04290 } 04291 04292 /** 04293 * @brief Overwrite current walk time. 04294 * WARNING: This function writes to DMP memory and could potentially encounter 04295 * a race condition if called while the pedometer is enabled. 04296 * @param[in] time New walk time in milliseconds. 04297 */ 04298 int dmp_set_pedometer_walk_time(unsigned long time) 04299 { 04300 unsigned char tmp[4]; 04301 04302 time /= 20; 04303 04304 tmp[0] = (unsigned char)((time >> 24) & 0xFF); 04305 tmp[1] = (unsigned char)((time >> 16) & 0xFF); 04306 tmp[2] = (unsigned char)((time >> 8) & 0xFF); 04307 tmp[3] = (unsigned char)(time & 0xFF); 04308 return mpu_write_mem(D_PEDSTD_TIMECTR, 4, tmp); 04309 } 04310 04311 /** 04312 * @brief Enable DMP features. 04313 * The following \#define's are used in the input mask: 04314 * \n DMP_FEATURE_TAP 04315 * \n DMP_FEATURE_ANDROID_ORIENT 04316 * \n DMP_FEATURE_LP_QUAT 04317 * \n DMP_FEATURE_6X_LP_QUAT 04318 * \n DMP_FEATURE_GYRO_CAL 04319 * \n DMP_FEATURE_SEND_RAW_ACCEL 04320 * \n DMP_FEATURE_SEND_RAW_GYRO 04321 * \n NOTE: DMP_FEATURE_LP_QUAT and DMP_FEATURE_6X_LP_QUAT are mutually 04322 * exclusive. 04323 * \n NOTE: DMP_FEATURE_SEND_RAW_GYRO and DMP_FEATURE_SEND_CAL_GYRO are also 04324 * mutually exclusive. 04325 * @param[in] mask Mask of features to enable. 04326 * @return 0 if successful. 04327 */ 04328 int dmp_enable_feature(unsigned short mask) 04329 { 04330 unsigned char tmp[10]; 04331 04332 /* TODO: All of these settings can probably be integrated into the default 04333 * DMP image. 04334 */ 04335 /* Set integration scale factor. */ 04336 tmp[0] = (unsigned char)((GYRO_SF >> 24) & 0xFF); 04337 tmp[1] = (unsigned char)((GYRO_SF >> 16) & 0xFF); 04338 tmp[2] = (unsigned char)((GYRO_SF >> 8) & 0xFF); 04339 tmp[3] = (unsigned char)(GYRO_SF & 0xFF); 04340 mpu_write_mem(D_0_104, 4, tmp); 04341 04342 /* Send sensor data to the FIFO. */ 04343 tmp[0] = 0xA3; 04344 if (mask & DMP_FEATURE_SEND_RAW_ACCEL) { 04345 tmp[1] = 0xC0; 04346 tmp[2] = 0xC8; 04347 tmp[3] = 0xC2; 04348 } else { 04349 tmp[1] = 0xA3; 04350 tmp[2] = 0xA3; 04351 tmp[3] = 0xA3; 04352 } 04353 if (mask & DMP_FEATURE_SEND_ANY_GYRO) { 04354 tmp[4] = 0xC4; 04355 tmp[5] = 0xCC; 04356 tmp[6] = 0xC6; 04357 } else { 04358 tmp[4] = 0xA3; 04359 tmp[5] = 0xA3; 04360 tmp[6] = 0xA3; 04361 } 04362 tmp[7] = 0xA3; 04363 tmp[8] = 0xA3; 04364 tmp[9] = 0xA3; 04365 mpu_write_mem(CFG_15,10,tmp); 04366 04367 /* Send gesture data to the FIFO. */ 04368 if (mask & (DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT)) 04369 tmp[0] = DINA20; 04370 else 04371 tmp[0] = 0xD8; 04372 mpu_write_mem(CFG_27,1,tmp); 04373 04374 if (mask & DMP_FEATURE_GYRO_CAL) 04375 dmp_enable_gyro_cal(1); 04376 else 04377 dmp_enable_gyro_cal(0); 04378 04379 if (mask & DMP_FEATURE_SEND_ANY_GYRO) { 04380 if (mask & DMP_FEATURE_SEND_CAL_GYRO) { 04381 tmp[0] = 0xB2; 04382 tmp[1] = 0x8B; 04383 tmp[2] = 0xB6; 04384 tmp[3] = 0x9B; 04385 } else { 04386 tmp[0] = DINAC0; 04387 tmp[1] = DINA80; 04388 tmp[2] = DINAC2; 04389 tmp[3] = DINA90; 04390 } 04391 mpu_write_mem(CFG_GYRO_RAW_DATA, 4, tmp); 04392 } 04393 04394 if (mask & DMP_FEATURE_TAP) { 04395 /* Enable tap. */ 04396 tmp[0] = 0xF8; 04397 mpu_write_mem(CFG_20, 1, tmp); 04398 dmp_set_tap_thresh(TAP_XYZ, 250); 04399 dmp_set_tap_axes(TAP_XYZ); 04400 dmp_set_tap_count(1); 04401 dmp_set_tap_time(100); 04402 dmp_set_tap_time_multi(500); 04403 04404 dmp_set_shake_reject_thresh(GYRO_SF, 200); 04405 dmp_set_shake_reject_time(40); 04406 dmp_set_shake_reject_timeout(10); 04407 } else { 04408 tmp[0] = 0xD8; 04409 mpu_write_mem(CFG_20, 1, tmp); 04410 } 04411 04412 if (mask & DMP_FEATURE_ANDROID_ORIENT) { 04413 tmp[0] = 0xD9; 04414 } else 04415 tmp[0] = 0xD8; 04416 mpu_write_mem(CFG_ANDROID_ORIENT_INT, 1, tmp); 04417 04418 if (mask & DMP_FEATURE_LP_QUAT) 04419 dmp_enable_lp_quat(1); 04420 else 04421 dmp_enable_lp_quat(0); 04422 04423 if (mask & DMP_FEATURE_6X_LP_QUAT) 04424 dmp_enable_6x_lp_quat(1); 04425 else 04426 dmp_enable_6x_lp_quat(0); 04427 04428 /* Pedometer is always enabled. */ 04429 dmp.feature_mask = mask | DMP_FEATURE_PEDOMETER; 04430 mpu_reset_fifo(); 04431 04432 dmp.packet_length = 0; 04433 if (mask & DMP_FEATURE_SEND_RAW_ACCEL) 04434 dmp.packet_length += 6; 04435 if (mask & DMP_FEATURE_SEND_ANY_GYRO) 04436 dmp.packet_length += 6; 04437 if (mask & (DMP_FEATURE_LP_QUAT | DMP_FEATURE_6X_LP_QUAT)) 04438 dmp.packet_length += 16; 04439 if (mask & (DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT)) 04440 dmp.packet_length += 4; 04441 04442 return 0; 04443 } 04444 04445 /** 04446 * @brief Get list of currently enabled DMP features. 04447 * @param[out] Mask of enabled features. 04448 * @return 0 if successful. 04449 */ 04450 int dmp_get_enabled_features(unsigned short *mask) 04451 { 04452 mask[0] = dmp.feature_mask; 04453 return 0; 04454 } 04455 04456 /** 04457 * @brief Calibrate the gyro data in the DMP. 04458 * After eight seconds of no motion, the DMP will compute gyro biases and 04459 * subtract them from the quaternion output. If @e dmp_enable_feature is 04460 * called with @e DMP_FEATURE_SEND_CAL_GYRO, the biases will also be 04461 * subtracted from the gyro output. 04462 * @param[in] enable 1 to enable gyro calibration. 04463 * @return 0 if successful. 04464 */ 04465 int dmp_enable_gyro_cal(unsigned char enable) 04466 { 04467 if (enable) { 04468 unsigned char regs[9] = {0xb8, 0xaa, 0xb3, 0x8d, 0xb4, 0x98, 0x0d, 0x35, 0x5d}; 04469 return mpu_write_mem(CFG_MOTION_BIAS, 9, regs); 04470 } else { 04471 unsigned char regs[9] = {0xb8, 0xaa, 0xaa, 0xaa, 0xb0, 0x88, 0xc3, 0xc5, 0xc7}; 04472 return mpu_write_mem(CFG_MOTION_BIAS, 9, regs); 04473 } 04474 } 04475 04476 /** 04477 * @brief Generate 3-axis quaternions from the DMP. 04478 * In this driver, the 3-axis and 6-axis DMP quaternion features are mutually 04479 * exclusive. 04480 * @param[in] enable 1 to enable 3-axis quaternion. 04481 * @return 0 if successful. 04482 */ 04483 int dmp_enable_lp_quat(unsigned char enable) 04484 { 04485 unsigned char regs[4]; 04486 if (enable) { 04487 regs[0] = DINBC0; 04488 regs[1] = DINBC2; 04489 regs[2] = DINBC4; 04490 regs[3] = DINBC6; 04491 } 04492 else 04493 memset(regs, 0x8B, 4); 04494 04495 mpu_write_mem(CFG_LP_QUAT, 4, regs); 04496 04497 return mpu_reset_fifo(); 04498 } 04499 04500 /** 04501 * @brief Generate 6-axis quaternions from the DMP. 04502 * In this driver, the 3-axis and 6-axis DMP quaternion features are mutually 04503 * exclusive. 04504 * @param[in] enable 1 to enable 6-axis quaternion. 04505 * @return 0 if successful. 04506 */ 04507 int dmp_enable_6x_lp_quat(unsigned char enable) 04508 { 04509 unsigned char regs[4]; 04510 if (enable) { 04511 regs[0] = DINA20; 04512 regs[1] = DINA28; 04513 regs[2] = DINA30; 04514 regs[3] = DINA38; 04515 } else 04516 memset(regs, 0xA3, 4); 04517 04518 mpu_write_mem(CFG_8, 4, regs); 04519 04520 return mpu_reset_fifo(); 04521 } 04522 04523 /** 04524 * @brief Decode the four-byte gesture data and execute any callbacks. 04525 * @param[in] gesture Gesture data from DMP packet. 04526 * @return 0 if successful. 04527 */ 04528 static int decode_gesture(unsigned char *gesture) 04529 { 04530 unsigned char tap, android_orient; 04531 04532 android_orient = gesture[3] & 0xC0; 04533 tap = 0x3F & gesture[3]; 04534 04535 if (gesture[1] & INT_SRC_TAP) { 04536 unsigned char direction, count; 04537 direction = tap >> 3; 04538 count = (tap % 8) + 1; 04539 if (dmp.tap_cb) 04540 dmp.tap_cb(direction, count); 04541 } 04542 04543 if (gesture[1] & INT_SRC_ANDROID_ORIENT) { 04544 if (dmp.android_orient_cb) 04545 dmp.android_orient_cb(android_orient >> 6); 04546 } 04547 04548 return 0; 04549 } 04550 04551 /** 04552 * @brief Specify when a DMP interrupt should occur. 04553 * A DMP interrupt can be configured to trigger on either of the two 04554 * conditions below: 04555 * \n a. One FIFO period has elapsed (set by @e mpu_set_sample_rate). 04556 * \n b. A tap event has been detected. 04557 * @param[in] mode DMP_INT_GESTURE or DMP_INT_CONTINUOUS. 04558 * @return 0 if successful. 04559 */ 04560 int dmp_set_interrupt_mode(unsigned char mode) 04561 { 04562 const unsigned char regs_continuous[11] = 04563 {0xd8, 0xb1, 0xb9, 0xf3, 0x8b, 0xa3, 0x91, 0xb6, 0x09, 0xb4, 0xd9}; 04564 const unsigned char regs_gesture[11] = 04565 {0xda, 0xb1, 0xb9, 0xf3, 0x8b, 0xa3, 0x91, 0xb6, 0xda, 0xb4, 0xda}; 04566 04567 switch (mode) { 04568 case DMP_INT_CONTINUOUS: 04569 return mpu_write_mem(CFG_FIFO_ON_EVENT, 11, 04570 (unsigned char*)regs_continuous); 04571 case DMP_INT_GESTURE: 04572 return mpu_write_mem(CFG_FIFO_ON_EVENT, 11, 04573 (unsigned char*)regs_gesture); 04574 default: 04575 return -1; 04576 } 04577 } 04578 04579 /** 04580 * @brief Get one packet from the FIFO. 04581 * If @e sensors does not contain a particular sensor, disregard the data 04582 * returned to that pointer. 04583 * \n @e sensors can contain a combination of the following flags: 04584 * \n INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO 04585 * \n INV_XYZ_GYRO 04586 * \n INV_XYZ_ACCEL 04587 * \n INV_WXYZ_QUAT 04588 * \n If the FIFO has no new data, @e sensors will be zero. 04589 * \n If the FIFO is disabled, @e sensors will be zero and this function will 04590 * return a non-zero error code. 04591 * @param[out] gyro Gyro data in hardware units. 04592 * @param[out] accel Accel data in hardware units. 04593 * @param[out] quat 3-axis quaternion data in hardware units. 04594 * @param[out] timestamp Timestamp in milliseconds. 04595 * @param[out] sensors Mask of sensors read from FIFO. 04596 * @param[out] more Number of remaining packets. 04597 * @return 0 if successful. 04598 */ 04599 int dmp_read_fifo(short *gyro, short *accel, long *quat, 04600 unsigned long *timestamp, short *sensors, unsigned char *more) 04601 { 04602 unsigned char fifo_data[MAX_PACKET_LENGTH_2]; 04603 unsigned char ii = 0; 04604 04605 /* TODO: sensors[0] only changes when dmp_enable_feature is called. We can 04606 * cache this value and save some cycles. 04607 */ 04608 sensors[0] = 0; 04609 04610 /* Get a packet. */ 04611 if (mpu_read_fifo_stream(dmp.packet_length, fifo_data, more)) 04612 return -1; 04613 04614 /* Parse DMP packet. */ 04615 if (dmp.feature_mask & (DMP_FEATURE_LP_QUAT | DMP_FEATURE_6X_LP_QUAT)) { 04616 #ifdef FIFO_CORRUPTION_CHECK 04617 long quat_q14[4], quat_mag_sq; 04618 #endif 04619 quat[0] = ((long)fifo_data[0] << 24) | ((long)fifo_data[1] << 16) | 04620 ((long)fifo_data[2] << 8) | fifo_data[3]; 04621 quat[1] = ((long)fifo_data[4] << 24) | ((long)fifo_data[5] << 16) | 04622 ((long)fifo_data[6] << 8) | fifo_data[7]; 04623 quat[2] = ((long)fifo_data[8] << 24) | ((long)fifo_data[9] << 16) | 04624 ((long)fifo_data[10] << 8) | fifo_data[11]; 04625 quat[3] = ((long)fifo_data[12] << 24) | ((long)fifo_data[13] << 16) | 04626 ((long)fifo_data[14] << 8) | fifo_data[15]; 04627 ii += 16; 04628 #ifdef FIFO_CORRUPTION_CHECK 04629 /* We can detect a corrupted FIFO by monitoring the quaternion data and 04630 * ensuring that the magnitude is always normalized to one. This 04631 * shouldn't happen in normal operation, but if an I2C error occurs, 04632 * the FIFO reads might become misaligned. 04633 * 04634 * Let's start by scaling down the quaternion data to avoid long long 04635 * math. 04636 */ 04637 quat_q14[0] = quat[0] >> 16; 04638 quat_q14[1] = quat[1] >> 16; 04639 quat_q14[2] = quat[2] >> 16; 04640 quat_q14[3] = quat[3] >> 16; 04641 quat_mag_sq = quat_q14[0] * quat_q14[0] + quat_q14[1] * quat_q14[1] + 04642 quat_q14[2] * quat_q14[2] + quat_q14[3] * quat_q14[3]; 04643 if ((quat_mag_sq < QUAT_MAG_SQ_MIN) || 04644 (quat_mag_sq > QUAT_MAG_SQ_MAX)) { 04645 /* Quaternion is outside of the acceptable threshold. */ 04646 mpu_reset_fifo(); 04647 sensors[0] = 0; 04648 return -1; 04649 } 04650 sensors[0] |= INV_WXYZ_QUAT; 04651 #endif 04652 } 04653 04654 if (dmp.feature_mask & DMP_FEATURE_SEND_RAW_ACCEL) { 04655 accel[0] = ((short)fifo_data[ii+0] << 8) | fifo_data[ii+1]; 04656 accel[1] = ((short)fifo_data[ii+2] << 8) | fifo_data[ii+3]; 04657 accel[2] = ((short)fifo_data[ii+4] << 8) | fifo_data[ii+5]; 04658 ii += 6; 04659 sensors[0] |= INV_XYZ_ACCEL; 04660 } 04661 04662 if (dmp.feature_mask & DMP_FEATURE_SEND_ANY_GYRO) { 04663 gyro[0] = ((short)fifo_data[ii+0] << 8) | fifo_data[ii+1]; 04664 gyro[1] = ((short)fifo_data[ii+2] << 8) | fifo_data[ii+3]; 04665 gyro[2] = ((short)fifo_data[ii+4] << 8) | fifo_data[ii+5]; 04666 ii += 6; 04667 sensors[0] |= INV_XYZ_GYRO; 04668 } 04669 04670 /* Gesture data is at the end of the DMP packet. Parse it and call 04671 * the gesture callbacks (if registered). 04672 */ 04673 if (dmp.feature_mask & (DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT)) 04674 decode_gesture(fifo_data + ii); 04675 04676 get_ms(timestamp); 04677 return 0; 04678 } 04679 04680 /** 04681 * @brief Register a function to be executed on a tap event. 04682 * The tap direction is represented by one of the following: 04683 * \n TAP_X_UP 04684 * \n TAP_X_DOWN 04685 * \n TAP_Y_UP 04686 * \n TAP_Y_DOWN 04687 * \n TAP_Z_UP 04688 * \n TAP_Z_DOWN 04689 * @param[in] func Callback function. 04690 * @return 0 if successful. 04691 */ 04692 int dmp_register_tap_cb(void (*func)(unsigned char, unsigned char)) 04693 { 04694 dmp.tap_cb = func; 04695 return 0; 04696 } 04697 04698 /** 04699 * @brief Register a function to be executed on a android orientation event. 04700 * @param[in] func Callback function. 04701 * @return 0 if successful. 04702 */ 04703 int dmp_register_android_orient_cb(void (*func)(unsigned char)) 04704 { 04705 dmp.android_orient_cb = func; 04706 return 0; 04707 }
Generated on Sat Jul 16 2022 18:13:26 by 1.7.2