Seeed / eMPL_MPU6050

Dependents:   CSSE4011_BLE_IMU_Project_rev2 Seeed_Tiny_BLE_Get_Started nrf51822_fix_i2c_spi_conflict balanceboard ... more

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