It is modified accordingly to work with sparkfun dmp library under mbed platform

Dependents:   MPU9250-dmp-bluepill MPU9250-dmp

Fork of MotionDriver_6_1 by Prosper Van

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers inv_mpu_dmp_motion_driver.c Source File

inv_mpu_dmp_motion_driver.c

Go to the documentation of this file.
00001 /*
00002  $License:
00003     Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
00004     See included License.txt for License information.
00005  $
00006  */
00007 /**
00008  *  @addtogroup  DRIVERS Sensor Driver Layer
00009  *  @brief       Hardware drivers to communicate with sensors via I2C.
00010  *
00011  *  @{
00012  *      @file       inv_mpu_dmp_motion_driver.c
00013  *      @brief      DMP image and interface functions.
00014  *      @details    All functions are preceded by the dmp_ prefix to
00015  *                  differentiate among MPL and general driver function calls.
00016  */
00017 #include <stdio.h>
00018 #include <stdint.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <math.h>
00022 #include "inv_mpu.h"
00023 #include "inv_mpu_dmp_motion_driver.h"
00024 #include "dmpKey.h"
00025 #include "dmpmap.h"
00026 
00027 /* The following functions must be defined for this platform:
00028  * i2c_write(unsigned char slave_addr, unsigned char reg_addr,
00029  *      unsigned char length, unsigned char const *data)
00030  * i2c_read(unsigned char slave_addr, unsigned char reg_addr,
00031  *      unsigned char length, unsigned char *data)
00032  * delay_ms(unsigned long num_ms)
00033  * get_ms(unsigned long *count)
00034  */
00035 #if defined EMPL_TARGET_STM32F4
00036 #include "i2c.h"   
00037 #include "main.h"
00038 #include "board-st_discovery.h"
00039    
00040 #define i2c_write   Sensors_I2C_WriteRegister
00041 #define i2c_read    Sensors_I2C_ReadRegister
00042 #define get_ms      get_tick_count
00043 
00044 #elif defined MOTION_DRIVER_TARGET_MSP430
00045 #include "msp430.h"
00046 #include "msp430_clock.h"
00047 #define delay_ms    msp430_delay_ms
00048 #define get_ms      msp430_get_clock_ms
00049 #define log_i(...)     do {} while (0)
00050 #define log_e(...)     do {} while (0)
00051 
00052 #elif defined EMPL_TARGET_MSP430
00053 #include "msp430.h"
00054 #include "msp430_clock.h"
00055 #include "log.h"
00056 #define delay_ms    msp430_delay_ms
00057 #define get_ms      msp430_get_clock_ms
00058 #define log_i       MPL_LOGI
00059 #define log_e       MPL_LOGE
00060 
00061 #elif defined EMPL_TARGET_UC3L0
00062 /* Instead of using the standard TWI driver from the ASF library, we're using
00063  * a TWI driver that follows the slave address + register address convention.
00064  */
00065 #include "delay.h"
00066 #include "sysclk.h"
00067 #include "log.h"
00068 #include "uc3l0_clock.h"
00069 /* delay_ms is a function already defined in ASF. */
00070 #define get_ms  uc3l0_get_clock_ms
00071 #define log_i       MPL_LOGI
00072 #define log_e       MPL_LOGE
00073 
00074 #else
00075 #warning    Your system is not officially supported. So, I will just include \
00076             mdcompat.h, however you must provide it.
00077 #include "mdcompat.h"
00078 #define log_i       MPL_LOGI
00079 #define log_e       MPL_LOGE
00080 
00081 #endif
00082 
00083 /* These defines are copied from dmpDefaultMPU6050.c in the general MPL
00084  * releases. These defines may change for each DMP image, so be sure to modify
00085  * these values when switching to a new image.
00086  */
00087 #define CFG_LP_QUAT             (2712)
00088 #define END_ORIENT_TEMP         (1866)
00089 #define CFG_27                  (2742)
00090 #define CFG_20                  (2224)
00091 #define CFG_23                  (2745)
00092 #define CFG_FIFO_ON_EVENT       (2690)
00093 #define END_PREDICTION_UPDATE   (1761)
00094 #define CGNOTICE_INTR           (2620)
00095 #define X_GRT_Y_TMP             (1358)
00096 #define CFG_DR_INT              (1029)
00097 #define CFG_AUTH                (1035)
00098 #define UPDATE_PROP_ROT         (1835)
00099 #define END_COMPARE_Y_X_TMP2    (1455)
00100 #define SKIP_X_GRT_Y_TMP        (1359)
00101 #define SKIP_END_COMPARE        (1435)
00102 #define FCFG_3                  (1088)
00103 #define FCFG_2                  (1066)
00104 #define FCFG_1                  (1062)
00105 #define END_COMPARE_Y_X_TMP3    (1434)
00106 #define FCFG_7                  (1073)
00107 #define FCFG_6                  (1106)
00108 #define FLAT_STATE_END          (1713)
00109 #define SWING_END_4             (1616)
00110 #define SWING_END_2             (1565)
00111 #define SWING_END_3             (1587)
00112 #define SWING_END_1             (1550)
00113 #define CFG_8                   (2718)
00114 #define CFG_15                  (2727)
00115 #define CFG_16                  (2746)
00116 #define CFG_EXT_GYRO_BIAS       (1189)
00117 #define END_COMPARE_Y_X_TMP     (1407)
00118 #define DO_NOT_UPDATE_PROP_ROT  (1839)
00119 #define CFG_7                   (1205)
00120 #define FLAT_STATE_END_TEMP     (1683)
00121 #define END_COMPARE_Y_X         (1484)
00122 #define SKIP_SWING_END_1        (1551)
00123 #define SKIP_SWING_END_3        (1588)
00124 #define SKIP_SWING_END_2        (1566)
00125 #define TILTG75_START           (1672)
00126 #define CFG_6                   (2753)
00127 #define TILTL75_END             (1669)
00128 #define END_ORIENT              (1884)
00129 #define CFG_FLICK_IN            (2573)
00130 #define TILTL75_START           (1643)
00131 #define CFG_MOTION_BIAS         (1208)
00132 #define X_GRT_Y                 (1408)
00133 #define TEMPLABEL               (2324)
00134 #define CFG_ANDROID_ORIENT_INT  (1853)
00135 #define CFG_GYRO_RAW_DATA       (2722)
00136 #define X_GRT_Y_TMP2            (1379)
00137 
00138 #define D_0_22                  (22+512)
00139 #define D_0_24                  (24+512)
00140 
00141 #define D_0_36                  (36)
00142 #define D_0_52                  (52)
00143 #define D_0_96                  (96)
00144 #define D_0_104                 (104)
00145 #define D_0_108                 (108)
00146 #define D_0_163                 (163)
00147 #define D_0_188                 (188)
00148 #define D_0_192                 (192)
00149 #define D_0_224                 (224)
00150 #define D_0_228                 (228)
00151 #define D_0_232                 (232)
00152 #define D_0_236                 (236)
00153 
00154 #define D_1_2                   (256 + 2)
00155 #define D_1_4                   (256 + 4)
00156 #define D_1_8                   (256 + 8)
00157 #define D_1_10                  (256 + 10)
00158 #define D_1_24                  (256 + 24)
00159 #define D_1_28                  (256 + 28)
00160 #define D_1_36                  (256 + 36)
00161 #define D_1_40                  (256 + 40)
00162 #define D_1_44                  (256 + 44)
00163 #define D_1_72                  (256 + 72)
00164 #define D_1_74                  (256 + 74)
00165 #define D_1_79                  (256 + 79)
00166 #define D_1_88                  (256 + 88)
00167 #define D_1_90                  (256 + 90)
00168 #define D_1_92                  (256 + 92)
00169 #define D_1_96                  (256 + 96)
00170 #define D_1_98                  (256 + 98)
00171 #define D_1_106                 (256 + 106)
00172 #define D_1_108                 (256 + 108)
00173 #define D_1_112                 (256 + 112)
00174 #define D_1_128                 (256 + 144)
00175 #define D_1_152                 (256 + 12)
00176 #define D_1_160                 (256 + 160)
00177 #define D_1_176                 (256 + 176)
00178 #define D_1_178                 (256 + 178)
00179 #define D_1_218                 (256 + 218)
00180 #define D_1_232                 (256 + 232)
00181 #define D_1_236                 (256 + 236)
00182 #define D_1_240                 (256 + 240)
00183 #define D_1_244                 (256 + 244)
00184 #define D_1_250                 (256 + 250)
00185 #define D_1_252                 (256 + 252)
00186 #define D_2_12                  (512 + 12)
00187 #define D_2_96                  (512 + 96)
00188 #define D_2_108                 (512 + 108)
00189 #define D_2_208                 (512 + 208)
00190 #define D_2_224                 (512 + 224)
00191 #define D_2_236                 (512 + 236)
00192 #define D_2_244                 (512 + 244)
00193 #define D_2_248                 (512 + 248)
00194 #define D_2_252                 (512 + 252)
00195 
00196 #define CPASS_BIAS_X            (35 * 16 + 4)
00197 #define CPASS_BIAS_Y            (35 * 16 + 8)
00198 #define CPASS_BIAS_Z            (35 * 16 + 12)
00199 #define CPASS_MTX_00            (36 * 16)
00200 #define CPASS_MTX_01            (36 * 16 + 4)
00201 #define CPASS_MTX_02            (36 * 16 + 8)
00202 #define CPASS_MTX_10            (36 * 16 + 12)
00203 #define CPASS_MTX_11            (37 * 16)
00204 #define CPASS_MTX_12            (37 * 16 + 4)
00205 #define CPASS_MTX_20            (37 * 16 + 8)
00206 #define CPASS_MTX_21            (37 * 16 + 12)
00207 #define CPASS_MTX_22            (43 * 16 + 12)
00208 #define D_EXT_GYRO_BIAS_X       (61 * 16)
00209 #define D_EXT_GYRO_BIAS_Y       (61 * 16) + 4
00210 #define D_EXT_GYRO_BIAS_Z       (61 * 16) + 8
00211 #define D_ACT0                  (40 * 16)
00212 #define D_ACSX                  (40 * 16 + 4)
00213 #define D_ACSY                  (40 * 16 + 8)
00214 #define D_ACSZ                  (40 * 16 + 12)
00215 
00216 #define FLICK_MSG               (45 * 16 + 4)
00217 #define FLICK_COUNTER           (45 * 16 + 8)
00218 #define FLICK_LOWER             (45 * 16 + 12)
00219 #define FLICK_UPPER             (46 * 16 + 12)
00220 
00221 #define D_AUTH_OUT              (992)
00222 #define D_AUTH_IN               (996)
00223 #define D_AUTH_A                (1000)
00224 #define D_AUTH_B                (1004)
00225 
00226 #define D_PEDSTD_BP_B           (768 + 0x1C)
00227 #define D_PEDSTD_HP_A           (768 + 0x78)
00228 #define D_PEDSTD_HP_B           (768 + 0x7C)
00229 #define D_PEDSTD_BP_A4          (768 + 0x40)
00230 #define D_PEDSTD_BP_A3          (768 + 0x44)
00231 #define D_PEDSTD_BP_A2          (768 + 0x48)
00232 #define D_PEDSTD_BP_A1          (768 + 0x4C)
00233 #define D_PEDSTD_INT_THRSH      (768 + 0x68)
00234 #define D_PEDSTD_CLIP           (768 + 0x6C)
00235 #define D_PEDSTD_SB             (768 + 0x28)
00236 #define D_PEDSTD_SB_TIME        (768 + 0x2C)
00237 #define D_PEDSTD_PEAKTHRSH      (768 + 0x98)
00238 #define D_PEDSTD_TIML           (768 + 0x2A)
00239 #define D_PEDSTD_TIMH           (768 + 0x2E)
00240 #define D_PEDSTD_PEAK           (768 + 0X94)
00241 #define D_PEDSTD_STEPCTR        (768 + 0x60)
00242 #define D_PEDSTD_TIMECTR        (964)
00243 #define D_PEDSTD_DECI           (768 + 0xA0)
00244 
00245 #define D_HOST_NO_MOT           (976)
00246 #define D_ACCEL_BIAS            (660)
00247 
00248 #define D_ORIENT_GAP            (76)
00249 
00250 #define D_TILT0_H               (48)
00251 #define D_TILT0_L               (50)
00252 #define D_TILT1_H               (52)
00253 #define D_TILT1_L               (54)
00254 #define D_TILT2_H               (56)
00255 #define D_TILT2_L               (58)
00256 #define D_TILT3_H               (60)
00257 #define D_TILT3_L               (62)
00258 
00259 #define DMP_CODE_SIZE           (3062)
00260 
00261 static const unsigned char dmp_memory[DMP_CODE_SIZE] = {
00262     /* bank # 0 */
00263     0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00,
00264     0x00, 0x65, 0x00, 0x54, 0xff, 0xef, 0x00, 0x00, 0xfa, 0x80, 0x00, 0x0b, 0x12, 0x82, 0x00, 0x01,
00265     0x03, 0x0c, 0x30, 0xc3, 0x0e, 0x8c, 0x8c, 0xe9, 0x14, 0xd5, 0x40, 0x02, 0x13, 0x71, 0x0f, 0x8e,
00266     0x38, 0x83, 0xf8, 0x83, 0x30, 0x00, 0xf8, 0x83, 0x25, 0x8e, 0xf8, 0x83, 0x30, 0x00, 0xf8, 0x83,
00267     0xff, 0xff, 0xff, 0xff, 0x0f, 0xfe, 0xa9, 0xd6, 0x24, 0x00, 0x04, 0x00, 0x1a, 0x82, 0x79, 0xa1,
00268     0x00, 0x00, 0x00, 0x3c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x38, 0x83, 0x6f, 0xa2,
00269     0x00, 0x3e, 0x03, 0x30, 0x40, 0x00, 0x00, 0x00, 0x02, 0xca, 0xe3, 0x09, 0x3e, 0x80, 0x00, 0x00,
00270     0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
00271     0x00, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x6e, 0x00, 0x00, 0x06, 0x92, 0x0a, 0x16, 0xc0, 0xdf,
00272     0xff, 0xff, 0x02, 0x56, 0xfd, 0x8c, 0xd3, 0x77, 0xff, 0xe1, 0xc4, 0x96, 0xe0, 0xc5, 0xbe, 0xaa,
00273     0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0b, 0x2b, 0x00, 0x00, 0x16, 0x57, 0x00, 0x00, 0x03, 0x59,
00274     0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0xfa, 0x00, 0x02, 0x6c, 0x1d, 0x00, 0x00, 0x00, 0x00,
00275     0x3f, 0xff, 0xdf, 0xeb, 0x00, 0x3e, 0xb3, 0xb6, 0x00, 0x0d, 0x22, 0x78, 0x00, 0x00, 0x2f, 0x3c,
00276     0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x42, 0xb5, 0x00, 0x00, 0x39, 0xa2, 0x00, 0x00, 0xb3, 0x65,
00277     0xd9, 0x0e, 0x9f, 0xc9, 0x1d, 0xcf, 0x4c, 0x34, 0x30, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
00278     0x3b, 0xb6, 0x7a, 0xe8, 0x00, 0x64, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00279     /* bank # 1 */
00280     0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0xfa, 0x92, 0x10, 0x00, 0x22, 0x5e, 0x00, 0x0d, 0x22, 0x9f,
00281     0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0xff, 0x46, 0x00, 0x00, 0x63, 0xd4, 0x00, 0x00,
00282     0x10, 0x00, 0x00, 0x00, 0x04, 0xd6, 0x00, 0x00, 0x04, 0xcc, 0x00, 0x00, 0x04, 0xcc, 0x00, 0x00,
00283     0x00, 0x00, 0x10, 0x72, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00284     0x00, 0x06, 0x00, 0x02, 0x00, 0x05, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00,
00285     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x00, 0x64, 0x00, 0x20, 0x00, 0x00,
00286     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00,
00287     0x00, 0x00, 0x00, 0x32, 0xf8, 0x98, 0x00, 0x00, 0xff, 0x65, 0x00, 0x00, 0x83, 0x0f, 0x00, 0x00,
00288     0xff, 0x9b, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00289     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00290     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
00291     0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xb2, 0x6a, 0x00, 0x02, 0x00, 0x00,
00292     0x00, 0x01, 0xfb, 0x83, 0x00, 0x68, 0x00, 0x00, 0x00, 0xd9, 0xfc, 0x00, 0x7c, 0xf1, 0xff, 0x83,
00293     0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x64, 0x03, 0xe8, 0x00, 0x64, 0x00, 0x28,
00294     0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x16, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
00295     0x00, 0x00, 0x10, 0x00, 0x00, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf4, 0x00, 0x00, 0x10, 0x00,
00296     /* bank # 2 */
00297     0x00, 0x28, 0x00, 0x00, 0xff, 0xff, 0x45, 0x81, 0xff, 0xff, 0xfa, 0x72, 0x00, 0x00, 0x00, 0x00,
00298     0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x05, 0x00, 0x05, 0xba, 0xc6, 0x00, 0x47, 0x78, 0xa2,
00299     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x14,
00300     0x00, 0x00, 0x25, 0x4d, 0x00, 0x2f, 0x70, 0x6d, 0x00, 0x00, 0x05, 0xae, 0x00, 0x0c, 0x02, 0xd0,
00301     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00302     0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00303     0x00, 0x64, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00304     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00305     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00306     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00307     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00308     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00309     0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e,
00310     0x00, 0x00, 0x0a, 0xc7, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xff, 0xff, 0xff, 0x9c,
00311     0x00, 0x00, 0x0b, 0x2b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x64,
00312     0xff, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00313     /* bank # 3 */
00314     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00315     0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x24, 0x26, 0xd3,
00316     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x10, 0x00, 0x96, 0x00, 0x3c,
00317     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00318     0x0c, 0x0a, 0x4e, 0x68, 0xcd, 0xcf, 0x77, 0x09, 0x50, 0x16, 0x67, 0x59, 0xc6, 0x19, 0xce, 0x82,
00319     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00320     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xd7, 0x84, 0x00, 0x03, 0x00, 0x00, 0x00,
00321     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x93, 0x8f, 0x9d, 0x1e, 0x1b, 0x1c, 0x19,
00322     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00323     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x18, 0x85, 0x00, 0x00, 0x40, 0x00,
00324     0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00325     0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00326     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00327     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00328     0x00, 0x00, 0x00, 0x00, 0x67, 0x7d, 0xdf, 0x7e, 0x72, 0x90, 0x2e, 0x55, 0x4c, 0xf6, 0xe6, 0x88,
00329     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00330 
00331     /* bank # 4 */
00332     0xd8, 0xdc, 0xb4, 0xb8, 0xb0, 0xd8, 0xb9, 0xab, 0xf3, 0xf8, 0xfa, 0xb3, 0xb7, 0xbb, 0x8e, 0x9e,
00333     0xae, 0xf1, 0x32, 0xf5, 0x1b, 0xf1, 0xb4, 0xb8, 0xb0, 0x80, 0x97, 0xf1, 0xa9, 0xdf, 0xdf, 0xdf,
00334     0xaa, 0xdf, 0xdf, 0xdf, 0xf2, 0xaa, 0xc5, 0xcd, 0xc7, 0xa9, 0x0c, 0xc9, 0x2c, 0x97, 0xf1, 0xa9,
00335     0x89, 0x26, 0x46, 0x66, 0xb2, 0x89, 0x99, 0xa9, 0x2d, 0x55, 0x7d, 0xb0, 0xb0, 0x8a, 0xa8, 0x96,
00336     0x36, 0x56, 0x76, 0xf1, 0xba, 0xa3, 0xb4, 0xb2, 0x80, 0xc0, 0xb8, 0xa8, 0x97, 0x11, 0xb2, 0x83,
00337     0x98, 0xba, 0xa3, 0xf0, 0x24, 0x08, 0x44, 0x10, 0x64, 0x18, 0xb2, 0xb9, 0xb4, 0x98, 0x83, 0xf1,
00338     0xa3, 0x29, 0x55, 0x7d, 0xba, 0xb5, 0xb1, 0xa3, 0x83, 0x93, 0xf0, 0x00, 0x28, 0x50, 0xf5, 0xb2,
00339     0xb6, 0xaa, 0x83, 0x93, 0x28, 0x54, 0x7c, 0xf1, 0xb9, 0xa3, 0x82, 0x93, 0x61, 0xba, 0xa2, 0xda,
00340     0xde, 0xdf, 0xdb, 0x81, 0x9a, 0xb9, 0xae, 0xf5, 0x60, 0x68, 0x70, 0xf1, 0xda, 0xba, 0xa2, 0xdf,
00341     0xd9, 0xba, 0xa2, 0xfa, 0xb9, 0xa3, 0x82, 0x92, 0xdb, 0x31, 0xba, 0xa2, 0xd9, 0xba, 0xa2, 0xf8,
00342     0xdf, 0x85, 0xa4, 0xd0, 0xc1, 0xbb, 0xad, 0x83, 0xc2, 0xc5, 0xc7, 0xb8, 0xa2, 0xdf, 0xdf, 0xdf,
00343     0xba, 0xa0, 0xdf, 0xdf, 0xdf, 0xd8, 0xd8, 0xf1, 0xb8, 0xaa, 0xb3, 0x8d, 0xb4, 0x98, 0x0d, 0x35,
00344     0x5d, 0xb2, 0xb6, 0xba, 0xaf, 0x8c, 0x96, 0x19, 0x8f, 0x9f, 0xa7, 0x0e, 0x16, 0x1e, 0xb4, 0x9a,
00345     0xb8, 0xaa, 0x87, 0x2c, 0x54, 0x7c, 0xba, 0xa4, 0xb0, 0x8a, 0xb6, 0x91, 0x32, 0x56, 0x76, 0xb2,
00346     0x84, 0x94, 0xa4, 0xc8, 0x08, 0xcd, 0xd8, 0xb8, 0xb4, 0xb0, 0xf1, 0x99, 0x82, 0xa8, 0x2d, 0x55,
00347     0x7d, 0x98, 0xa8, 0x0e, 0x16, 0x1e, 0xa2, 0x2c, 0x54, 0x7c, 0x92, 0xa4, 0xf0, 0x2c, 0x50, 0x78,
00348     /* bank # 5 */
00349     0xf1, 0x84, 0xa8, 0x98, 0xc4, 0xcd, 0xfc, 0xd8, 0x0d, 0xdb, 0xa8, 0xfc, 0x2d, 0xf3, 0xd9, 0xba,
00350     0xa6, 0xf8, 0xda, 0xba, 0xa6, 0xde, 0xd8, 0xba, 0xb2, 0xb6, 0x86, 0x96, 0xa6, 0xd0, 0xf3, 0xc8,
00351     0x41, 0xda, 0xa6, 0xc8, 0xf8, 0xd8, 0xb0, 0xb4, 0xb8, 0x82, 0xa8, 0x92, 0xf5, 0x2c, 0x54, 0x88,
00352     0x98, 0xf1, 0x35, 0xd9, 0xf4, 0x18, 0xd8, 0xf1, 0xa2, 0xd0, 0xf8, 0xf9, 0xa8, 0x84, 0xd9, 0xc7,
00353     0xdf, 0xf8, 0xf8, 0x83, 0xc5, 0xda, 0xdf, 0x69, 0xdf, 0x83, 0xc1, 0xd8, 0xf4, 0x01, 0x14, 0xf1,
00354     0xa8, 0x82, 0x4e, 0xa8, 0x84, 0xf3, 0x11, 0xd1, 0x82, 0xf5, 0xd9, 0x92, 0x28, 0x97, 0x88, 0xf1,
00355     0x09, 0xf4, 0x1c, 0x1c, 0xd8, 0x84, 0xa8, 0xf3, 0xc0, 0xf9, 0xd1, 0xd9, 0x97, 0x82, 0xf1, 0x29,
00356     0xf4, 0x0d, 0xd8, 0xf3, 0xf9, 0xf9, 0xd1, 0xd9, 0x82, 0xf4, 0xc2, 0x03, 0xd8, 0xde, 0xdf, 0x1a,
00357     0xd8, 0xf1, 0xa2, 0xfa, 0xf9, 0xa8, 0x84, 0x98, 0xd9, 0xc7, 0xdf, 0xf8, 0xf8, 0xf8, 0x83, 0xc7,
00358     0xda, 0xdf, 0x69, 0xdf, 0xf8, 0x83, 0xc3, 0xd8, 0xf4, 0x01, 0x14, 0xf1, 0x98, 0xa8, 0x82, 0x2e,
00359     0xa8, 0x84, 0xf3, 0x11, 0xd1, 0x82, 0xf5, 0xd9, 0x92, 0x50, 0x97, 0x88, 0xf1, 0x09, 0xf4, 0x1c,
00360     0xd8, 0x84, 0xa8, 0xf3, 0xc0, 0xf8, 0xf9, 0xd1, 0xd9, 0x97, 0x82, 0xf1, 0x49, 0xf4, 0x0d, 0xd8,
00361     0xf3, 0xf9, 0xf9, 0xd1, 0xd9, 0x82, 0xf4, 0xc4, 0x03, 0xd8, 0xde, 0xdf, 0xd8, 0xf1, 0xad, 0x88,
00362     0x98, 0xcc, 0xa8, 0x09, 0xf9, 0xd9, 0x82, 0x92, 0xa8, 0xf5, 0x7c, 0xf1, 0x88, 0x3a, 0xcf, 0x94,
00363     0x4a, 0x6e, 0x98, 0xdb, 0x69, 0x31, 0xda, 0xad, 0xf2, 0xde, 0xf9, 0xd8, 0x87, 0x95, 0xa8, 0xf2,
00364     0x21, 0xd1, 0xda, 0xa5, 0xf9, 0xf4, 0x17, 0xd9, 0xf1, 0xae, 0x8e, 0xd0, 0xc0, 0xc3, 0xae, 0x82,
00365     /* bank # 6 */
00366     0xc6, 0x84, 0xc3, 0xa8, 0x85, 0x95, 0xc8, 0xa5, 0x88, 0xf2, 0xc0, 0xf1, 0xf4, 0x01, 0x0e, 0xf1,
00367     0x8e, 0x9e, 0xa8, 0xc6, 0x3e, 0x56, 0xf5, 0x54, 0xf1, 0x88, 0x72, 0xf4, 0x01, 0x15, 0xf1, 0x98,
00368     0x45, 0x85, 0x6e, 0xf5, 0x8e, 0x9e, 0x04, 0x88, 0xf1, 0x42, 0x98, 0x5a, 0x8e, 0x9e, 0x06, 0x88,
00369     0x69, 0xf4, 0x01, 0x1c, 0xf1, 0x98, 0x1e, 0x11, 0x08, 0xd0, 0xf5, 0x04, 0xf1, 0x1e, 0x97, 0x02,
00370     0x02, 0x98, 0x36, 0x25, 0xdb, 0xf9, 0xd9, 0x85, 0xa5, 0xf3, 0xc1, 0xda, 0x85, 0xa5, 0xf3, 0xdf,
00371     0xd8, 0x85, 0x95, 0xa8, 0xf3, 0x09, 0xda, 0xa5, 0xfa, 0xd8, 0x82, 0x92, 0xa8, 0xf5, 0x78, 0xf1,
00372     0x88, 0x1a, 0x84, 0x9f, 0x26, 0x88, 0x98, 0x21, 0xda, 0xf4, 0x1d, 0xf3, 0xd8, 0x87, 0x9f, 0x39,
00373     0xd1, 0xaf, 0xd9, 0xdf, 0xdf, 0xfb, 0xf9, 0xf4, 0x0c, 0xf3, 0xd8, 0xfa, 0xd0, 0xf8, 0xda, 0xf9,
00374     0xf9, 0xd0, 0xdf, 0xd9, 0xf9, 0xd8, 0xf4, 0x0b, 0xd8, 0xf3, 0x87, 0x9f, 0x39, 0xd1, 0xaf, 0xd9,
00375     0xdf, 0xdf, 0xf4, 0x1d, 0xf3, 0xd8, 0xfa, 0xfc, 0xa8, 0x69, 0xf9, 0xf9, 0xaf, 0xd0, 0xda, 0xde,
00376     0xfa, 0xd9, 0xf8, 0x8f, 0x9f, 0xa8, 0xf1, 0xcc, 0xf3, 0x98, 0xdb, 0x45, 0xd9, 0xaf, 0xdf, 0xd0,
00377     0xf8, 0xd8, 0xf1, 0x8f, 0x9f, 0xa8, 0xca, 0xf3, 0x88, 0x09, 0xda, 0xaf, 0x8f, 0xcb, 0xf8, 0xd8,
00378     0xf2, 0xad, 0x97, 0x8d, 0x0c, 0xd9, 0xa5, 0xdf, 0xf9, 0xba, 0xa6, 0xf3, 0xfa, 0xf4, 0x12, 0xf2,
00379     0xd8, 0x95, 0x0d, 0xd1, 0xd9, 0xba, 0xa6, 0xf3, 0xfa, 0xda, 0xa5, 0xf2, 0xc1, 0xba, 0xa6, 0xf3,
00380     0xdf, 0xd8, 0xf1, 0xba, 0xb2, 0xb6, 0x86, 0x96, 0xa6, 0xd0, 0xca, 0xf3, 0x49, 0xda, 0xa6, 0xcb,
00381     0xf8, 0xd8, 0xb0, 0xb4, 0xb8, 0xd8, 0xad, 0x84, 0xf2, 0xc0, 0xdf, 0xf1, 0x8f, 0xcb, 0xc3, 0xa8,
00382     /* bank # 7 */
00383     0xb2, 0xb6, 0x86, 0x96, 0xc8, 0xc1, 0xcb, 0xc3, 0xf3, 0xb0, 0xb4, 0x88, 0x98, 0xa8, 0x21, 0xdb,
00384     0x71, 0x8d, 0x9d, 0x71, 0x85, 0x95, 0x21, 0xd9, 0xad, 0xf2, 0xfa, 0xd8, 0x85, 0x97, 0xa8, 0x28,
00385     0xd9, 0xf4, 0x08, 0xd8, 0xf2, 0x8d, 0x29, 0xda, 0xf4, 0x05, 0xd9, 0xf2, 0x85, 0xa4, 0xc2, 0xf2,
00386     0xd8, 0xa8, 0x8d, 0x94, 0x01, 0xd1, 0xd9, 0xf4, 0x11, 0xf2, 0xd8, 0x87, 0x21, 0xd8, 0xf4, 0x0a,
00387     0xd8, 0xf2, 0x84, 0x98, 0xa8, 0xc8, 0x01, 0xd1, 0xd9, 0xf4, 0x11, 0xd8, 0xf3, 0xa4, 0xc8, 0xbb,
00388     0xaf, 0xd0, 0xf2, 0xde, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xd8, 0xf1, 0xb8, 0xf6,
00389     0xb5, 0xb9, 0xb0, 0x8a, 0x95, 0xa3, 0xde, 0x3c, 0xa3, 0xd9, 0xf8, 0xd8, 0x5c, 0xa3, 0xd9, 0xf8,
00390     0xd8, 0x7c, 0xa3, 0xd9, 0xf8, 0xd8, 0xf8, 0xf9, 0xd1, 0xa5, 0xd9, 0xdf, 0xda, 0xfa, 0xd8, 0xb1,
00391     0x85, 0x30, 0xf7, 0xd9, 0xde, 0xd8, 0xf8, 0x30, 0xad, 0xda, 0xde, 0xd8, 0xf2, 0xb4, 0x8c, 0x99,
00392     0xa3, 0x2d, 0x55, 0x7d, 0xa0, 0x83, 0xdf, 0xdf, 0xdf, 0xb5, 0x91, 0xa0, 0xf6, 0x29, 0xd9, 0xfb,
00393     0xd8, 0xa0, 0xfc, 0x29, 0xd9, 0xfa, 0xd8, 0xa0, 0xd0, 0x51, 0xd9, 0xf8, 0xd8, 0xfc, 0x51, 0xd9,
00394     0xf9, 0xd8, 0x79, 0xd9, 0xfb, 0xd8, 0xa0, 0xd0, 0xfc, 0x79, 0xd9, 0xfa, 0xd8, 0xa1, 0xf9, 0xf9,
00395     0xf9, 0xf9, 0xf9, 0xa0, 0xda, 0xdf, 0xdf, 0xdf, 0xd8, 0xa1, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xac,
00396     0xde, 0xf8, 0xad, 0xde, 0x83, 0x93, 0xac, 0x2c, 0x54, 0x7c, 0xf1, 0xa8, 0xdf, 0xdf, 0xdf, 0xf6,
00397     0x9d, 0x2c, 0xda, 0xa0, 0xdf, 0xd9, 0xfa, 0xdb, 0x2d, 0xf8, 0xd8, 0xa8, 0x50, 0xda, 0xa0, 0xd0,
00398     0xde, 0xd9, 0xd0, 0xf8, 0xf8, 0xf8, 0xdb, 0x55, 0xf8, 0xd8, 0xa8, 0x78, 0xda, 0xa0, 0xd0, 0xdf,
00399     /* bank # 8 */
00400     0xd9, 0xd0, 0xfa, 0xf8, 0xf8, 0xf8, 0xf8, 0xdb, 0x7d, 0xf8, 0xd8, 0x9c, 0xa8, 0x8c, 0xf5, 0x30,
00401     0xdb, 0x38, 0xd9, 0xd0, 0xde, 0xdf, 0xa0, 0xd0, 0xde, 0xdf, 0xd8, 0xa8, 0x48, 0xdb, 0x58, 0xd9,
00402     0xdf, 0xd0, 0xde, 0xa0, 0xdf, 0xd0, 0xde, 0xd8, 0xa8, 0x68, 0xdb, 0x70, 0xd9, 0xdf, 0xdf, 0xa0,
00403     0xdf, 0xdf, 0xd8, 0xf1, 0xa8, 0x88, 0x90, 0x2c, 0x54, 0x7c, 0x98, 0xa8, 0xd0, 0x5c, 0x38, 0xd1,
00404     0xda, 0xf2, 0xae, 0x8c, 0xdf, 0xf9, 0xd8, 0xb0, 0x87, 0xa8, 0xc1, 0xc1, 0xb1, 0x88, 0xa8, 0xc6,
00405     0xf9, 0xf9, 0xda, 0x36, 0xd8, 0xa8, 0xf9, 0xda, 0x36, 0xd8, 0xa8, 0xf9, 0xda, 0x36, 0xd8, 0xa8,
00406     0xf9, 0xda, 0x36, 0xd8, 0xa8, 0xf9, 0xda, 0x36, 0xd8, 0xf7, 0x8d, 0x9d, 0xad, 0xf8, 0x18, 0xda,
00407     0xf2, 0xae, 0xdf, 0xd8, 0xf7, 0xad, 0xfa, 0x30, 0xd9, 0xa4, 0xde, 0xf9, 0xd8, 0xf2, 0xae, 0xde,
00408     0xfa, 0xf9, 0x83, 0xa7, 0xd9, 0xc3, 0xc5, 0xc7, 0xf1, 0x88, 0x9b, 0xa7, 0x7a, 0xad, 0xf7, 0xde,
00409     0xdf, 0xa4, 0xf8, 0x84, 0x94, 0x08, 0xa7, 0x97, 0xf3, 0x00, 0xae, 0xf2, 0x98, 0x19, 0xa4, 0x88,
00410     0xc6, 0xa3, 0x94, 0x88, 0xf6, 0x32, 0xdf, 0xf2, 0x83, 0x93, 0xdb, 0x09, 0xd9, 0xf2, 0xaa, 0xdf,
00411     0xd8, 0xd8, 0xae, 0xf8, 0xf9, 0xd1, 0xda, 0xf3, 0xa4, 0xde, 0xa7, 0xf1, 0x88, 0x9b, 0x7a, 0xd8,
00412     0xf3, 0x84, 0x94, 0xae, 0x19, 0xf9, 0xda, 0xaa, 0xf1, 0xdf, 0xd8, 0xa8, 0x81, 0xc0, 0xc3, 0xc5,
00413     0xc7, 0xa3, 0x92, 0x83, 0xf6, 0x28, 0xad, 0xde, 0xd9, 0xf8, 0xd8, 0xa3, 0x50, 0xad, 0xd9, 0xf8,
00414     0xd8, 0xa3, 0x78, 0xad, 0xd9, 0xf8, 0xd8, 0xf8, 0xf9, 0xd1, 0xa1, 0xda, 0xde, 0xc3, 0xc5, 0xc7,
00415     0xd8, 0xa1, 0x81, 0x94, 0xf8, 0x18, 0xf2, 0xb0, 0x89, 0xac, 0xc3, 0xc5, 0xc7, 0xf1, 0xd8, 0xb8,
00416     /* bank # 9 */
00417     0xb4, 0xb0, 0x97, 0x86, 0xa8, 0x31, 0x9b, 0x06, 0x99, 0x07, 0xab, 0x97, 0x28, 0x88, 0x9b, 0xf0,
00418     0x0c, 0x20, 0x14, 0x40, 0xb0, 0xb4, 0xb8, 0xf0, 0xa8, 0x8a, 0x9a, 0x28, 0x50, 0x78, 0xb7, 0x9b,
00419     0xa8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, 0xf1, 0xbb, 0xab,
00420     0x88, 0x00, 0x2c, 0x54, 0x7c, 0xf0, 0xb3, 0x8b, 0xb8, 0xa8, 0x04, 0x28, 0x50, 0x78, 0xf1, 0xb0,
00421     0x88, 0xb4, 0x97, 0x26, 0xa8, 0x59, 0x98, 0xbb, 0xab, 0xb3, 0x8b, 0x02, 0x26, 0x46, 0x66, 0xb0,
00422     0xb8, 0xf0, 0x8a, 0x9c, 0xa8, 0x29, 0x51, 0x79, 0x8b, 0x29, 0x51, 0x79, 0x8a, 0x24, 0x70, 0x59,
00423     0x8b, 0x20, 0x58, 0x71, 0x8a, 0x44, 0x69, 0x38, 0x8b, 0x39, 0x40, 0x68, 0x8a, 0x64, 0x48, 0x31,
00424     0x8b, 0x30, 0x49, 0x60, 0x88, 0xf1, 0xac, 0x00, 0x2c, 0x54, 0x7c, 0xf0, 0x8c, 0xa8, 0x04, 0x28,
00425     0x50, 0x78, 0xf1, 0x88, 0x97, 0x26, 0xa8, 0x59, 0x98, 0xac, 0x8c, 0x02, 0x26, 0x46, 0x66, 0xf0,
00426     0x89, 0x9c, 0xa8, 0x29, 0x51, 0x79, 0x24, 0x70, 0x59, 0x44, 0x69, 0x38, 0x64, 0x48, 0x31, 0xa9,
00427     0x88, 0x09, 0x20, 0x59, 0x70, 0xab, 0x11, 0x38, 0x40, 0x69, 0xa8, 0x19, 0x31, 0x48, 0x60, 0x8c,
00428     0xa8, 0x3c, 0x41, 0x5c, 0x20, 0x7c, 0x00, 0xf1, 0x87, 0x98, 0x19, 0x86, 0xa8, 0x6e, 0x76, 0x7e,
00429     0xa9, 0x99, 0x88, 0x2d, 0x55, 0x7d, 0xd8, 0xb1, 0xb5, 0xb9, 0xa3, 0xdf, 0xdf, 0xdf, 0xae, 0xd0,
00430     0xdf, 0xaa, 0xd0, 0xde, 0xf2, 0xab, 0xf8, 0xf9, 0xd9, 0xb0, 0x87, 0xc4, 0xaa, 0xf1, 0xdf, 0xdf,
00431     0xbb, 0xaf, 0xdf, 0xdf, 0xb9, 0xd8, 0xb1, 0xf1, 0xa3, 0x97, 0x8e, 0x60, 0xdf, 0xb0, 0x84, 0xf2,
00432     0xc8, 0xf8, 0xf9, 0xd9, 0xde, 0xd8, 0x93, 0x85, 0xf1, 0x4a, 0xb1, 0x83, 0xa3, 0x08, 0xb5, 0x83,
00433     /* bank # 10 */
00434     0x9a, 0x08, 0x10, 0xb7, 0x9f, 0x10, 0xd8, 0xf1, 0xb0, 0xba, 0xae, 0xb0, 0x8a, 0xc2, 0xb2, 0xb6,
00435     0x8e, 0x9e, 0xf1, 0xfb, 0xd9, 0xf4, 0x1d, 0xd8, 0xf9, 0xd9, 0x0c, 0xf1, 0xd8, 0xf8, 0xf8, 0xad,
00436     0x61, 0xd9, 0xae, 0xfb, 0xd8, 0xf4, 0x0c, 0xf1, 0xd8, 0xf8, 0xf8, 0xad, 0x19, 0xd9, 0xae, 0xfb,
00437     0xdf, 0xd8, 0xf4, 0x16, 0xf1, 0xd8, 0xf8, 0xad, 0x8d, 0x61, 0xd9, 0xf4, 0xf4, 0xac, 0xf5, 0x9c,
00438     0x9c, 0x8d, 0xdf, 0x2b, 0xba, 0xb6, 0xae, 0xfa, 0xf8, 0xf4, 0x0b, 0xd8, 0xf1, 0xae, 0xd0, 0xf8,
00439     0xad, 0x51, 0xda, 0xae, 0xfa, 0xf8, 0xf1, 0xd8, 0xb9, 0xb1, 0xb6, 0xa3, 0x83, 0x9c, 0x08, 0xb9,
00440     0xb1, 0x83, 0x9a, 0xb5, 0xaa, 0xc0, 0xfd, 0x30, 0x83, 0xb7, 0x9f, 0x10, 0xb5, 0x8b, 0x93, 0xf2,
00441     0x02, 0x02, 0xd1, 0xab, 0xda, 0xde, 0xd8, 0xf1, 0xb0, 0x80, 0xba, 0xab, 0xc0, 0xc3, 0xb2, 0x84,
00442     0xc1, 0xc3, 0xd8, 0xb1, 0xb9, 0xf3, 0x8b, 0xa3, 0x91, 0xb6, 0x09, 0xb4, 0xd9, 0xab, 0xde, 0xb0,
00443     0x87, 0x9c, 0xb9, 0xa3, 0xdd, 0xf1, 0xb3, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0xb0, 0x87, 0xa3, 0xa3,
00444     0xa3, 0xa3, 0xb2, 0x8b, 0xb6, 0x9b, 0xf2, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
00445     0xa3, 0xf1, 0xb0, 0x87, 0xb5, 0x9a, 0xa3, 0xf3, 0x9b, 0xa3, 0xa3, 0xdc, 0xba, 0xac, 0xdf, 0xb9,
00446     0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
00447     0xd8, 0xd8, 0xd8, 0xbb, 0xb3, 0xb7, 0xf1, 0xaa, 0xf9, 0xda, 0xff, 0xd9, 0x80, 0x9a, 0xaa, 0x28,
00448     0xb4, 0x80, 0x98, 0xa7, 0x20, 0xb7, 0x97, 0x87, 0xa8, 0x66, 0x88, 0xf0, 0x79, 0x51, 0xf1, 0x90,
00449     0x2c, 0x87, 0x0c, 0xa7, 0x81, 0x97, 0x62, 0x93, 0xf0, 0x71, 0x71, 0x60, 0x85, 0x94, 0x01, 0x29,
00450     /* bank # 11 */
00451     0x51, 0x79, 0x90, 0xa5, 0xf1, 0x28, 0x4c, 0x6c, 0x87, 0x0c, 0x95, 0x18, 0x85, 0x78, 0xa3, 0x83,
00452     0x90, 0x28, 0x4c, 0x6c, 0x88, 0x6c, 0xd8, 0xf3, 0xa2, 0x82, 0x00, 0xf2, 0x10, 0xa8, 0x92, 0x19,
00453     0x80, 0xa2, 0xf2, 0xd9, 0x26, 0xd8, 0xf1, 0x88, 0xa8, 0x4d, 0xd9, 0x48, 0xd8, 0x96, 0xa8, 0x39,
00454     0x80, 0xd9, 0x3c, 0xd8, 0x95, 0x80, 0xa8, 0x39, 0xa6, 0x86, 0x98, 0xd9, 0x2c, 0xda, 0x87, 0xa7,
00455     0x2c, 0xd8, 0xa8, 0x89, 0x95, 0x19, 0xa9, 0x80, 0xd9, 0x38, 0xd8, 0xa8, 0x89, 0x39, 0xa9, 0x80,
00456     0xda, 0x3c, 0xd8, 0xa8, 0x2e, 0xa8, 0x39, 0x90, 0xd9, 0x0c, 0xd8, 0xa8, 0x95, 0x31, 0x98, 0xd9,
00457     0x0c, 0xd8, 0xa8, 0x09, 0xd9, 0xff, 0xd8, 0x01, 0xda, 0xff, 0xd8, 0x95, 0x39, 0xa9, 0xda, 0x26,
00458     0xff, 0xd8, 0x90, 0xa8, 0x0d, 0x89, 0x99, 0xa8, 0x10, 0x80, 0x98, 0x21, 0xda, 0x2e, 0xd8, 0x89,
00459     0x99, 0xa8, 0x31, 0x80, 0xda, 0x2e, 0xd8, 0xa8, 0x86, 0x96, 0x31, 0x80, 0xda, 0x2e, 0xd8, 0xa8,
00460     0x87, 0x31, 0x80, 0xda, 0x2e, 0xd8, 0xa8, 0x82, 0x92, 0xf3, 0x41, 0x80, 0xf1, 0xd9, 0x2e, 0xd8,
00461     0xa8, 0x82, 0xf3, 0x19, 0x80, 0xf1, 0xd9, 0x2e, 0xd8, 0x82, 0xac, 0xf3, 0xc0, 0xa2, 0x80, 0x22,
00462     0xf1, 0xa6, 0x2e, 0xa7, 0x2e, 0xa9, 0x22, 0x98, 0xa8, 0x29, 0xda, 0xac, 0xde, 0xff, 0xd8, 0xa2,
00463     0xf2, 0x2a, 0xf1, 0xa9, 0x2e, 0x82, 0x92, 0xa8, 0xf2, 0x31, 0x80, 0xa6, 0x96, 0xf1, 0xd9, 0x00,
00464     0xac, 0x8c, 0x9c, 0x0c, 0x30, 0xac, 0xde, 0xd0, 0xde, 0xff, 0xd8, 0x8c, 0x9c, 0xac, 0xd0, 0x10,
00465     0xac, 0xde, 0x80, 0x92, 0xa2, 0xf2, 0x4c, 0x82, 0xa8, 0xf1, 0xca, 0xf2, 0x35, 0xf1, 0x96, 0x88,
00466     0xa6, 0xd9, 0x00, 0xd8, 0xf1, 0xff
00467 };
00468 
00469 static const unsigned short sStartAddress = 0x0400;
00470 
00471 /* END OF SECTION COPIED FROM dmpDefaultMPU6050.c */
00472 
00473 #define INT_SRC_TAP             (0x01)
00474 #define INT_SRC_ANDROID_ORIENT  (0x08)
00475 
00476 #define DMP_FEATURE_SEND_ANY_GYRO   (DMP_FEATURE_SEND_RAW_GYRO | \
00477                                      DMP_FEATURE_SEND_CAL_GYRO)
00478 
00479 #define MAX_PACKET_LENGTH   (32)
00480 
00481 #define DMP_SAMPLE_RATE     (200)
00482 #define GYRO_SF             (46850825LL * 200 / DMP_SAMPLE_RATE)
00483 
00484 #define FIFO_CORRUPTION_CHECK
00485 #ifdef FIFO_CORRUPTION_CHECK
00486 #define QUAT_ERROR_THRESH       (1L<<24)
00487 #define QUAT_MAG_SQ_NORMALIZED  (1L<<28)
00488 #define QUAT_MAG_SQ_MIN         (QUAT_MAG_SQ_NORMALIZED - QUAT_ERROR_THRESH)
00489 #define QUAT_MAG_SQ_MAX         (QUAT_MAG_SQ_NORMALIZED + QUAT_ERROR_THRESH)
00490 #endif
00491 
00492 struct dmp_s {
00493     void (*tap_cb)(unsigned char count, unsigned char direction);
00494     void (*android_orient_cb)(unsigned char orientation);
00495     unsigned short orient;
00496     unsigned short feature_mask;
00497     unsigned short fifo_rate;
00498     unsigned char packet_length;
00499 };
00500 
00501 static struct dmp_s dmp = {
00502     .tap_cb = NULL,
00503     .android_orient_cb = NULL,
00504     .orient = 0,
00505     .feature_mask = 0,
00506     .fifo_rate = 0,
00507     .packet_length = 0
00508 };
00509 
00510 /**
00511  *  @brief  Load the DMP with this image.
00512  *  @return 0 if successful.
00513  */
00514 int dmp_load_motion_driver_firmware(void)
00515 {
00516     return mpu_load_firmware(DMP_CODE_SIZE, dmp_memory, sStartAddress,
00517         DMP_SAMPLE_RATE);
00518 }
00519 
00520 /**
00521  *  @brief      Push gyro and accel orientation to the DMP.
00522  *  The orientation is represented here as the output of
00523  *  @e inv_orientation_matrix_to_scalar.
00524  *  @param[in]  orient  Gyro and accel orientation in body frame.
00525  *  @return     0 if successful.
00526  */
00527 int dmp_set_orientation(unsigned short orient)
00528 {
00529     unsigned char gyro_regs[3], accel_regs[3];
00530     const unsigned char gyro_axes[3] = {DINA4C, DINACD, DINA6C};
00531     const unsigned char accel_axes[3] = {DINA0C, DINAC9, DINA2C};
00532     const unsigned char gyro_sign[3] = {DINA36, DINA56, DINA76};
00533     const unsigned char accel_sign[3] = {DINA26, DINA46, DINA66};
00534 
00535     gyro_regs[0] = gyro_axes[orient & 3];
00536     gyro_regs[1] = gyro_axes[(orient >> 3) & 3];
00537     gyro_regs[2] = gyro_axes[(orient >> 6) & 3];
00538     accel_regs[0] = accel_axes[orient & 3];
00539     accel_regs[1] = accel_axes[(orient >> 3) & 3];
00540     accel_regs[2] = accel_axes[(orient >> 6) & 3];
00541 
00542     /* Chip-to-body, axes only. */
00543     if (mpu_write_mem(FCFG_1, 3, gyro_regs))
00544         return -1;
00545     if (mpu_write_mem(FCFG_2, 3, accel_regs))
00546         return -1;
00547 
00548     memcpy(gyro_regs, gyro_sign, 3);
00549     memcpy(accel_regs, accel_sign, 3);
00550     if (orient & 4) {
00551         gyro_regs[0] |= 1;
00552         accel_regs[0] |= 1;
00553     }
00554     if (orient & 0x20) {
00555         gyro_regs[1] |= 1;
00556         accel_regs[1] |= 1;
00557     }
00558     if (orient & 0x100) {
00559         gyro_regs[2] |= 1;
00560         accel_regs[2] |= 1;
00561     }
00562 
00563     /* Chip-to-body, sign only. */
00564     if (mpu_write_mem(FCFG_3, 3, gyro_regs))
00565         return -1;
00566     if (mpu_write_mem(FCFG_7, 3, accel_regs))
00567         return -1;
00568     dmp.orient = orient;
00569     return 0;
00570 }
00571 
00572 /**
00573  *  @brief      Push gyro biases to the DMP.
00574  *  Because the gyro integration is handled in the DMP, any gyro biases
00575  *  calculated by the MPL should be pushed down to DMP memory to remove
00576  *  3-axis quaternion drift.
00577  *  \n NOTE: If the DMP-based gyro calibration is enabled, the DMP will
00578  *  overwrite the biases written to this location once a new one is computed.
00579  *  @param[in]  bias    Gyro biases in q16.
00580  *  @return     0 if successful.
00581  */
00582 int dmp_set_gyro_bias(long *bias)
00583 {
00584     long gyro_bias_body[3];
00585     unsigned char regs[4];
00586 
00587     gyro_bias_body[0] = bias[dmp.orient & 3];
00588     if (dmp.orient & 4)
00589         gyro_bias_body[0] *= -1;
00590     gyro_bias_body[1] = bias[(dmp.orient >> 3) & 3];
00591     if (dmp.orient & 0x20)
00592         gyro_bias_body[1] *= -1;
00593     gyro_bias_body[2] = bias[(dmp.orient >> 6) & 3];
00594     if (dmp.orient & 0x100)
00595         gyro_bias_body[2] *= -1;
00596 
00597 #ifdef EMPL_NO_64BIT
00598     gyro_bias_body[0] = (long)(((float)gyro_bias_body[0] * GYRO_SF) / 1073741824.f);
00599     gyro_bias_body[1] = (long)(((float)gyro_bias_body[1] * GYRO_SF) / 1073741824.f);
00600     gyro_bias_body[2] = (long)(((float)gyro_bias_body[2] * GYRO_SF) / 1073741824.f);
00601 #else
00602     gyro_bias_body[0] = (long)(((long long)gyro_bias_body[0] * GYRO_SF) >> 30);
00603     gyro_bias_body[1] = (long)(((long long)gyro_bias_body[1] * GYRO_SF) >> 30);
00604     gyro_bias_body[2] = (long)(((long long)gyro_bias_body[2] * GYRO_SF) >> 30);
00605 #endif
00606 
00607     regs[0] = (unsigned char)((gyro_bias_body[0] >> 24) & 0xFF);
00608     regs[1] = (unsigned char)((gyro_bias_body[0] >> 16) & 0xFF);
00609     regs[2] = (unsigned char)((gyro_bias_body[0] >> 8) & 0xFF);
00610     regs[3] = (unsigned char)(gyro_bias_body[0] & 0xFF);
00611     if (mpu_write_mem(D_EXT_GYRO_BIAS_X, 4, regs))
00612         return -1;
00613 
00614     regs[0] = (unsigned char)((gyro_bias_body[1] >> 24) & 0xFF);
00615     regs[1] = (unsigned char)((gyro_bias_body[1] >> 16) & 0xFF);
00616     regs[2] = (unsigned char)((gyro_bias_body[1] >> 8) & 0xFF);
00617     regs[3] = (unsigned char)(gyro_bias_body[1] & 0xFF);
00618     if (mpu_write_mem(D_EXT_GYRO_BIAS_Y, 4, regs))
00619         return -1;
00620 
00621     regs[0] = (unsigned char)((gyro_bias_body[2] >> 24) & 0xFF);
00622     regs[1] = (unsigned char)((gyro_bias_body[2] >> 16) & 0xFF);
00623     regs[2] = (unsigned char)((gyro_bias_body[2] >> 8) & 0xFF);
00624     regs[3] = (unsigned char)(gyro_bias_body[2] & 0xFF);
00625     return mpu_write_mem(D_EXT_GYRO_BIAS_Z, 4, regs);
00626 }
00627 
00628 /**
00629  *  @brief      Push accel biases to the DMP.
00630  *  These biases will be removed from the DMP 6-axis quaternion.
00631  *  @param[in]  bias    Accel biases in q16.
00632  *  @return     0 if successful.
00633  */
00634 int dmp_set_accel_bias(long *bias)
00635 {
00636     long accel_bias_body[3];
00637     unsigned char regs[12];
00638     long long accel_sf;
00639     unsigned short accel_sens;
00640 
00641     mpu_get_accel_sens(&accel_sens);
00642     accel_sf = (long long)accel_sens << 15;
00643     //nsol __no_operation();
00644 
00645     accel_bias_body[0] = bias[dmp.orient & 3];
00646     if (dmp.orient & 4)
00647         accel_bias_body[0] *= -1;
00648     accel_bias_body[1] = bias[(dmp.orient >> 3) & 3];
00649     if (dmp.orient & 0x20)
00650         accel_bias_body[1] *= -1;
00651     accel_bias_body[2] = bias[(dmp.orient >> 6) & 3];
00652     if (dmp.orient & 0x100)
00653         accel_bias_body[2] *= -1;
00654 
00655 #ifdef EMPL_NO_64BIT
00656     accel_bias_body[0] = (long)(((float)accel_bias_body[0] * accel_sf) / 1073741824.f);
00657     accel_bias_body[1] = (long)(((float)accel_bias_body[1] * accel_sf) / 1073741824.f);
00658     accel_bias_body[2] = (long)(((float)accel_bias_body[2] * accel_sf) / 1073741824.f);
00659 #else
00660     accel_bias_body[0] = (long)(((long long)accel_bias_body[0] * accel_sf) >> 30);
00661     accel_bias_body[1] = (long)(((long long)accel_bias_body[1] * accel_sf) >> 30);
00662     accel_bias_body[2] = (long)(((long long)accel_bias_body[2] * accel_sf) >> 30);
00663 #endif
00664 
00665     regs[0] = (unsigned char)((accel_bias_body[0] >> 24) & 0xFF);
00666     regs[1] = (unsigned char)((accel_bias_body[0] >> 16) & 0xFF);
00667     regs[2] = (unsigned char)((accel_bias_body[0] >> 8) & 0xFF);
00668     regs[3] = (unsigned char)(accel_bias_body[0] & 0xFF);
00669     regs[4] = (unsigned char)((accel_bias_body[1] >> 24) & 0xFF);
00670     regs[5] = (unsigned char)((accel_bias_body[1] >> 16) & 0xFF);
00671     regs[6] = (unsigned char)((accel_bias_body[1] >> 8) & 0xFF);
00672     regs[7] = (unsigned char)(accel_bias_body[1] & 0xFF);
00673     regs[8] = (unsigned char)((accel_bias_body[2] >> 24) & 0xFF);
00674     regs[9] = (unsigned char)((accel_bias_body[2] >> 16) & 0xFF);
00675     regs[10] = (unsigned char)((accel_bias_body[2] >> 8) & 0xFF);
00676     regs[11] = (unsigned char)(accel_bias_body[2] & 0xFF);
00677     return mpu_write_mem(D_ACCEL_BIAS, 12, regs);
00678 }
00679 
00680 /**
00681  *  @brief      Set DMP output rate.
00682  *  Only used when DMP is on.
00683  *  @param[in]  rate    Desired fifo rate (Hz).
00684  *  @return     0 if successful.
00685  */
00686 int dmp_set_fifo_rate(unsigned short rate)
00687 {
00688     const unsigned char regs_end[12] = {DINAFE, DINAF2, DINAAB,
00689         0xc4, DINAAA, DINAF1, DINADF, DINADF, 0xBB, 0xAF, DINADF, DINADF};
00690     unsigned short div;
00691     unsigned char tmp[8];
00692 
00693     if (rate > DMP_SAMPLE_RATE)
00694         return -1;
00695     div = DMP_SAMPLE_RATE / rate - 1;
00696     tmp[0] = (unsigned char)((div >> 8) & 0xFF);
00697     tmp[1] = (unsigned char)(div & 0xFF);
00698     if (mpu_write_mem(D_0_22, 2, tmp))
00699         return -1;
00700     if (mpu_write_mem(CFG_6, 12, (unsigned char*)regs_end))
00701         return -1;
00702 
00703     dmp.fifo_rate = rate;
00704     return 0;
00705 }
00706 
00707 /**
00708  *  @brief      Get DMP output rate.
00709  *  @param[out] rate    Current fifo rate (Hz).
00710  *  @return     0 if successful.
00711  */
00712 int dmp_get_fifo_rate(unsigned short *rate)
00713 {
00714     rate[0] = dmp.fifo_rate;
00715     return 0;
00716 }
00717 
00718 /**
00719  *  @brief      Set tap threshold for a specific axis.
00720  *  @param[in]  axis    1, 2, and 4 for XYZ accel, respectively.
00721  *  @param[in]  thresh  Tap threshold, in mg/ms.
00722  *  @return     0 if successful.
00723  */
00724 int dmp_set_tap_thresh(unsigned char axis, unsigned short thresh)
00725 {
00726     unsigned char tmp[4], accel_fsr;
00727     float scaled_thresh;
00728     unsigned short dmp_thresh, dmp_thresh_2;
00729     if (!(axis & TAP_XYZ) || thresh > 1600)
00730         return -1;
00731 
00732     scaled_thresh = (float)thresh / DMP_SAMPLE_RATE;
00733 
00734     mpu_get_accel_fsr(&accel_fsr);
00735     switch (accel_fsr) {
00736     case 2:
00737         dmp_thresh = (unsigned short)(scaled_thresh * 16384);
00738         /* dmp_thresh * 0.75 */
00739         dmp_thresh_2 = (unsigned short)(scaled_thresh * 12288);
00740         break;
00741     case 4:
00742         dmp_thresh = (unsigned short)(scaled_thresh * 8192);
00743         /* dmp_thresh * 0.75 */
00744         dmp_thresh_2 = (unsigned short)(scaled_thresh * 6144);
00745         break;
00746     case 8:
00747         dmp_thresh = (unsigned short)(scaled_thresh * 4096);
00748         /* dmp_thresh * 0.75 */
00749         dmp_thresh_2 = (unsigned short)(scaled_thresh * 3072);
00750         break;
00751     case 16:
00752         dmp_thresh = (unsigned short)(scaled_thresh * 2048);
00753         /* dmp_thresh * 0.75 */
00754         dmp_thresh_2 = (unsigned short)(scaled_thresh * 1536);
00755         break;
00756     default:
00757         return -1;
00758     }
00759     tmp[0] = (unsigned char)(dmp_thresh >> 8);
00760     tmp[1] = (unsigned char)(dmp_thresh & 0xFF);
00761     tmp[2] = (unsigned char)(dmp_thresh_2 >> 8);
00762     tmp[3] = (unsigned char)(dmp_thresh_2 & 0xFF);
00763 
00764     if (axis & TAP_X) {
00765         if (mpu_write_mem(DMP_TAP_THX, 2, tmp))
00766             return -1;
00767         if (mpu_write_mem(D_1_36, 2, tmp+2))
00768             return -1;
00769     }
00770     if (axis & TAP_Y) {
00771         if (mpu_write_mem(DMP_TAP_THY, 2, tmp))
00772             return -1;
00773         if (mpu_write_mem(D_1_40, 2, tmp+2))
00774             return -1;
00775     }
00776     if (axis & TAP_Z) {
00777         if (mpu_write_mem(DMP_TAP_THZ, 2, tmp))
00778             return -1;
00779         if (mpu_write_mem(D_1_44, 2, tmp+2))
00780             return -1;
00781     }
00782     return 0;
00783 }
00784 
00785 /**
00786  *  @brief      Set which axes will register a tap.
00787  *  @param[in]  axis    1, 2, and 4 for XYZ, respectively.
00788  *  @return     0 if successful.
00789  */
00790 int dmp_set_tap_axes(unsigned char axis)
00791 {
00792     unsigned char tmp = 0;
00793 
00794     if (axis & TAP_X)
00795         tmp |= 0x30;
00796     if (axis & TAP_Y)
00797         tmp |= 0x0C;
00798     if (axis & TAP_Z)
00799         tmp |= 0x03;
00800     return mpu_write_mem(D_1_72, 1, &tmp);
00801 }
00802 
00803 /**
00804  *  @brief      Set minimum number of taps needed for an interrupt.
00805  *  @param[in]  min_taps    Minimum consecutive taps (1-4).
00806  *  @return     0 if successful.
00807  */
00808 int dmp_set_tap_count(unsigned char min_taps)
00809 {
00810     unsigned char tmp;
00811 
00812     if (min_taps < 1)
00813         min_taps = 1;
00814     else if (min_taps > 4)
00815         min_taps = 4;
00816 
00817     tmp = min_taps - 1;
00818     return mpu_write_mem(D_1_79, 1, &tmp);
00819 }
00820 
00821 /**
00822  *  @brief      Set length between valid taps.
00823  *  @param[in]  time    Milliseconds between taps.
00824  *  @return     0 if successful.
00825  */
00826 int dmp_set_tap_time(unsigned short time)
00827 {
00828     unsigned short dmp_time;
00829     unsigned char tmp[2];
00830 
00831     dmp_time = time / (1000 / DMP_SAMPLE_RATE);
00832     tmp[0] = (unsigned char)(dmp_time >> 8);
00833     tmp[1] = (unsigned char)(dmp_time & 0xFF);
00834     return mpu_write_mem(DMP_TAPW_MIN, 2, tmp);
00835 }
00836 
00837 /**
00838  *  @brief      Set max time between taps to register as a multi-tap.
00839  *  @param[in]  time    Max milliseconds between taps.
00840  *  @return     0 if successful.
00841  */
00842 int dmp_set_tap_time_multi(unsigned short time)
00843 {
00844     unsigned short dmp_time;
00845     unsigned char tmp[2];
00846 
00847     dmp_time = time / (1000 / DMP_SAMPLE_RATE);
00848     tmp[0] = (unsigned char)(dmp_time >> 8);
00849     tmp[1] = (unsigned char)(dmp_time & 0xFF);
00850     return mpu_write_mem(D_1_218, 2, tmp);
00851 }
00852 
00853 /**
00854  *  @brief      Set shake rejection threshold.
00855  *  If the DMP detects a gyro sample larger than @e thresh, taps are rejected.
00856  *  @param[in]  sf      Gyro scale factor.
00857  *  @param[in]  thresh  Gyro threshold in dps.
00858  *  @return     0 if successful.
00859  */
00860 int dmp_set_shake_reject_thresh(long sf, unsigned short thresh)
00861 {
00862     unsigned char tmp[4];
00863     long thresh_scaled = sf / 1000 * thresh;
00864     tmp[0] = (unsigned char)(((long)thresh_scaled >> 24) & 0xFF);
00865     tmp[1] = (unsigned char)(((long)thresh_scaled >> 16) & 0xFF);
00866     tmp[2] = (unsigned char)(((long)thresh_scaled >> 8) & 0xFF);
00867     tmp[3] = (unsigned char)((long)thresh_scaled & 0xFF);
00868     return mpu_write_mem(D_1_92, 4, tmp);
00869 }
00870 
00871 /**
00872  *  @brief      Set shake rejection time.
00873  *  Sets the length of time that the gyro must be outside of the threshold set
00874  *  by @e gyro_set_shake_reject_thresh before taps are rejected. A mandatory
00875  *  60 ms is added to this parameter.
00876  *  @param[in]  time    Time in milliseconds.
00877  *  @return     0 if successful.
00878  */
00879 int dmp_set_shake_reject_time(unsigned short time)
00880 {
00881     unsigned char tmp[2];
00882 
00883     time /= (1000 / DMP_SAMPLE_RATE);
00884     tmp[0] = time >> 8;
00885     tmp[1] = time & 0xFF;
00886     return mpu_write_mem(D_1_90,2,tmp);
00887 }
00888 
00889 /**
00890  *  @brief      Set shake rejection timeout.
00891  *  Sets the length of time after a shake rejection that the gyro must stay
00892  *  inside of the threshold before taps can be detected again. A mandatory
00893  *  60 ms is added to this parameter.
00894  *  @param[in]  time    Time in milliseconds.
00895  *  @return     0 if successful.
00896  */
00897 int dmp_set_shake_reject_timeout(unsigned short time)
00898 {
00899     unsigned char tmp[2];
00900 
00901     time /= (1000 / DMP_SAMPLE_RATE);
00902     tmp[0] = time >> 8;
00903     tmp[1] = time & 0xFF;
00904     return mpu_write_mem(D_1_88,2,tmp);
00905 }
00906 
00907 /**
00908  *  @brief      Get current step count.
00909  *  @param[out] count   Number of steps detected.
00910  *  @return     0 if successful.
00911  */
00912 int dmp_get_pedometer_step_count(unsigned long *count)
00913 {
00914     unsigned char tmp[4];
00915     if (!count)
00916         return -1;
00917 
00918     if (mpu_read_mem(D_PEDSTD_STEPCTR, 4, tmp))
00919         return -1;
00920 
00921     count[0] = ((unsigned long)tmp[0] << 24) | ((unsigned long)tmp[1] << 16) |
00922         ((unsigned long)tmp[2] << 8) | tmp[3];
00923     return 0;
00924 }
00925 
00926 /**
00927  *  @brief      Overwrite current step count.
00928  *  WARNING: This function writes to DMP memory and could potentially encounter
00929  *  a race condition if called while the pedometer is enabled.
00930  *  @param[in]  count   New step count.
00931  *  @return     0 if successful.
00932  */
00933 int dmp_set_pedometer_step_count(unsigned long count)
00934 {
00935     unsigned char tmp[4];
00936 
00937     tmp[0] = (unsigned char)((count >> 24) & 0xFF);
00938     tmp[1] = (unsigned char)((count >> 16) & 0xFF);
00939     tmp[2] = (unsigned char)((count >> 8) & 0xFF);
00940     tmp[3] = (unsigned char)(count & 0xFF);
00941     return mpu_write_mem(D_PEDSTD_STEPCTR, 4, tmp);
00942 }
00943 
00944 /**
00945  *  @brief      Get duration of walking time.
00946  *  @param[in]  time    Walk time in milliseconds.
00947  *  @return     0 if successful.
00948  */
00949 int dmp_get_pedometer_walk_time(unsigned long *time)
00950 {
00951     unsigned char tmp[4];
00952     if (!time)
00953         return -1;
00954 
00955     if (mpu_read_mem(D_PEDSTD_TIMECTR, 4, tmp))
00956         return -1;
00957 
00958     time[0] = (((unsigned long)tmp[0] << 24) | ((unsigned long)tmp[1] << 16) |
00959         ((unsigned long)tmp[2] << 8) | tmp[3]) * 20;
00960     return 0;
00961 }
00962 
00963 /**
00964  *  @brief      Overwrite current walk time.
00965  *  WARNING: This function writes to DMP memory and could potentially encounter
00966  *  a race condition if called while the pedometer is enabled.
00967  *  @param[in]  time    New walk time in milliseconds.
00968  */
00969 int dmp_set_pedometer_walk_time(unsigned long time)
00970 {
00971     unsigned char tmp[4];
00972 
00973     time /= 20;
00974 
00975     tmp[0] = (unsigned char)((time >> 24) & 0xFF);
00976     tmp[1] = (unsigned char)((time >> 16) & 0xFF);
00977     tmp[2] = (unsigned char)((time >> 8) & 0xFF);
00978     tmp[3] = (unsigned char)(time & 0xFF);
00979     return mpu_write_mem(D_PEDSTD_TIMECTR, 4, tmp);
00980 }
00981 
00982 /**
00983  *  @brief      Enable DMP features.
00984  *  The following \#define's are used in the input mask:
00985  *  \n DMP_FEATURE_TAP
00986  *  \n DMP_FEATURE_ANDROID_ORIENT
00987  *  \n DMP_FEATURE_LP_QUAT
00988  *  \n DMP_FEATURE_6X_LP_QUAT
00989  *  \n DMP_FEATURE_GYRO_CAL
00990  *  \n DMP_FEATURE_SEND_RAW_ACCEL
00991  *  \n DMP_FEATURE_SEND_RAW_GYRO
00992  *  \n NOTE: DMP_FEATURE_LP_QUAT and DMP_FEATURE_6X_LP_QUAT are mutually
00993  *  exclusive.
00994  *  \n NOTE: DMP_FEATURE_SEND_RAW_GYRO and DMP_FEATURE_SEND_CAL_GYRO are also
00995  *  mutually exclusive.
00996  *  @param[in]  mask    Mask of features to enable.
00997  *  @return     0 if successful.
00998  */
00999 int dmp_enable_feature(unsigned short mask)
01000 {
01001     unsigned char tmp[10];
01002 
01003     /* TODO: All of these settings can probably be integrated into the default
01004      * DMP image.
01005      */
01006     /* Set integration scale factor. */
01007     tmp[0] = (unsigned char)((GYRO_SF >> 24) & 0xFF);
01008     tmp[1] = (unsigned char)((GYRO_SF >> 16) & 0xFF);
01009     tmp[2] = (unsigned char)((GYRO_SF >> 8) & 0xFF);
01010     tmp[3] = (unsigned char)(GYRO_SF & 0xFF);
01011     mpu_write_mem(D_0_104, 4, tmp);
01012 
01013     /* Send sensor data to the FIFO. */
01014     tmp[0] = 0xA3;
01015     if (mask & DMP_FEATURE_SEND_RAW_ACCEL) {
01016         tmp[1] = 0xC0;
01017         tmp[2] = 0xC8;
01018         tmp[3] = 0xC2;
01019     } else {
01020         tmp[1] = 0xA3;
01021         tmp[2] = 0xA3;
01022         tmp[3] = 0xA3;
01023     }
01024     if (mask & DMP_FEATURE_SEND_ANY_GYRO) {
01025         tmp[4] = 0xC4;
01026         tmp[5] = 0xCC;
01027         tmp[6] = 0xC6;
01028     } else {
01029         tmp[4] = 0xA3;
01030         tmp[5] = 0xA3;
01031         tmp[6] = 0xA3;
01032     }
01033     tmp[7] = 0xA3;
01034     tmp[8] = 0xA3;
01035     tmp[9] = 0xA3;
01036     mpu_write_mem(CFG_15,10,tmp);
01037 
01038     /* Send gesture data to the FIFO. */
01039     if (mask & (DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT))
01040         tmp[0] = DINA20;
01041     else
01042         tmp[0] = 0xD8;
01043     mpu_write_mem(CFG_27,1,tmp);
01044 
01045     if (mask & DMP_FEATURE_GYRO_CAL)
01046         dmp_enable_gyro_cal(1);
01047     else
01048         dmp_enable_gyro_cal(0);
01049 
01050     if (mask & DMP_FEATURE_SEND_ANY_GYRO) {
01051         if (mask & DMP_FEATURE_SEND_CAL_GYRO) {
01052             tmp[0] = 0xB2;
01053             tmp[1] = 0x8B;
01054             tmp[2] = 0xB6;
01055             tmp[3] = 0x9B;
01056         } else {
01057             tmp[0] = DINAC0;
01058             tmp[1] = DINA80;
01059             tmp[2] = DINAC2;
01060             tmp[3] = DINA90;
01061         }
01062         mpu_write_mem(CFG_GYRO_RAW_DATA, 4, tmp);
01063     }
01064 
01065     if (mask & DMP_FEATURE_TAP) {
01066         /* Enable tap. */
01067         tmp[0] = 0xF8;
01068         mpu_write_mem(CFG_20, 1, tmp);
01069         dmp_set_tap_thresh(TAP_XYZ, 250);
01070         dmp_set_tap_axes(TAP_XYZ);
01071         dmp_set_tap_count(1);
01072         dmp_set_tap_time(100);
01073         dmp_set_tap_time_multi(500);
01074 
01075         dmp_set_shake_reject_thresh(GYRO_SF, 200);
01076         dmp_set_shake_reject_time(40);
01077         dmp_set_shake_reject_timeout(10);
01078     } else {
01079         tmp[0] = 0xD8;
01080         mpu_write_mem(CFG_20, 1, tmp);
01081     }
01082 
01083     if (mask & DMP_FEATURE_ANDROID_ORIENT) {
01084         tmp[0] = 0xD9;
01085     } else
01086         tmp[0] = 0xD8;
01087     mpu_write_mem(CFG_ANDROID_ORIENT_INT, 1, tmp);
01088 
01089     if (mask & DMP_FEATURE_LP_QUAT)
01090         dmp_enable_lp_quat(1);
01091     else
01092         dmp_enable_lp_quat(0);
01093 
01094     if (mask & DMP_FEATURE_6X_LP_QUAT)
01095         dmp_enable_6x_lp_quat(1);
01096     else
01097         dmp_enable_6x_lp_quat(0);
01098 
01099     /* Pedometer is always enabled. */
01100     dmp.feature_mask = mask | DMP_FEATURE_PEDOMETER;
01101     mpu_reset_fifo();
01102 
01103     dmp.packet_length = 0;
01104     if (mask & DMP_FEATURE_SEND_RAW_ACCEL)
01105         dmp.packet_length += 6;
01106     if (mask & DMP_FEATURE_SEND_ANY_GYRO)
01107         dmp.packet_length += 6;
01108     if (mask & (DMP_FEATURE_LP_QUAT | DMP_FEATURE_6X_LP_QUAT))
01109         dmp.packet_length += 16;
01110     if (mask & (DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT))
01111         dmp.packet_length += 4;
01112 
01113     return 0;
01114 }
01115 
01116 /**
01117  *  @brief      Get list of currently enabled DMP features.
01118  *  @param[out] Mask of enabled features.
01119  *  @return     0 if successful.
01120  */
01121 int dmp_get_enabled_features(unsigned short *mask)
01122 {
01123     mask[0] = dmp.feature_mask;
01124     return 0;
01125 }
01126 
01127 /**
01128  *  @brief      Calibrate the gyro data in the DMP.
01129  *  After eight seconds of no motion, the DMP will compute gyro biases and
01130  *  subtract them from the quaternion output. If @e dmp_enable_feature is
01131  *  called with @e DMP_FEATURE_SEND_CAL_GYRO, the biases will also be
01132  *  subtracted from the gyro output.
01133  *  @param[in]  enable  1 to enable gyro calibration.
01134  *  @return     0 if successful.
01135  */
01136 int dmp_enable_gyro_cal(unsigned char enable)
01137 {
01138     if (enable) {
01139         unsigned char regs[9] = {0xb8, 0xaa, 0xb3, 0x8d, 0xb4, 0x98, 0x0d, 0x35, 0x5d};
01140         return mpu_write_mem(CFG_MOTION_BIAS, 9, regs);
01141     } else {
01142         unsigned char regs[9] = {0xb8, 0xaa, 0xaa, 0xaa, 0xb0, 0x88, 0xc3, 0xc5, 0xc7};
01143         return mpu_write_mem(CFG_MOTION_BIAS, 9, regs);
01144     }
01145 }
01146 
01147 /**
01148  *  @brief      Generate 3-axis quaternions from the DMP.
01149  *  In this driver, the 3-axis and 6-axis DMP quaternion features are mutually
01150  *  exclusive.
01151  *  @param[in]  enable  1 to enable 3-axis quaternion.
01152  *  @return     0 if successful.
01153  */
01154 int dmp_enable_lp_quat(unsigned char enable)
01155 {
01156     unsigned char regs[4];
01157     if (enable) {
01158         regs[0] = DINBC0;
01159         regs[1] = DINBC2;
01160         regs[2] = DINBC4;
01161         regs[3] = DINBC6;
01162     }
01163     else
01164         memset(regs, 0x8B, 4);
01165 
01166     mpu_write_mem(CFG_LP_QUAT, 4, regs);
01167 
01168     return mpu_reset_fifo();
01169 }
01170 
01171 /**
01172  *  @brief       Generate 6-axis quaternions from the DMP.
01173  *  In this driver, the 3-axis and 6-axis DMP quaternion features are mutually
01174  *  exclusive.
01175  *  @param[in]   enable  1 to enable 6-axis quaternion.
01176  *  @return      0 if successful.
01177  */
01178 int dmp_enable_6x_lp_quat(unsigned char enable)
01179 {
01180     unsigned char regs[4];
01181     if (enable) {
01182         regs[0] = DINA20;
01183         regs[1] = DINA28;
01184         regs[2] = DINA30;
01185         regs[3] = DINA38;
01186     } else
01187         memset(regs, 0xA3, 4);
01188 
01189     mpu_write_mem(CFG_8, 4, regs);
01190 
01191     return mpu_reset_fifo();
01192 }
01193 
01194 /**
01195  *  @brief      Decode the four-byte gesture data and execute any callbacks.
01196  *  @param[in]  gesture Gesture data from DMP packet.
01197  *  @return     0 if successful.
01198  */
01199 static int decode_gesture(unsigned char *gesture)
01200 {
01201     unsigned char tap, android_orient;
01202 
01203     android_orient = gesture[3] & 0xC0;
01204     tap = 0x3F & gesture[3];
01205 
01206     if (gesture[1] & INT_SRC_TAP) {
01207         unsigned char direction, count;
01208         direction = tap >> 3;
01209         count = (tap % 8) + 1;
01210         if (dmp.tap_cb)
01211             dmp.tap_cb(direction, count);
01212     }
01213 
01214     if (gesture[1] & INT_SRC_ANDROID_ORIENT) {
01215         if (dmp.android_orient_cb)
01216             dmp.android_orient_cb(android_orient >> 6);
01217     }
01218 
01219     return 0;
01220 }
01221 
01222 /**
01223  *  @brief      Specify when a DMP interrupt should occur.
01224  *  A DMP interrupt can be configured to trigger on either of the two
01225  *  conditions below:
01226  *  \n a. One FIFO period has elapsed (set by @e mpu_set_sample_rate).
01227  *  \n b. A tap event has been detected.
01228  *  @param[in]  mode    DMP_INT_GESTURE or DMP_INT_CONTINUOUS.
01229  *  @return     0 if successful.
01230  */
01231 int dmp_set_interrupt_mode(unsigned char mode)
01232 {
01233     const unsigned char regs_continuous[11] =
01234         {0xd8, 0xb1, 0xb9, 0xf3, 0x8b, 0xa3, 0x91, 0xb6, 0x09, 0xb4, 0xd9};
01235     const unsigned char regs_gesture[11] =
01236         {0xda, 0xb1, 0xb9, 0xf3, 0x8b, 0xa3, 0x91, 0xb6, 0xda, 0xb4, 0xda};
01237 
01238     switch (mode) {
01239     case DMP_INT_CONTINUOUS:
01240         return mpu_write_mem(CFG_FIFO_ON_EVENT, 11,
01241             (unsigned char*)regs_continuous);
01242     case DMP_INT_GESTURE:
01243         return mpu_write_mem(CFG_FIFO_ON_EVENT, 11,
01244             (unsigned char*)regs_gesture);
01245     default:
01246         return -1;
01247     }
01248 }
01249 
01250 /**
01251  *  @brief      Get one packet from the FIFO.
01252  *  If @e sensors does not contain a particular sensor, disregard the data
01253  *  returned to that pointer.
01254  *  \n @e sensors can contain a combination of the following flags:
01255  *  \n INV_X_GYRO, INV_Y_GYRO, INV_Z_GYRO
01256  *  \n INV_XYZ_GYRO
01257  *  \n INV_XYZ_ACCEL
01258  *  \n INV_WXYZ_QUAT
01259  *  \n If the FIFO has no new data, @e sensors will be zero.
01260  *  \n If the FIFO is disabled, @e sensors will be zero and this function will
01261  *  return a non-zero error code.
01262  *  @param[out] gyro        Gyro data in hardware units.
01263  *  @param[out] accel       Accel data in hardware units.
01264  *  @param[out] quat        3-axis quaternion data in hardware units.
01265  *  @param[out] timestamp   Timestamp in milliseconds.
01266  *  @param[out] sensors     Mask of sensors read from FIFO.
01267  *  @param[out] more        Number of remaining packets.
01268  *  @return     0 if successful.
01269  */
01270 int dmp_read_fifo(short *gyro, short *accel, long *quat,
01271     unsigned long *timestamp, short *sensors, unsigned char *more)
01272 {
01273     unsigned char fifo_data[MAX_PACKET_LENGTH];
01274     unsigned char ii = 0;
01275 
01276     /* TODO: sensors[0] only changes when dmp_enable_feature is called. We can
01277      * cache this value and save some cycles.
01278      */
01279     sensors[0] = 0;
01280 
01281     /* Get a packet. */
01282     if (mpu_read_fifo_stream(dmp.packet_length, fifo_data, more))
01283         return -1;
01284 
01285     /* Parse DMP packet. */
01286     if (dmp.feature_mask & (DMP_FEATURE_LP_QUAT | DMP_FEATURE_6X_LP_QUAT)) {
01287 #ifdef FIFO_CORRUPTION_CHECK
01288         long quat_q14[4], quat_mag_sq;
01289 #endif
01290         quat[0] = ((long)fifo_data[0] << 24) | ((long)fifo_data[1] << 16) |
01291             ((long)fifo_data[2] << 8) | fifo_data[3];
01292         quat[1] = ((long)fifo_data[4] << 24) | ((long)fifo_data[5] << 16) |
01293             ((long)fifo_data[6] << 8) | fifo_data[7];
01294         quat[2] = ((long)fifo_data[8] << 24) | ((long)fifo_data[9] << 16) |
01295             ((long)fifo_data[10] << 8) | fifo_data[11];
01296         quat[3] = ((long)fifo_data[12] << 24) | ((long)fifo_data[13] << 16) |
01297             ((long)fifo_data[14] << 8) | fifo_data[15];
01298         ii += 16;
01299 #ifdef FIFO_CORRUPTION_CHECK
01300         /* We can detect a corrupted FIFO by monitoring the quaternion data and
01301          * ensuring that the magnitude is always normalized to one. This
01302          * shouldn't happen in normal operation, but if an I2C error occurs,
01303          * the FIFO reads might become misaligned.
01304          *
01305          * Let's start by scaling down the quaternion data to avoid long long
01306          * math.
01307          */
01308         quat_q14[0] = quat[0] >> 16;
01309         quat_q14[1] = quat[1] >> 16;
01310         quat_q14[2] = quat[2] >> 16;
01311         quat_q14[3] = quat[3] >> 16;
01312         quat_mag_sq = quat_q14[0] * quat_q14[0] + quat_q14[1] * quat_q14[1] +
01313             quat_q14[2] * quat_q14[2] + quat_q14[3] * quat_q14[3];
01314         if ((quat_mag_sq < QUAT_MAG_SQ_MIN) ||
01315             (quat_mag_sq > QUAT_MAG_SQ_MAX)) {
01316             /* Quaternion is outside of the acceptable threshold. */
01317             mpu_reset_fifo();
01318             sensors[0] = 0;
01319             return -1;
01320         }
01321         sensors[0] |= INV_WXYZ_QUAT;
01322 #endif
01323     }
01324 
01325     if (dmp.feature_mask & DMP_FEATURE_SEND_RAW_ACCEL) {
01326         accel[0] = ((short)fifo_data[ii+0] << 8) | fifo_data[ii+1];
01327         accel[1] = ((short)fifo_data[ii+2] << 8) | fifo_data[ii+3];
01328         accel[2] = ((short)fifo_data[ii+4] << 8) | fifo_data[ii+5];
01329         ii += 6;
01330         sensors[0] |= INV_XYZ_ACCEL;
01331     }
01332 
01333     if (dmp.feature_mask & DMP_FEATURE_SEND_ANY_GYRO) {
01334         gyro[0] = ((short)fifo_data[ii+0] << 8) | fifo_data[ii+1];
01335         gyro[1] = ((short)fifo_data[ii+2] << 8) | fifo_data[ii+3];
01336         gyro[2] = ((short)fifo_data[ii+4] << 8) | fifo_data[ii+5];
01337         ii += 6;
01338         sensors[0] |= INV_XYZ_GYRO;
01339     }
01340 
01341     /* Gesture data is at the end of the DMP packet. Parse it and call
01342      * the gesture callbacks (if registered).
01343      */
01344     if (dmp.feature_mask & (DMP_FEATURE_TAP | DMP_FEATURE_ANDROID_ORIENT))
01345         decode_gesture(fifo_data + ii);
01346 
01347     get_ms(timestamp);
01348     return 0;
01349 }
01350 
01351 /**
01352  *  @brief      Register a function to be executed on a tap event.
01353  *  The tap direction is represented by one of the following:
01354  *  \n TAP_X_UP
01355  *  \n TAP_X_DOWN
01356  *  \n TAP_Y_UP
01357  *  \n TAP_Y_DOWN
01358  *  \n TAP_Z_UP
01359  *  \n TAP_Z_DOWN
01360  *  @param[in]  func    Callback function.
01361  *  @return     0 if successful.
01362  */
01363 int dmp_register_tap_cb(void (*func)(unsigned char, unsigned char))
01364 {
01365     dmp.tap_cb = func;
01366     return 0;
01367 }
01368 
01369 /**
01370  *  @brief      Register a function to be executed on a android orientation event.
01371  *  @param[in]  func    Callback function.
01372  *  @return     0 if successful.
01373  */
01374 int dmp_register_android_orient_cb(void (*func)(unsigned char))
01375 {
01376     dmp.android_orient_cb = func;
01377     return 0;
01378 }
01379 
01380 /**
01381  *  @}
01382  */
01383 
01384