Home | History | Annotate | Download | only in mllite
      1 /*
      2  $License:
      3    Copyright 2011 InvenSense, Inc.
      4 
      5  Licensed under the Apache License, Version 2.0 (the "License");
      6  you may not use this file except in compliance with the License.
      7  You may obtain a copy of the License at
      8 
      9  http://www.apache.org/licenses/LICENSE-2.0
     10 
     11  Unless required by applicable law or agreed to in writing, software
     12  distributed under the License is distributed on an "AS IS" BASIS,
     13  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  See the License for the specific language governing permissions and
     15  limitations under the License.
     16   $
     17  */
     18 
     19 /******************************************************************************
     20  *
     21  * $Id: ml_stored_data.c 5641 2011-06-14 02:10:02Z mcaramello $
     22  *
     23  *****************************************************************************/
     24 
     25 /**
     26  * @defgroup ML_STORED_DATA
     27  *
     28  * @{
     29  *      @file     ml_stored_data.c
     30  *      @brief    functions for reading and writing stored data sets.
     31  *                Typically, these functions process stored calibration data.
     32  */
     33 
     34 #include "ml_stored_data.h"
     35 #include "ml.h"
     36 #include "mlFIFO.h"
     37 #include "mltypes.h"
     38 #include "mlinclude.h"
     39 #include "compass.h"
     40 #include "dmpKey.h"
     41 #include "dmpDefault.h"
     42 #include "mlstates.h"
     43 #include "checksum.h"
     44 #include "mlsupervisor.h"
     45 
     46 #include "mlsl.h"
     47 #include "mlos.h"
     48 
     49 #include "log.h"
     50 #undef MPL_LOG_TAG
     51 #define MPL_LOG_TAG "MPL-storeload"
     52 
     53 /*
     54     Typedefs
     55 */
     56 typedef inv_error_t(*tMLLoadFunc) (unsigned char *, unsigned short);
     57 
     58 /*
     59     Globals
     60 */
     61 extern struct inv_obj_t inv_obj;
     62 
     63 /*
     64     Debugging Definitions
     65     set LOADCAL_DEBUG and/or STORECAL_DEBUG to 1 print the fields
     66     being read or stored in human-readable format.
     67     When set to 0, the compiler will optimize and remove the printouts
     68     from the code.
     69 */
     70 #define LOADCAL_DEBUG    0
     71 #define STORECAL_DEBUG   0
     72 
     73 #define LOADCAL_LOG(...)                        \
     74     if(LOADCAL_DEBUG)                           \
     75         MPL_LOGI("LOADCAL: " __VA_ARGS__)
     76 #define STORECAL_LOG(...)                       \
     77     if(STORECAL_DEBUG)                          \
     78         MPL_LOGI("STORECAL: " __VA_ARGS__)
     79 
     80 /**
     81  *  @brief  Duplicate of the inv_temp_comp_find_bin function in the libmpl
     82  *          advanced algorithms library. To remove cross-dependency, for now,
     83  *          we reimplement the same function here.
     84  *  @param  temp
     85  *              the temperature (1 count == 1 degree C).
     86  */
     87 int FindTempBin(float temp)
     88 {
     89     int bin = (int)((temp - MIN_TEMP) / TEMP_PER_BIN);
     90     if (bin < 0)
     91         bin = 0;
     92     if (bin > BINS - 1)
     93         bin = BINS - 1;
     94     return bin;
     95 }
     96 
     97 /**
     98  * @brief   Returns the length of the <b>MPL internal calibration data</b>.
     99  *          Should be called before allocating the memory required to store
    100  *          this data to a file.
    101  *          This function returns the total size required to store the cal
    102  *          data including the header (4 bytes) and the checksum (2 bytes).
    103  *
    104  *  @pre    Must be in INV_STATE_DMP_OPENED state.
    105  *          inv_dmp_open() or inv_dmp_stop() must have been called.
    106  *          inv_dmp_start() and inv_dmp_close() must have <b>NOT</b>
    107  *          been called.
    108  *
    109  * @return  the length of the internal calibrated data format.
    110  */
    111 unsigned int inv_get_cal_length(void)
    112 {
    113     INVENSENSE_FUNC_START;
    114     unsigned int length;
    115     length = INV_CAL_HDR_LEN +  // header
    116         BINS * PTS_PER_BIN * 4 * 4 + BINS * 4 * 2 + // gyro cal
    117         INV_CAL_ACCEL_LEN +     // accel cal
    118         INV_CAL_COMPASS_LEN +   // compass cal
    119         INV_CAL_CHK_LEN;        // checksum
    120     return length;
    121 }
    122 
    123 /**
    124  *  @brief  Loads a type 0 set of calibration data.
    125  *          It parses a binary data set containing calibration data.
    126  *          The binary data set is intended to be loaded from a file.
    127  *          This calibrations data format stores values for (in order of
    128  *          appearance) :
    129  *          - temperature,
    130  *          - gyro biases for X, Y, Z axes.
    131  *          This calibration data would normally be produced by the MPU Self
    132  *          Test and its size is 18 bytes (header and checksum included).
    133  *          Calibration format type 0 is currently <b>NOT</b> used and
    134  *          is substituted by type 5 : inv_load_cal_V5().
    135  *
    136  *  @note   This calibration data format is obsoleted and no longer supported
    137  *          by the rest of the MPL
    138  *
    139  *  @pre    inv_dmp_open()
    140  *          @ifnot MPL_MF
    141  *              or inv_open_low_power_pedometer()
    142  *              or inv_eis_open_dmp()
    143  *          @endif
    144  *          must have been called.
    145  *
    146  *  @param  calData
    147  *              A pointer to an array of bytes to be parsed.
    148  *  @param  len
    149  *              the length of the calibration
    150  *
    151  *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
    152  */
    153 inv_error_t inv_load_cal_V0(unsigned char *calData, unsigned short len)
    154 {
    155     INVENSENSE_FUNC_START;
    156     const short expLen = 18;
    157     long newGyroData[3] = { 0, 0, 0 };
    158     float newTemp;
    159     int bin;
    160 
    161     LOADCAL_LOG("Entering inv_load_cal_V0\n");
    162 
    163     if (len != expLen) {
    164         MPL_LOGE("Calibration data type 1 must be %d bytes long\n", expLen);
    165         return INV_ERROR_FILE_READ;
    166     }
    167 
    168     newTemp = (float)inv_decode_temperature(
    169                 (unsigned short)calData[6] * 256 + calData[7]) / 65536.f;
    170     LOADCAL_LOG("newTemp = %f\n", newTemp);
    171 
    172     newGyroData[0] = ((long)calData[8]) * 256 + ((long)calData[9]);
    173     if (newGyroData[0] > 32767L)
    174         newGyroData[0] -= 65536L;
    175     LOADCAL_LOG("newGyroData[0] = %ld\n", newGyroData[0]);
    176     newGyroData[1] = ((long)calData[10]) * 256 + ((long)calData[11]);
    177     if (newGyroData[1] > 32767L)
    178         newGyroData[1] -= 65536L;
    179     LOADCAL_LOG("newGyroData[2] = %ld\n", newGyroData[2]);
    180     newGyroData[2] = ((long)calData[12]) * 256 + ((long)calData[13]);
    181     if (newGyroData[2] > 32767L)
    182         newGyroData[2] -= 65536L;
    183     LOADCAL_LOG("newGyroData[2] = %ld\n", newGyroData[2]);
    184 
    185     bin = FindTempBin(newTemp);
    186     LOADCAL_LOG("bin = %d", bin);
    187 
    188     inv_obj.temp_data[bin][inv_obj.temp_ptrs[bin]] = newTemp;
    189     LOADCAL_LOG("temp_data[%d][%d] = %f",
    190                 bin, inv_obj.temp_ptrs[bin],
    191                 inv_obj.temp_data[bin][inv_obj.temp_ptrs[bin]]);
    192     inv_obj.x_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] =
    193         ((float)newGyroData[0]) / 65536.f;
    194     LOADCAL_LOG("x_gyro_temp_data[%d][%d] = %f\n",
    195                 bin, inv_obj.temp_ptrs[bin],
    196                 inv_obj.x_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]]);
    197     inv_obj.y_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] =
    198         ((float)newGyroData[0]) / 65536.f;
    199     LOADCAL_LOG("y_gyro_temp_data[%d][%d] = %f\n",
    200                 bin, inv_obj.temp_ptrs[bin],
    201                 inv_obj.y_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]]);
    202     inv_obj.z_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] =
    203         ((float)newGyroData[0]) / 65536.f;
    204     LOADCAL_LOG("z_gyro_temp_data[%d][%d] = %f\n",
    205                 bin, inv_obj.temp_ptrs[bin],
    206                 inv_obj.z_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]]);
    207 
    208     inv_obj.temp_ptrs[bin] = (inv_obj.temp_ptrs[bin] + 1) % PTS_PER_BIN;
    209     LOADCAL_LOG("temp_ptrs[%d] = %d\n", bin, inv_obj.temp_ptrs[bin]);
    210 
    211     if (inv_obj.temp_ptrs[bin] == 0)
    212         inv_obj.temp_valid_data[bin] = TRUE;
    213     LOADCAL_LOG("temp_valid_data[%d] = %ld\n",
    214                 bin, inv_obj.temp_valid_data[bin]);
    215 
    216     inv_obj.got_no_motion_bias = TRUE;
    217     LOADCAL_LOG("got_no_motion_bias = 1\n");
    218     inv_obj.cal_loaded_flag = TRUE;
    219     LOADCAL_LOG("cal_loaded_flag = 1\n");
    220 
    221     LOADCAL_LOG("Exiting inv_load_cal_V0\n");
    222     return INV_SUCCESS;
    223 }
    224 
    225 /**
    226  *  @brief  Loads a type 1 set of calibration data.
    227  *          It parses a binary data set containing calibration data.
    228  *          The binary data set is intended to be loaded from a file.
    229  *          This calibrations data format stores values for (in order of
    230  *          appearance) :
    231  *          - temperature,
    232  *          - gyro biases for X, Y, Z axes,
    233  *          - accel biases for X, Y, Z axes.
    234  *          This calibration data would normally be produced by the MPU Self
    235  *          Test and its size is 24 bytes (header and checksum included).
    236  *          Calibration format type 1 is currently <b>NOT</b> used and
    237  *          is substituted by type 5 : inv_load_cal_V5().
    238  *
    239  *  @note   In order to successfully work, the gyro bias must be stored
    240  *          expressed in 250 dps full scale (131.072 sensitivity). Other full
    241  *          scale range will produce unpredictable results in the gyro biases.
    242  *
    243  *  @pre    inv_dmp_open()
    244  *          @ifnot MPL_MF
    245  *              or inv_open_low_power_pedometer()
    246  *              or inv_eis_open_dmp()
    247  *          @endif
    248  *          must have been called.
    249  *
    250  *  @param  calData
    251  *              A pointer to an array of bytes to be parsed.
    252  *  @param  len
    253  *              the length of the calibration
    254  *
    255  *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
    256  */
    257 inv_error_t inv_load_cal_V1(unsigned char *calData, unsigned short len)
    258 {
    259     INVENSENSE_FUNC_START;
    260     const short expLen = 24;
    261     long newGyroData[3] = {0, 0, 0};
    262     long accelBias[3] = {0, 0, 0};
    263     float gyroBias[3] = {0, 0, 0};
    264     float newTemp = 0;
    265     int bin;
    266 
    267     LOADCAL_LOG("Entering inv_load_cal_V1\n");
    268 
    269     if (len != expLen) {
    270         MPL_LOGE("Calibration data type 1 must be %d bytes long\n", expLen);
    271         return INV_ERROR_FILE_READ;
    272     }
    273 
    274     newTemp = (float)inv_decode_temperature(
    275                 (unsigned short)calData[6] * 256 + calData[7]) / 65536.f;
    276     LOADCAL_LOG("newTemp = %f\n", newTemp);
    277 
    278     newGyroData[0] = ((long)calData[8]) * 256 + ((long)calData[9]);
    279     if (newGyroData[0] > 32767L)
    280         newGyroData[0] -= 65536L;
    281     LOADCAL_LOG("newGyroData[0] = %ld\n", newGyroData[0]);
    282     newGyroData[1] = ((long)calData[10]) * 256 + ((long)calData[11]);
    283     if (newGyroData[1] > 32767L)
    284         newGyroData[1] -= 65536L;
    285     LOADCAL_LOG("newGyroData[1] = %ld\n", newGyroData[1]);
    286     newGyroData[2] = ((long)calData[12]) * 256 + ((long)calData[13]);
    287     if (newGyroData[2] > 32767L)
    288         newGyroData[2] -= 65536L;
    289     LOADCAL_LOG("newGyroData[2] = %ld\n", newGyroData[2]);
    290 
    291     bin = FindTempBin(newTemp);
    292     LOADCAL_LOG("bin = %d\n", bin);
    293 
    294     gyroBias[0] = ((float)newGyroData[0]) / 131.072f;
    295     gyroBias[1] = ((float)newGyroData[1]) / 131.072f;
    296     gyroBias[2] = ((float)newGyroData[2]) / 131.072f;
    297     LOADCAL_LOG("gyroBias[0] = %f\n", gyroBias[0]);
    298     LOADCAL_LOG("gyroBias[1] = %f\n", gyroBias[1]);
    299     LOADCAL_LOG("gyroBias[2] = %f\n", gyroBias[2]);
    300 
    301     inv_obj.temp_data[bin][inv_obj.temp_ptrs[bin]] = newTemp;
    302     LOADCAL_LOG("temp_data[%d][%d] = %f",
    303                 bin, inv_obj.temp_ptrs[bin],
    304                 inv_obj.temp_data[bin][inv_obj.temp_ptrs[bin]]);
    305     inv_obj.x_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] = gyroBias[0];
    306     LOADCAL_LOG("x_gyro_temp_data[%d][%d] = %f\n",
    307                 bin, inv_obj.temp_ptrs[bin],
    308                 inv_obj.x_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]]);
    309     inv_obj.y_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] = gyroBias[1];
    310     LOADCAL_LOG("y_gyro_temp_data[%d][%d] = %f\n",
    311                 bin, inv_obj.temp_ptrs[bin],
    312                 inv_obj.y_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]]);
    313     inv_obj.z_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] = gyroBias[2];
    314     LOADCAL_LOG("z_gyro_temp_data[%d][%d] = %f\n",
    315                 bin, inv_obj.temp_ptrs[bin],
    316                 inv_obj.z_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]]);
    317 
    318     inv_obj.temp_ptrs[bin] = (inv_obj.temp_ptrs[bin] + 1) % PTS_PER_BIN;
    319     LOADCAL_LOG("temp_ptrs[%d] = %d\n", bin, inv_obj.temp_ptrs[bin]);
    320 
    321     if (inv_obj.temp_ptrs[bin] == 0)
    322         inv_obj.temp_valid_data[bin] = TRUE;
    323     LOADCAL_LOG("temp_valid_data[%d] = %ld\n",
    324                 bin, inv_obj.temp_valid_data[bin]);
    325 
    326     /* load accel biases and apply immediately */
    327     accelBias[0] = ((long)calData[14]) * 256 + ((long)calData[15]);
    328     if (accelBias[0] > 32767)
    329         accelBias[0] -= 65536L;
    330     accelBias[0] = (long)((long long)accelBias[0] * 65536L *
    331                           inv_obj.accel_sens / 1073741824L);
    332     LOADCAL_LOG("accelBias[0] = %ld\n", accelBias[0]);
    333     accelBias[1] = ((long)calData[16]) * 256 + ((long)calData[17]);
    334     if (accelBias[1] > 32767)
    335         accelBias[1] -= 65536L;
    336     accelBias[1] = (long)((long long)accelBias[1] * 65536L *
    337                           inv_obj.accel_sens / 1073741824L);
    338     LOADCAL_LOG("accelBias[1] = %ld\n", accelBias[1]);
    339     accelBias[2] = ((long)calData[18]) * 256 + ((int)calData[19]);
    340     if (accelBias[2] > 32767)
    341         accelBias[2] -= 65536L;
    342     accelBias[2] = (long)((long long)accelBias[2] * 65536L *
    343                           inv_obj.accel_sens / 1073741824L);
    344     LOADCAL_LOG("accelBias[2] = %ld\n", accelBias[2]);
    345     if (inv_set_array(INV_ACCEL_BIAS, accelBias)) {
    346         LOG_RESULT_LOCATION(inv_set_array(INV_ACCEL_BIAS, accelBias));
    347         return inv_set_array(INV_ACCEL_BIAS, accelBias);
    348     }
    349 
    350     inv_obj.got_no_motion_bias = TRUE;
    351     LOADCAL_LOG("got_no_motion_bias = 1\n");
    352     inv_obj.cal_loaded_flag = TRUE;
    353     LOADCAL_LOG("cal_loaded_flag = 1\n");
    354 
    355     LOADCAL_LOG("Exiting inv_load_cal_V1\n");
    356     return INV_SUCCESS;
    357 }
    358 
    359 /**
    360  *  @brief  Loads a type 2 set of calibration data.
    361  *          It parses a binary data set containing calibration data.
    362  *          The binary data set is intended to be loaded from a file.
    363  *          This calibrations data format stores values for (in order of
    364  *          appearance) :
    365  *          - temperature compensation : temperature data points,
    366  *          - temperature compensation : gyro biases data points for X, Y,
    367  *              and Z axes.
    368  *          - accel biases for X, Y, Z axes.
    369  *          This calibration data is produced internally by the MPL and its
    370  *          size is 2222 bytes (header and checksum included).
    371  *          Calibration format type 2 is currently <b>NOT</b> used and
    372  *          is substituted by type 4 : inv_load_cal_V4().
    373  *
    374  *  @pre    inv_dmp_open()
    375  *          @ifnot MPL_MF
    376  *              or inv_open_low_power_pedometer()
    377  *              or inv_eis_open_dmp()
    378  *          @endif
    379  *          must have been called.
    380  *
    381  *  @param  calData
    382  *              A pointer to an array of bytes to be parsed.
    383  *  @param  len
    384  *              the length of the calibration
    385  *
    386  *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
    387  */
    388 inv_error_t inv_load_cal_V2(unsigned char *calData, unsigned short len)
    389 {
    390     INVENSENSE_FUNC_START;
    391     const short expLen = 2222;
    392     long accel_bias[3];
    393     int ptr = INV_CAL_HDR_LEN;
    394 
    395     int i, j;
    396     long long tmp;
    397 
    398     LOADCAL_LOG("Entering inv_load_cal_V2\n");
    399 
    400     if (len != expLen) {
    401         MPL_LOGE("Calibration data type 2 must be %d bytes long (got %d)\n",
    402                  expLen, len);
    403         return INV_ERROR_FILE_READ;
    404     }
    405 
    406     for (i = 0; i < BINS; i++) {
    407         inv_obj.temp_ptrs[i] = 0;
    408         inv_obj.temp_ptrs[i] += 16777216L * ((long)calData[ptr++]);
    409         inv_obj.temp_ptrs[i] += 65536L * ((long)calData[ptr++]);
    410         inv_obj.temp_ptrs[i] += 256 * ((int)calData[ptr++]);
    411         inv_obj.temp_ptrs[i] += (int)calData[ptr++];
    412         LOADCAL_LOG("temp_ptrs[%d] = %d\n", i, inv_obj.temp_ptrs[i]);
    413     }
    414     for (i = 0; i < BINS; i++) {
    415         inv_obj.temp_valid_data[i] = 0;
    416         inv_obj.temp_valid_data[i] += 16777216L * ((long)calData[ptr++]);
    417         inv_obj.temp_valid_data[i] += 65536L * ((long)calData[ptr++]);
    418         inv_obj.temp_valid_data[i] += 256 * ((int)calData[ptr++]);
    419         inv_obj.temp_valid_data[i] += (int)calData[ptr++];
    420         LOADCAL_LOG("temp_valid_data[%d] = %ld\n",
    421                     i, inv_obj.temp_valid_data[i]);
    422     }
    423 
    424     for (i = 0; i < BINS; i++) {
    425         for (j = 0; j < PTS_PER_BIN; j++) {
    426             tmp = 0;
    427             tmp += 16777216LL * (long long)calData[ptr++];
    428             tmp += 65536LL * (long long)calData[ptr++];
    429             tmp += 256LL * (long long)calData[ptr++];
    430             tmp += (long long)calData[ptr++];
    431             if (tmp > 2147483648LL) {
    432                 tmp -= 4294967296LL;
    433             }
    434             inv_obj.temp_data[i][j] = ((float)tmp) / 65536.0f;
    435             LOADCAL_LOG("temp_data[%d][%d] = %f\n",
    436                         i, j, inv_obj.temp_data[i][j]);
    437         }
    438 
    439     }
    440     for (i = 0; i < BINS; i++) {
    441         for (j = 0; j < PTS_PER_BIN; j++) {
    442             tmp = 0;
    443             tmp += 16777216LL * (long long)calData[ptr++];
    444             tmp += 65536LL * (long long)calData[ptr++];
    445             tmp += 256LL * (long long)calData[ptr++];
    446             tmp += (long long)calData[ptr++];
    447             if (tmp > 2147483648LL) {
    448                 tmp -= 4294967296LL;
    449             }
    450             inv_obj.x_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    451             LOADCAL_LOG("x_gyro_temp_data[%d][%d] = %f\n",
    452                         i, j, inv_obj.x_gyro_temp_data[i][j]);
    453         }
    454     }
    455     for (i = 0; i < BINS; i++) {
    456         for (j = 0; j < PTS_PER_BIN; j++) {
    457             tmp = 0;
    458             tmp += 16777216LL * (long long)calData[ptr++];
    459             tmp += 65536LL * (long long)calData[ptr++];
    460             tmp += 256LL * (long long)calData[ptr++];
    461             tmp += (long long)calData[ptr++];
    462             if (tmp > 2147483648LL) {
    463                 tmp -= 4294967296LL;
    464             }
    465             inv_obj.y_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    466             LOADCAL_LOG("y_gyro_temp_data[%d][%d] = %f\n",
    467                         i, j, inv_obj.y_gyro_temp_data[i][j]);
    468         }
    469     }
    470     for (i = 0; i < BINS; i++) {
    471         for (j = 0; j < PTS_PER_BIN; j++) {
    472             tmp = 0;
    473             tmp += 16777216LL * (long long)calData[ptr++];
    474             tmp += 65536LL * (long long)calData[ptr++];
    475             tmp += 256LL * (long long)calData[ptr++];
    476             tmp += (long long)calData[ptr++];
    477             if (tmp > 2147483648LL) {
    478                 tmp -= 4294967296LL;
    479             }
    480             inv_obj.z_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    481             LOADCAL_LOG("z_gyro_temp_data[%d][%d] = %f\n",
    482                         i, j, inv_obj.z_gyro_temp_data[i][j]);
    483         }
    484     }
    485 
    486     /* read the accel biases */
    487     for (i = 0; i < 3; i++) {
    488         uint32_t t = 0;
    489         t += 16777216UL * ((uint32_t) calData[ptr++]);
    490         t += 65536UL * ((uint32_t) calData[ptr++]);
    491         t += 256u * ((uint32_t) calData[ptr++]);
    492         t += (uint32_t) calData[ptr++];
    493         accel_bias[i] = (int32_t) t;
    494         LOADCAL_LOG("accel_bias[%d] = %ld\n", i, accel_bias[i]);
    495     }
    496 
    497     if (inv_set_array(INV_ACCEL_BIAS, accel_bias)) {
    498         LOG_RESULT_LOCATION(inv_set_array(INV_ACCEL_BIAS, accel_bias));
    499         return inv_set_array(INV_ACCEL_BIAS, accel_bias);
    500     }
    501 
    502     inv_obj.got_no_motion_bias = TRUE;
    503     LOADCAL_LOG("got_no_motion_bias = 1\n");
    504     inv_obj.cal_loaded_flag = TRUE;
    505     LOADCAL_LOG("cal_loaded_flag = 1\n");
    506 
    507     LOADCAL_LOG("Exiting inv_load_cal_V2\n");
    508     return INV_SUCCESS;
    509 }
    510 
    511 /**
    512  *  @brief  Loads a type 3 set of calibration data.
    513  *          It parses a binary data set containing calibration data.
    514  *          The binary data set is intended to be loaded from a file.
    515  *          This calibrations data format stores values for (in order of
    516  *          appearance) :
    517  *          - temperature compensation : temperature data points,
    518  *          - temperature compensation : gyro biases data points for X, Y,
    519  *              and Z axes.
    520  *          - accel biases for X, Y, Z axes.
    521  *          - compass biases for X, Y, Z axes and bias tracking algorithm
    522  *              mock-up.
    523  *          This calibration data is produced internally by the MPL and its
    524  *          size is 2429 bytes (header and checksum included).
    525  *          Calibration format type 3 is currently <b>NOT</b> used and
    526  *          is substituted by type 4 : inv_load_cal_V4().
    527 
    528  *  @pre    inv_dmp_open()
    529  *          @ifnot MPL_MF
    530  *              or inv_open_low_power_pedometer()
    531  *              or inv_eis_open_dmp()
    532  *          @endif
    533  *          must have been called.
    534  *
    535  *  @param  calData
    536  *              A pointer to an array of bytes to be parsed.
    537  *  @param  len
    538  *              the length of the calibration
    539  *
    540  *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
    541  */
    542 inv_error_t inv_load_cal_V3(unsigned char *calData, unsigned short len)
    543 {
    544     INVENSENSE_FUNC_START;
    545     union doubleToLongLong {
    546         double db;
    547         unsigned long long ll;
    548     } dToLL;
    549 
    550     const short expLen = 2429;
    551     long bias[3];
    552     int i, j;
    553     int ptr = INV_CAL_HDR_LEN;
    554     long long tmp;
    555 
    556     LOADCAL_LOG("Entering inv_load_cal_V3\n");
    557 
    558     if (len != expLen) {
    559         MPL_LOGE("Calibration data type 3 must be %d bytes long (got %d)\n",
    560                  expLen, len);
    561         return INV_ERROR_FILE_READ;
    562     }
    563 
    564     for (i = 0; i < BINS; i++) {
    565         inv_obj.temp_ptrs[i] = 0;
    566         inv_obj.temp_ptrs[i] += 16777216L * ((long)calData[ptr++]);
    567         inv_obj.temp_ptrs[i] += 65536L * ((long)calData[ptr++]);
    568         inv_obj.temp_ptrs[i] += 256 * ((int)calData[ptr++]);
    569         inv_obj.temp_ptrs[i] += (int)calData[ptr++];
    570         LOADCAL_LOG("temp_ptrs[%d] = %d\n", i, inv_obj.temp_ptrs[i]);
    571     }
    572     for (i = 0; i < BINS; i++) {
    573         inv_obj.temp_valid_data[i] = 0;
    574         inv_obj.temp_valid_data[i] += 16777216L * ((long)calData[ptr++]);
    575         inv_obj.temp_valid_data[i] += 65536L * ((long)calData[ptr++]);
    576         inv_obj.temp_valid_data[i] += 256 * ((int)calData[ptr++]);
    577         inv_obj.temp_valid_data[i] += (int)calData[ptr++];
    578         LOADCAL_LOG("temp_valid_data[%d] = %ld\n",
    579                     i, inv_obj.temp_valid_data[i]);
    580     }
    581 
    582     for (i = 0; i < BINS; i++) {
    583         for (j = 0; j < PTS_PER_BIN; j++) {
    584             tmp = 0;
    585             tmp += 16777216LL * (long long)calData[ptr++];
    586             tmp += 65536LL * (long long)calData[ptr++];
    587             tmp += 256LL * (long long)calData[ptr++];
    588             tmp += (long long)calData[ptr++];
    589             if (tmp > 2147483648LL) {
    590                 tmp -= 4294967296LL;
    591             }
    592             inv_obj.temp_data[i][j] = ((float)tmp) / 65536.0f;
    593             LOADCAL_LOG("temp_data[%d][%d] = %f\n",
    594                         i, j, inv_obj.temp_data[i][j]);
    595         }
    596     }
    597 
    598     for (i = 0; i < BINS; i++) {
    599         for (j = 0; j < PTS_PER_BIN; j++) {
    600             tmp = 0;
    601             tmp += 16777216LL * (long long)calData[ptr++];
    602             tmp += 65536LL * (long long)calData[ptr++];
    603             tmp += 256LL * (long long)calData[ptr++];
    604             tmp += (long long)calData[ptr++];
    605             if (tmp > 2147483648LL) {
    606                 tmp -= 4294967296LL;
    607             }
    608             inv_obj.x_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    609             LOADCAL_LOG("x_gyro_temp_data[%d][%d] = %f\n",
    610                         i, j, inv_obj.x_gyro_temp_data[i][j]);
    611         }
    612     }
    613     for (i = 0; i < BINS; i++) {
    614         for (j = 0; j < PTS_PER_BIN; j++) {
    615             tmp = 0;
    616             tmp += 16777216LL * (long long)calData[ptr++];
    617             tmp += 65536LL * (long long)calData[ptr++];
    618             tmp += 256LL * (long long)calData[ptr++];
    619             tmp += (long long)calData[ptr++];
    620             if (tmp > 2147483648LL) {
    621                 tmp -= 4294967296LL;
    622             }
    623             inv_obj.y_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    624             LOADCAL_LOG("y_gyro_temp_data[%d][%d] = %f\n",
    625                         i, j, inv_obj.y_gyro_temp_data[i][j]);
    626         }
    627     }
    628     for (i = 0; i < BINS; i++) {
    629         for (j = 0; j < PTS_PER_BIN; j++) {
    630             tmp = 0;
    631             tmp += 16777216LL * (long long)calData[ptr++];
    632             tmp += 65536LL * (long long)calData[ptr++];
    633             tmp += 256LL * (long long)calData[ptr++];
    634             tmp += (long long)calData[ptr++];
    635             if (tmp > 2147483648LL) {
    636                 tmp -= 4294967296LL;
    637             }
    638             inv_obj.z_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    639             LOADCAL_LOG("z_gyro_temp_data[%d][%d] = %f\n",
    640                         i, j, inv_obj.z_gyro_temp_data[i][j]);
    641         }
    642     }
    643 
    644     /* read the accel biases */
    645     for (i = 0; i < 3; i++) {
    646         uint32_t t = 0;
    647         t += 16777216UL * ((uint32_t) calData[ptr++]);
    648         t += 65536UL * ((uint32_t) calData[ptr++]);
    649         t += 256u * ((uint32_t) calData[ptr++]);
    650         t += (uint32_t) calData[ptr++];
    651         bias[i] = (int32_t) t;
    652         LOADCAL_LOG("accel_bias[%d] = %ld\n", i, bias[i]);
    653     }
    654     if (inv_set_array(INV_ACCEL_BIAS, bias)) {
    655         LOG_RESULT_LOCATION(inv_set_array(INV_ACCEL_BIAS, bias));
    656         return inv_set_array(INV_ACCEL_BIAS, bias);
    657     }
    658 
    659     /* read the compass biases */
    660     inv_obj.got_compass_bias = (int)calData[ptr++];
    661     inv_obj.got_init_compass_bias = (int)calData[ptr++];
    662     inv_obj.compass_state = (int)calData[ptr++];
    663 
    664     for (i = 0; i < 3; i++) {
    665         uint32_t t = 0;
    666         t += 16777216UL * ((uint32_t) calData[ptr++]);
    667         t += 65536UL * ((uint32_t) calData[ptr++]);
    668         t += 256u * ((uint32_t) calData[ptr++]);
    669         t += (uint32_t) calData[ptr++];
    670         inv_obj.compass_bias_error[i] = (int32_t) t;
    671         LOADCAL_LOG("compass_bias_error[%d] = %ld\n", i,
    672                     inv_obj.compass_bias_error[i]);
    673     }
    674     for (i = 0; i < 3; i++) {
    675         uint32_t t = 0;
    676         t += 16777216UL * ((uint32_t) calData[ptr++]);
    677         t += 65536UL * ((uint32_t) calData[ptr++]);
    678         t += 256u * ((uint32_t) calData[ptr++]);
    679         t += (uint32_t) calData[ptr++];
    680         inv_obj.init_compass_bias[i] = (int32_t) t;
    681         LOADCAL_LOG("init_compass_bias[%d] = %ld\n", i,
    682                     inv_obj.init_compass_bias[i]);
    683     }
    684     for (i = 0; i < 3; i++) {
    685         uint32_t t = 0;
    686         t += 16777216UL * ((uint32_t) calData[ptr++]);
    687         t += 65536UL * ((uint32_t) calData[ptr++]);
    688         t += 256u * ((uint32_t) calData[ptr++]);
    689         t += (uint32_t) calData[ptr++];
    690         inv_obj.compass_bias[i] = (int32_t) t;
    691         LOADCAL_LOG("compass_bias[%d] = %ld\n", i, inv_obj.compass_bias[i]);
    692     }
    693     for (i = 0; i < 18; i++) {
    694         uint32_t t = 0;
    695         t += 16777216UL * ((uint32_t) calData[ptr++]);
    696         t += 65536UL * ((uint32_t) calData[ptr++]);
    697         t += 256u * ((uint32_t) calData[ptr++]);
    698         t += (uint32_t) calData[ptr++];
    699         inv_obj.compass_peaks[i] = (int32_t) t;
    700         LOADCAL_LOG("compass_peaks[%d] = %d\n", i, inv_obj.compass_peaks[i]);
    701     }
    702     for (i = 0; i < 3; i++) {
    703         dToLL.ll = 0;
    704         dToLL.ll += 72057594037927936ULL * ((unsigned long long)calData[ptr++]);
    705         dToLL.ll += 281474976710656ULL * ((unsigned long long)calData[ptr++]);
    706         dToLL.ll += 1099511627776ULL * ((unsigned long long)calData[ptr++]);
    707         dToLL.ll += 4294967296LL * ((unsigned long long)calData[ptr++]);
    708         dToLL.ll += 16777216ULL * ((unsigned long long)calData[ptr++]);
    709         dToLL.ll += 65536ULL * ((unsigned long long)calData[ptr++]);
    710         dToLL.ll += 256LL * ((unsigned long long)calData[ptr++]);
    711         dToLL.ll += (unsigned long long)calData[ptr++];
    712 
    713         inv_obj.compass_bias_v[i] = dToLL.db;
    714         LOADCAL_LOG("compass_bias_v[%d] = %lf\n", i, inv_obj.compass_bias_v[i]);
    715     }
    716     for (i = 0; i < 9; i++) {
    717         dToLL.ll = 0;
    718         dToLL.ll += 72057594037927936ULL * ((unsigned long long)calData[ptr++]);
    719         dToLL.ll += 281474976710656ULL * ((unsigned long long)calData[ptr++]);
    720         dToLL.ll += 1099511627776ULL * ((unsigned long long)calData[ptr++]);
    721         dToLL.ll += 4294967296LL * ((unsigned long long)calData[ptr++]);
    722         dToLL.ll += 16777216ULL * ((unsigned long long)calData[ptr++]);
    723         dToLL.ll += 65536ULL * ((unsigned long long)calData[ptr++]);
    724         dToLL.ll += 256LL * ((unsigned long long)calData[ptr++]);
    725         dToLL.ll += (unsigned long long)calData[ptr++];
    726 
    727         inv_obj.compass_bias_ptr[i] = dToLL.db;
    728         LOADCAL_LOG("compass_bias_ptr[%d] = %lf\n", i,
    729                     inv_obj.compass_bias_ptr[i]);
    730     }
    731 
    732     inv_obj.got_no_motion_bias = TRUE;
    733     LOADCAL_LOG("got_no_motion_bias = 1\n");
    734     inv_obj.cal_loaded_flag = TRUE;
    735     LOADCAL_LOG("cal_loaded_flag = 1\n");
    736 
    737     LOADCAL_LOG("Exiting inv_load_cal_V3\n");
    738     return INV_SUCCESS;
    739 }
    740 
    741 /**
    742  *  @brief  Loads a type 4 set of calibration data.
    743  *          It parses a binary data set containing calibration data.
    744  *          The binary data set is intended to be loaded from a file.
    745  *          This calibrations data format stores values for (in order of
    746  *          appearance) :
    747  *          - temperature compensation : temperature data points,
    748  *          - temperature compensation : gyro biases data points for X, Y,
    749  *              and Z axes.
    750  *          - accel biases for X, Y, Z axes.
    751  *          - compass biases for X, Y, Z axes, compass scale, and bias
    752  *              tracking algorithm  mock-up.
    753  *          This calibration data is produced internally by the MPL and its
    754  *          size is 2777 bytes (header and checksum included).
    755  *          Calibration format type 4 is currently used and
    756  *          substitutes type 2 (inv_load_cal_V2()) and 3 (inv_load_cal_V3()).
    757  *
    758  *  @pre    inv_dmp_open()
    759  *          @ifnot MPL_MF
    760  *              or inv_open_low_power_pedometer()
    761  *              or inv_eis_open_dmp()
    762  *          @endif
    763  *          must have been called.
    764  *
    765  *  @param  calData
    766  *              A pointer to an array of bytes to be parsed.
    767  *  @param  len
    768  *              the length of the calibration
    769  *
    770  *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
    771  */
    772 inv_error_t inv_load_cal_V4(unsigned char *calData, unsigned short len)
    773 {
    774     INVENSENSE_FUNC_START;
    775     union doubleToLongLong {
    776         double db;
    777         unsigned long long ll;
    778     } dToLL;
    779 
    780     const unsigned int expLen = 2782;
    781     long bias[3];
    782     int ptr = INV_CAL_HDR_LEN;
    783     int i, j;
    784     long long tmp;
    785     inv_error_t result;
    786 
    787     LOADCAL_LOG("Entering inv_load_cal_V4\n");
    788 
    789     if (len != expLen) {
    790         MPL_LOGE("Calibration data type 4 must be %d bytes long (got %d)\n",
    791                  expLen, len);
    792         return INV_ERROR_FILE_READ;
    793     }
    794 
    795     for (i = 0; i < BINS; i++) {
    796         inv_obj.temp_ptrs[i] = 0;
    797         inv_obj.temp_ptrs[i] += 16777216L * ((long)calData[ptr++]);
    798         inv_obj.temp_ptrs[i] += 65536L * ((long)calData[ptr++]);
    799         inv_obj.temp_ptrs[i] += 256 * ((int)calData[ptr++]);
    800         inv_obj.temp_ptrs[i] += (int)calData[ptr++];
    801         LOADCAL_LOG("temp_ptrs[%d] = %d\n", i, inv_obj.temp_ptrs[i]);
    802     }
    803     for (i = 0; i < BINS; i++) {
    804         inv_obj.temp_valid_data[i] = 0;
    805         inv_obj.temp_valid_data[i] += 16777216L * ((long)calData[ptr++]);
    806         inv_obj.temp_valid_data[i] += 65536L * ((long)calData[ptr++]);
    807         inv_obj.temp_valid_data[i] += 256 * ((int)calData[ptr++]);
    808         inv_obj.temp_valid_data[i] += (int)calData[ptr++];
    809         LOADCAL_LOG("temp_valid_data[%d] = %ld\n",
    810                     i, inv_obj.temp_valid_data[i]);
    811     }
    812 
    813     for (i = 0; i < BINS; i++) {
    814         for (j = 0; j < PTS_PER_BIN; j++) {
    815             tmp = 0;
    816             tmp += 16777216LL * (long long)calData[ptr++];
    817             tmp += 65536LL * (long long)calData[ptr++];
    818             tmp += 256LL * (long long)calData[ptr++];
    819             tmp += (long long)calData[ptr++];
    820             if (tmp > 2147483648LL) {
    821                 tmp -= 4294967296LL;
    822             }
    823             inv_obj.temp_data[i][j] = ((float)tmp) / 65536.0f;
    824             LOADCAL_LOG("temp_data[%d][%d] = %f\n",
    825                         i, j, inv_obj.temp_data[i][j]);
    826         }
    827     }
    828 
    829     for (i = 0; i < BINS; i++) {
    830         for (j = 0; j < PTS_PER_BIN; j++) {
    831             tmp = 0;
    832             tmp += 16777216LL * (long long)calData[ptr++];
    833             tmp += 65536LL * (long long)calData[ptr++];
    834             tmp += 256LL * (long long)calData[ptr++];
    835             tmp += (long long)calData[ptr++];
    836             if (tmp > 2147483648LL) {
    837                 tmp -= 4294967296LL;
    838             }
    839             inv_obj.x_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    840             LOADCAL_LOG("x_gyro_temp_data[%d][%d] = %f\n",
    841                         i, j, inv_obj.x_gyro_temp_data[i][j]);
    842         }
    843     }
    844     for (i = 0; i < BINS; i++) {
    845         for (j = 0; j < PTS_PER_BIN; j++) {
    846             tmp = 0;
    847             tmp += 16777216LL * (long long)calData[ptr++];
    848             tmp += 65536LL * (long long)calData[ptr++];
    849             tmp += 256LL * (long long)calData[ptr++];
    850             tmp += (long long)calData[ptr++];
    851             if (tmp > 2147483648LL) {
    852                 tmp -= 4294967296LL;
    853             }
    854             inv_obj.y_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    855             LOADCAL_LOG("y_gyro_temp_data[%d][%d] = %f\n",
    856                         i, j, inv_obj.y_gyro_temp_data[i][j]);
    857         }
    858     }
    859     for (i = 0; i < BINS; i++) {
    860         for (j = 0; j < PTS_PER_BIN; j++) {
    861             tmp = 0;
    862             tmp += 16777216LL * (long long)calData[ptr++];
    863             tmp += 65536LL * (long long)calData[ptr++];
    864             tmp += 256LL * (long long)calData[ptr++];
    865             tmp += (long long)calData[ptr++];
    866             if (tmp > 2147483648LL) {
    867                 tmp -= 4294967296LL;
    868             }
    869             inv_obj.z_gyro_temp_data[i][j] = ((float)tmp) / 65536.0f;
    870             LOADCAL_LOG("z_gyro_temp_data[%d][%d] = %f\n",
    871                         i, j, inv_obj.z_gyro_temp_data[i][j]);
    872         }
    873     }
    874 
    875     /* read the accel biases */
    876     for (i = 0; i < 3; i++) {
    877         uint32_t t = 0;
    878         t += 16777216UL * ((uint32_t) calData[ptr++]);
    879         t += 65536UL * ((uint32_t) calData[ptr++]);
    880         t += 256u * ((uint32_t) calData[ptr++]);
    881         t += (uint32_t) calData[ptr++];
    882         bias[i] = (int32_t) t;
    883         LOADCAL_LOG("accel_bias[%d] = %ld\n", i, bias[i]);
    884     }
    885     if (inv_set_array(INV_ACCEL_BIAS, bias)) {
    886         LOG_RESULT_LOCATION(inv_set_array(INV_ACCEL_BIAS, bias));
    887         return inv_set_array(INV_ACCEL_BIAS, bias);
    888     }
    889 
    890     /* read the compass biases */
    891     inv_reset_compass_calibration();
    892 
    893     inv_obj.got_compass_bias = (int)calData[ptr++];
    894     LOADCAL_LOG("got_compass_bias = %ld\n", inv_obj.got_compass_bias);
    895     inv_obj.got_init_compass_bias = (int)calData[ptr++];
    896     LOADCAL_LOG("got_init_compass_bias = %d\n", inv_obj.got_init_compass_bias);
    897     inv_obj.compass_state = (int)calData[ptr++];
    898     LOADCAL_LOG("compass_state = %ld\n", inv_obj.compass_state);
    899 
    900     for (i = 0; i < 3; i++) {
    901         uint32_t t = 0;
    902         t += 16777216UL * ((uint32_t) calData[ptr++]);
    903         t += 65536UL * ((uint32_t) calData[ptr++]);
    904         t += 256u * ((uint32_t) calData[ptr++]);
    905         t += (uint32_t) calData[ptr++];
    906         inv_obj.compass_bias_error[i] = (int32_t) t;
    907         LOADCAL_LOG("compass_bias_error[%d] = %ld\n", i,
    908                     inv_obj.compass_bias_error[i]);
    909     }
    910     for (i = 0; i < 3; i++) {
    911         uint32_t t = 0;
    912         t += 16777216UL * ((uint32_t) calData[ptr++]);
    913         t += 65536UL * ((uint32_t) calData[ptr++]);
    914         t += 256u * ((uint32_t) calData[ptr++]);
    915         t += (uint32_t) calData[ptr++];
    916         inv_obj.init_compass_bias[i] = (int32_t) t;
    917         LOADCAL_LOG("init_compass_bias[%d] = %ld\n", i,
    918                     inv_obj.init_compass_bias[i]);
    919     }
    920     for (i = 0; i < 3; i++) {
    921         uint32_t t = 0;
    922         t += 16777216UL * ((uint32_t) calData[ptr++]);
    923         t += 65536UL * ((uint32_t) calData[ptr++]);
    924         t += 256u * ((uint32_t) calData[ptr++]);
    925         t += (uint32_t) calData[ptr++];
    926         inv_obj.compass_bias[i] = (int32_t) t;
    927         LOADCAL_LOG("compass_bias[%d] = %ld\n", i, inv_obj.compass_bias[i]);
    928     }
    929     for (i = 0; i < 18; i++) {
    930         uint32_t t = 0;
    931         t += 16777216UL * ((uint32_t) calData[ptr++]);
    932         t += 65536UL * ((uint32_t) calData[ptr++]);
    933         t += 256u * ((uint32_t) calData[ptr++]);
    934         t += (uint32_t) calData[ptr++];
    935         inv_obj.compass_peaks[i] = (int32_t) t;
    936         LOADCAL_LOG("compass_peaks[%d] = %d\n", i, inv_obj.compass_peaks[i]);
    937     }
    938     for (i = 0; i < 3; i++) {
    939         dToLL.ll = 72057594037927936ULL * ((unsigned long long)calData[ptr++]);
    940         dToLL.ll += 281474976710656ULL * ((unsigned long long)calData[ptr++]);
    941         dToLL.ll += 1099511627776ULL * ((unsigned long long)calData[ptr++]);
    942         dToLL.ll += 4294967296LL * ((unsigned long long)calData[ptr++]);
    943         dToLL.ll += 16777216ULL * ((unsigned long long)calData[ptr++]);
    944         dToLL.ll += 65536ULL * ((unsigned long long)calData[ptr++]);
    945         dToLL.ll += 256LL * ((unsigned long long)calData[ptr++]);
    946         dToLL.ll += (unsigned long long)calData[ptr++];
    947 
    948         inv_obj.compass_bias_v[i] = dToLL.db;
    949         LOADCAL_LOG("compass_bias_v[%d] = %lf\n", i, inv_obj.compass_bias_v[i]);
    950     }
    951     for (i = 0; i < 9; i++) {
    952         dToLL.ll = 72057594037927936ULL * ((unsigned long long)calData[ptr++]);
    953         dToLL.ll += 281474976710656ULL * ((unsigned long long)calData[ptr++]);
    954         dToLL.ll += 1099511627776ULL * ((unsigned long long)calData[ptr++]);
    955         dToLL.ll += 4294967296LL * ((unsigned long long)calData[ptr++]);
    956         dToLL.ll += 16777216ULL * ((unsigned long long)calData[ptr++]);
    957         dToLL.ll += 65536ULL * ((unsigned long long)calData[ptr++]);
    958         dToLL.ll += 256LL * ((unsigned long long)calData[ptr++]);
    959         dToLL.ll += (unsigned long long)calData[ptr++];
    960 
    961         inv_obj.compass_bias_ptr[i] = dToLL.db;
    962         LOADCAL_LOG("compass_bias_ptr[%d] = %lf\n", i,
    963                     inv_obj.compass_bias_ptr[i]);
    964     }
    965     for (i = 0; i < 3; i++) {
    966         uint32_t t = 0;
    967         t += 16777216UL * ((uint32_t) calData[ptr++]);
    968         t += 65536UL * ((uint32_t) calData[ptr++]);
    969         t += 256u * ((uint32_t) calData[ptr++]);
    970         t += (uint32_t) calData[ptr++];
    971         inv_obj.compass_scale[i] = (int32_t) t;
    972         LOADCAL_LOG("compass_scale[%d] = %d\n", i, (int32_t) t);
    973     }
    974     for (i = 0; i < 6; i++) {
    975         dToLL.ll = 72057594037927936ULL * ((unsigned long long)calData[ptr++]);
    976         dToLL.ll += 281474976710656ULL * ((unsigned long long)calData[ptr++]);
    977         dToLL.ll += 1099511627776ULL * ((unsigned long long)calData[ptr++]);
    978         dToLL.ll += 4294967296LL * ((unsigned long long)calData[ptr++]);
    979         dToLL.ll += 16777216ULL * ((unsigned long long)calData[ptr++]);
    980         dToLL.ll += 65536ULL * ((unsigned long long)calData[ptr++]);
    981         dToLL.ll += 256LL * ((unsigned long long)calData[ptr++]);
    982         dToLL.ll += (unsigned long long)calData[ptr++];
    983 
    984         inv_obj.compass_prev_xty[i] = dToLL.db;
    985         LOADCAL_LOG("compass_prev_xty[%d] = %f\n", i, dToLL.db);
    986     }
    987     for (i = 0; i < 36; i++) {
    988         dToLL.ll = 72057594037927936ULL * ((unsigned long long)calData[ptr++]);
    989         dToLL.ll += 281474976710656ULL * ((unsigned long long)calData[ptr++]);
    990         dToLL.ll += 1099511627776ULL * ((unsigned long long)calData[ptr++]);
    991         dToLL.ll += 4294967296LL * ((unsigned long long)calData[ptr++]);
    992         dToLL.ll += 16777216ULL * ((unsigned long long)calData[ptr++]);
    993         dToLL.ll += 65536ULL * ((unsigned long long)calData[ptr++]);
    994         dToLL.ll += 256LL * ((unsigned long long)calData[ptr++]);
    995         dToLL.ll += (unsigned long long)calData[ptr++];
    996 
    997         inv_obj.compass_prev_m[i] = dToLL.db;
    998         LOADCAL_LOG("compass_prev_m[%d] = %f\n", i, dToLL.db);
    999     }
   1000 
   1001     /* Load the compass offset flag and values */
   1002     inv_obj.flags[INV_COMPASS_OFFSET_VALID] = calData[ptr++];
   1003     inv_obj.compass_offsets[0] = calData[ptr++];
   1004     inv_obj.compass_offsets[1] = calData[ptr++];
   1005     inv_obj.compass_offsets[2] = calData[ptr++];
   1006 
   1007     inv_obj.compass_accuracy = calData[ptr++];
   1008     /* push the compass offset values to the device */
   1009     result = inv_set_compass_offset();
   1010 
   1011     if (result == INV_SUCCESS) {
   1012         if (inv_compass_check_range() != INV_SUCCESS) {
   1013             MPL_LOGI("range check fail");
   1014             inv_reset_compass_calibration();
   1015             inv_obj.flags[INV_COMPASS_OFFSET_VALID] = 0;
   1016             inv_set_compass_offset();
   1017         }
   1018     }
   1019 
   1020     inv_obj.got_no_motion_bias = TRUE;
   1021     LOADCAL_LOG("got_no_motion_bias = 1\n");
   1022     inv_obj.cal_loaded_flag = TRUE;
   1023     LOADCAL_LOG("cal_loaded_flag = 1\n");
   1024 
   1025     LOADCAL_LOG("Exiting inv_load_cal_V4\n");
   1026     return INV_SUCCESS;
   1027 }
   1028 
   1029 /**
   1030  *  @brief  Loads a type 5 set of calibration data.
   1031  *          It parses a binary data set containing calibration data.
   1032  *          The binary data set is intended to be loaded from a file.
   1033  *          This calibrations data format stores values for (in order of
   1034  *          appearance) :
   1035  *          - temperature,
   1036  *          - gyro biases for X, Y, Z axes,
   1037  *          - accel biases for X, Y, Z axes.
   1038  *          This calibration data would normally be produced by the MPU Self
   1039  *          Test and its size is 36 bytes (header and checksum included).
   1040  *          Calibration format type 5 is produced by the MPU Self Test and
   1041  *          substitutes the type 1 : inv_load_cal_V1().
   1042  *
   1043  *  @pre    inv_dmp_open()
   1044  *          @ifnot MPL_MF
   1045  *              or inv_open_low_power_pedometer()
   1046  *              or inv_eis_open_dmp()
   1047  *          @endif
   1048  *          must have been called.
   1049  *
   1050  *  @param  calData
   1051  *              A pointer to an array of bytes to be parsed.
   1052  *  @param  len
   1053  *              the length of the calibration
   1054  *
   1055  *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
   1056  */
   1057 inv_error_t inv_load_cal_V5(unsigned char *calData, unsigned short len)
   1058 {
   1059     INVENSENSE_FUNC_START;
   1060     const short expLen = 36;
   1061     long accelBias[3] = { 0, 0, 0 };
   1062     float gyroBias[3] = { 0, 0, 0 };
   1063 
   1064     int ptr = INV_CAL_HDR_LEN;
   1065     unsigned short temp;
   1066     float newTemp;
   1067     int bin;
   1068     int i;
   1069 
   1070     LOADCAL_LOG("Entering inv_load_cal_V5\n");
   1071 
   1072     if (len != expLen) {
   1073         MPL_LOGE("Calibration data type 5 must be %d bytes long (got %d)\n",
   1074                  expLen, len);
   1075         return INV_ERROR_FILE_READ;
   1076     }
   1077 
   1078     /* load the temperature */
   1079     temp = (unsigned short)calData[ptr++] * (1L << 8);
   1080     temp += calData[ptr++];
   1081     newTemp = (float)inv_decode_temperature(temp) / 65536.f;
   1082     LOADCAL_LOG("newTemp = %f\n", newTemp);
   1083 
   1084     /* load the gyro biases (represented in 2 ^ 16 == 1 dps) */
   1085     for (i = 0; i < 3; i++) {
   1086         int32_t tmp = 0;
   1087         tmp += (int32_t) calData[ptr++] * (1L << 24);
   1088         tmp += (int32_t) calData[ptr++] * (1L << 16);
   1089         tmp += (int32_t) calData[ptr++] * (1L << 8);
   1090         tmp += (int32_t) calData[ptr++];
   1091         gyroBias[i] = (float)tmp / 65536.0f;
   1092         LOADCAL_LOG("gyroBias[%d] = %f\n", i, gyroBias[i]);
   1093     }
   1094     /* find the temperature bin */
   1095     bin = FindTempBin(newTemp);
   1096 
   1097     /* populate the temp comp data structure */
   1098     inv_obj.temp_data[bin][inv_obj.temp_ptrs[bin]] = newTemp;
   1099     LOADCAL_LOG("temp_data[%d][%d] = %f\n",
   1100                 bin, inv_obj.temp_ptrs[bin], newTemp);
   1101 
   1102     inv_obj.x_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] = gyroBias[0];
   1103     LOADCAL_LOG("x_gyro_temp_data[%d][%d] = %f\n",
   1104                 bin, inv_obj.temp_ptrs[bin], gyroBias[0]);
   1105     inv_obj.y_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] = gyroBias[1];
   1106     LOADCAL_LOG("y_gyro_temp_data[%d][%d] = %f\n",
   1107                 bin, inv_obj.temp_ptrs[bin], gyroBias[1]);
   1108     inv_obj.z_gyro_temp_data[bin][inv_obj.temp_ptrs[bin]] = gyroBias[2];
   1109     LOADCAL_LOG("z_gyro_temp_data[%d][%d] = %f\n",
   1110                 bin, inv_obj.temp_ptrs[bin], gyroBias[2]);
   1111     inv_obj.temp_ptrs[bin] = (inv_obj.temp_ptrs[bin] + 1) % PTS_PER_BIN;
   1112     LOADCAL_LOG("temp_ptrs[%d] = %d\n", bin, inv_obj.temp_ptrs[bin]);
   1113 
   1114     if (inv_obj.temp_ptrs[bin] == 0)
   1115         inv_obj.temp_valid_data[bin] = TRUE;
   1116     LOADCAL_LOG("temp_valid_data[%d] = %ld\n",
   1117                 bin, inv_obj.temp_valid_data[bin]);
   1118 
   1119     /* load accel biases (represented in 2 ^ 16 == 1 gee)
   1120        and apply immediately */
   1121     for (i = 0; i < 3; i++) {
   1122         int32_t tmp = 0;
   1123         tmp += (int32_t) calData[ptr++] * (1L << 24);
   1124         tmp += (int32_t) calData[ptr++] * (1L << 16);
   1125         tmp += (int32_t) calData[ptr++] * (1L << 8);
   1126         tmp += (int32_t) calData[ptr++];
   1127         accelBias[i] = (long)tmp;
   1128         LOADCAL_LOG("accelBias[%d] = %ld\n", i, accelBias[i]);
   1129     }
   1130     if (inv_set_array(INV_ACCEL_BIAS, accelBias)) {
   1131         LOG_RESULT_LOCATION(inv_set_array(INV_ACCEL_BIAS, accelBias));
   1132         return inv_set_array(INV_ACCEL_BIAS, accelBias);
   1133     }
   1134 
   1135     inv_obj.got_no_motion_bias = TRUE;
   1136     LOADCAL_LOG("got_no_motion_bias = 1\n");
   1137     inv_obj.cal_loaded_flag = TRUE;
   1138     LOADCAL_LOG("cal_loaded_flag = 1\n");
   1139 
   1140     LOADCAL_LOG("Exiting inv_load_cal_V5\n");
   1141     return INV_SUCCESS;
   1142 }
   1143 
   1144 /**
   1145  * @brief   Loads a set of calibration data.
   1146  *          It parses a binary data set containing calibration data.
   1147  *          The binary data set is intended to be loaded from a file.
   1148  *
   1149  * @pre     inv_dmp_open()
   1150  *          @ifnot MPL_MF
   1151  *              or inv_open_low_power_pedometer()
   1152  *              or inv_eis_open_dmp()
   1153  *          @endif
   1154  *          must have been called.
   1155  *
   1156  * @param   calData
   1157  *              A pointer to an array of bytes to be parsed.
   1158  *
   1159  * @return  INV_SUCCESS if successful, a non-zero error code otherwise.
   1160  */
   1161 inv_error_t inv_load_cal(unsigned char *calData)
   1162 {
   1163     INVENSENSE_FUNC_START;
   1164     int calType = 0;
   1165     int len = 0;
   1166     int ptr;
   1167     uint32_t chk = 0;
   1168     uint32_t cmp_chk = 0;
   1169 
   1170     tMLLoadFunc loaders[] = {
   1171         inv_load_cal_V0,
   1172         inv_load_cal_V1,
   1173         inv_load_cal_V2,
   1174         inv_load_cal_V3,
   1175         inv_load_cal_V4,
   1176         inv_load_cal_V5
   1177     };
   1178 
   1179     if (inv_get_state() < INV_STATE_DMP_OPENED)
   1180         return INV_ERROR_SM_IMPROPER_STATE;
   1181 
   1182     /* read the header (type and len)
   1183        len is the total record length including header and checksum */
   1184     len = 0;
   1185     len += 16777216L * ((int)calData[0]);
   1186     len += 65536L * ((int)calData[1]);
   1187     len += 256 * ((int)calData[2]);
   1188     len += (int)calData[3];
   1189 
   1190     calType = ((int)calData[4]) * 256 + ((int)calData[5]);
   1191     if (calType > 5) {
   1192         MPL_LOGE("Unsupported calibration file format %d. "
   1193                  "Valid types 0..5\n", calType);
   1194         return INV_ERROR_INVALID_PARAMETER;
   1195     }
   1196 
   1197     /* check the checksum */
   1198     chk = 0;
   1199     ptr = len - INV_CAL_CHK_LEN;
   1200 
   1201     chk += 16777216L * ((uint32_t) calData[ptr++]);
   1202     chk += 65536L * ((uint32_t) calData[ptr++]);
   1203     chk += 256 * ((uint32_t) calData[ptr++]);
   1204     chk += (uint32_t) calData[ptr++];
   1205 
   1206     cmp_chk = inv_checksum(calData + INV_CAL_HDR_LEN,
   1207                            len - (INV_CAL_HDR_LEN + INV_CAL_CHK_LEN));
   1208 
   1209     if (chk != cmp_chk) {
   1210         return INV_ERROR_CALIBRATION_CHECKSUM;
   1211     }
   1212 
   1213     /* call the proper method to read in the data */
   1214     return loaders[calType] (calData, len);
   1215 }
   1216 
   1217 /**
   1218  *  @brief  Stores a set of calibration data.
   1219  *          It generates a binary data set containing calibration data.
   1220  *          The binary data set is intended to be stored into a file.
   1221  *
   1222  *  @pre    inv_dmp_open()
   1223  *
   1224  *  @param  calData
   1225  *              A pointer to an array of bytes to be stored.
   1226  *  @param  length
   1227  *              The amount of bytes available in the array.
   1228  *
   1229  *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
   1230  */
   1231 inv_error_t inv_store_cal(unsigned char *calData, int length)
   1232 {
   1233     INVENSENSE_FUNC_START;
   1234     int ptr = 0;
   1235     int i = 0;
   1236     int j = 0;
   1237     long long tmp;
   1238     uint32_t chk;
   1239     long bias[3];
   1240     //unsigned char state;
   1241     union doubleToLongLong {
   1242         double db;
   1243         unsigned long long ll;
   1244     } dToLL;
   1245 
   1246     if (inv_get_state() < INV_STATE_DMP_OPENED)
   1247         return INV_ERROR_SM_IMPROPER_STATE;
   1248 
   1249     STORECAL_LOG("Entering inv_store_cal\n");
   1250 
   1251     // length
   1252     calData[0] = (unsigned char)((length >> 24) & 0xff);
   1253     calData[1] = (unsigned char)((length >> 16) & 0xff);
   1254     calData[2] = (unsigned char)((length >> 8) & 0xff);
   1255     calData[3] = (unsigned char)(length & 0xff);
   1256     STORECAL_LOG("calLen = %d\n", length);
   1257 
   1258     // calibration data format type
   1259     calData[4] = 0;
   1260     calData[5] = 4;
   1261     STORECAL_LOG("calType = %d\n", (int)calData[4] * 256 + calData[5]);
   1262 
   1263     // data
   1264     ptr = 6;
   1265     for (i = 0; i < BINS; i++) {
   1266         tmp = (int)inv_obj.temp_ptrs[i];
   1267         calData[ptr++] = (unsigned char)((tmp >> 24) & 0xff);
   1268         calData[ptr++] = (unsigned char)((tmp >> 16) & 0xff);
   1269         calData[ptr++] = (unsigned char)((tmp >> 8) & 0xff);
   1270         calData[ptr++] = (unsigned char)(tmp & 0xff);
   1271         STORECAL_LOG("temp_ptrs[%d] = %lld\n", i, tmp);
   1272     }
   1273 
   1274     for (i = 0; i < BINS; i++) {
   1275         tmp = (int)inv_obj.temp_valid_data[i];
   1276         calData[ptr++] = (unsigned char)((tmp >> 24) & 0xff);
   1277         calData[ptr++] = (unsigned char)((tmp >> 16) & 0xff);
   1278         calData[ptr++] = (unsigned char)((tmp >> 8) & 0xff);
   1279         calData[ptr++] = (unsigned char)(tmp & 0xff);
   1280         STORECAL_LOG("temp_valid_data[%d] = %lld\n", i, tmp);
   1281     }
   1282     for (i = 0; i < BINS; i++) {
   1283         for (j = 0; j < PTS_PER_BIN; j++) {
   1284             tmp = (long long)(inv_obj.temp_data[i][j] * 65536.0f);
   1285             if (tmp < 0) {
   1286                 tmp += 4294967296LL;
   1287             }
   1288             calData[ptr++] = (unsigned char)((tmp >> 24) & 0xff);
   1289             calData[ptr++] = (unsigned char)((tmp >> 16) & 0xff);
   1290             calData[ptr++] = (unsigned char)((tmp >> 8) & 0xff);
   1291             calData[ptr++] = (unsigned char)(tmp & 0xff);
   1292             STORECAL_LOG("temp_data[%d][%d] = %f\n",
   1293                          i, j, inv_obj.temp_data[i][j]);
   1294         }
   1295     }
   1296 
   1297     for (i = 0; i < BINS; i++) {
   1298         for (j = 0; j < PTS_PER_BIN; j++) {
   1299             tmp = (long long)(inv_obj.x_gyro_temp_data[i][j] * 65536.0f);
   1300             if (tmp < 0) {
   1301                 tmp += 4294967296LL;
   1302             }
   1303             calData[ptr++] = (unsigned char)((tmp >> 24) & 0xff);
   1304             calData[ptr++] = (unsigned char)((tmp >> 16) & 0xff);
   1305             calData[ptr++] = (unsigned char)((tmp >> 8) & 0xff);
   1306             calData[ptr++] = (unsigned char)(tmp & 0xff);
   1307             STORECAL_LOG("x_gyro_temp_data[%d][%d] = %f\n",
   1308                          i, j, inv_obj.x_gyro_temp_data[i][j]);
   1309         }
   1310     }
   1311     for (i = 0; i < BINS; i++) {
   1312         for (j = 0; j < PTS_PER_BIN; j++) {
   1313             tmp = (long long)(inv_obj.y_gyro_temp_data[i][j] * 65536.0f);
   1314             if (tmp < 0) {
   1315                 tmp += 4294967296LL;
   1316             }
   1317             calData[ptr++] = (unsigned char)((tmp >> 24) & 0xff);
   1318             calData[ptr++] = (unsigned char)((tmp >> 16) & 0xff);
   1319             calData[ptr++] = (unsigned char)((tmp >> 8) & 0xff);
   1320             calData[ptr++] = (unsigned char)(tmp & 0xff);
   1321             STORECAL_LOG("y_gyro_temp_data[%d][%d] = %f\n",
   1322                          i, j, inv_obj.y_gyro_temp_data[i][j]);
   1323         }
   1324     }
   1325     for (i = 0; i < BINS; i++) {
   1326         for (j = 0; j < PTS_PER_BIN; j++) {
   1327             tmp = (long long)(inv_obj.z_gyro_temp_data[i][j] * 65536.0f);
   1328             if (tmp < 0) {
   1329                 tmp += 4294967296LL;
   1330             }
   1331             calData[ptr++] = (unsigned char)((tmp >> 24) & 0xff);
   1332             calData[ptr++] = (unsigned char)((tmp >> 16) & 0xff);
   1333             calData[ptr++] = (unsigned char)((tmp >> 8) & 0xff);
   1334             calData[ptr++] = (unsigned char)(tmp & 0xff);
   1335             STORECAL_LOG("z_gyro_temp_data[%d][%d] = %f\n",
   1336                          i, j, inv_obj.z_gyro_temp_data[i][j]);
   1337         }
   1338     }
   1339 
   1340     inv_get_array(INV_ACCEL_BIAS, bias);
   1341 
   1342     /* write the accel biases */
   1343     for (i = 0; i < 3; i++) {
   1344         uint32_t t = (uint32_t) bias[i];
   1345         calData[ptr++] = (unsigned char)((t >> 24) & 0xff);
   1346         calData[ptr++] = (unsigned char)((t >> 16) & 0xff);
   1347         calData[ptr++] = (unsigned char)((t >> 8) & 0xff);
   1348         calData[ptr++] = (unsigned char)(t & 0xff);
   1349         STORECAL_LOG("accel_bias[%d] = %ld\n", i, bias[i]);
   1350     }
   1351 
   1352     /* write the compass calibration state */
   1353     calData[ptr++] = (unsigned char)(inv_obj.got_compass_bias);
   1354     STORECAL_LOG("got_compass_bias = %ld\n", inv_obj.got_compass_bias);
   1355     calData[ptr++] = (unsigned char)(inv_obj.got_init_compass_bias);
   1356     STORECAL_LOG("got_init_compass_bias = %d\n", inv_obj.got_init_compass_bias);
   1357     if (inv_obj.compass_state == SF_UNCALIBRATED) {
   1358         calData[ptr++] = SF_UNCALIBRATED;
   1359     } else {
   1360         calData[ptr++] = SF_STARTUP_SETTLE;
   1361     }
   1362     STORECAL_LOG("compass_state = %ld\n", inv_obj.compass_state);
   1363 
   1364     for (i = 0; i < 3; i++) {
   1365         uint32_t t = (uint32_t) inv_obj.compass_bias_error[i];
   1366         calData[ptr++] = (unsigned char)((t >> 24) & 0xff);
   1367         calData[ptr++] = (unsigned char)((t >> 16) & 0xff);
   1368         calData[ptr++] = (unsigned char)((t >> 8) & 0xff);
   1369         calData[ptr++] = (unsigned char)(t & 0xff);
   1370         STORECAL_LOG("compass_bias_error[%d] = %ld\n",
   1371                      i, inv_obj.compass_bias_error[i]);
   1372     }
   1373     for (i = 0; i < 3; i++) {
   1374         uint32_t t = (uint32_t) inv_obj.init_compass_bias[i];
   1375         calData[ptr++] = (unsigned char)((t >> 24) & 0xff);
   1376         calData[ptr++] = (unsigned char)((t >> 16) & 0xff);
   1377         calData[ptr++] = (unsigned char)((t >> 8) & 0xff);
   1378         calData[ptr++] = (unsigned char)(t & 0xff);
   1379         STORECAL_LOG("init_compass_bias[%d] = %ld\n", i,
   1380                      inv_obj.init_compass_bias[i]);
   1381     }
   1382     for (i = 0; i < 3; i++) {
   1383         uint32_t t = (uint32_t) inv_obj.compass_bias[i];
   1384         calData[ptr++] = (unsigned char)((t >> 24) & 0xff);
   1385         calData[ptr++] = (unsigned char)((t >> 16) & 0xff);
   1386         calData[ptr++] = (unsigned char)((t >> 8) & 0xff);
   1387         calData[ptr++] = (unsigned char)(t & 0xff);
   1388         STORECAL_LOG("compass_bias[%d] = %ld\n", i, inv_obj.compass_bias[i]);
   1389     }
   1390     for (i = 0; i < 18; i++) {
   1391         uint32_t t = (uint32_t) inv_obj.compass_peaks[i];
   1392         calData[ptr++] = (unsigned char)((t >> 24) & 0xff);
   1393         calData[ptr++] = (unsigned char)((t >> 16) & 0xff);
   1394         calData[ptr++] = (unsigned char)((t >> 8) & 0xff);
   1395         calData[ptr++] = (unsigned char)(t & 0xff);
   1396         STORECAL_LOG("compass_peaks[%d] = %d\n", i, inv_obj.compass_peaks[i]);
   1397     }
   1398     for (i = 0; i < 3; i++) {
   1399         dToLL.db = inv_obj.compass_bias_v[i];
   1400         calData[ptr++] = (unsigned char)((dToLL.ll >> 56) & 0xff);
   1401         calData[ptr++] = (unsigned char)((dToLL.ll >> 48) & 0xff);
   1402         calData[ptr++] = (unsigned char)((dToLL.ll >> 40) & 0xff);
   1403         calData[ptr++] = (unsigned char)((dToLL.ll >> 32) & 0xff);
   1404         calData[ptr++] = (unsigned char)((dToLL.ll >> 24) & 0xff);
   1405         calData[ptr++] = (unsigned char)((dToLL.ll >> 16) & 0xff);
   1406         calData[ptr++] = (unsigned char)((dToLL.ll >> 8) & 0xff);
   1407         calData[ptr++] = (unsigned char)(dToLL.ll & 0xff);
   1408         STORECAL_LOG("compass_bias_v[%d] = %lf\n", i,
   1409                      inv_obj.compass_bias_v[i]);
   1410     }
   1411     for (i = 0; i < 9; i++) {
   1412         dToLL.db = inv_obj.compass_bias_ptr[i];
   1413         calData[ptr++] = (unsigned char)((dToLL.ll >> 56) & 0xff);
   1414         calData[ptr++] = (unsigned char)((dToLL.ll >> 48) & 0xff);
   1415         calData[ptr++] = (unsigned char)((dToLL.ll >> 40) & 0xff);
   1416         calData[ptr++] = (unsigned char)((dToLL.ll >> 32) & 0xff);
   1417         calData[ptr++] = (unsigned char)((dToLL.ll >> 24) & 0xff);
   1418         calData[ptr++] = (unsigned char)((dToLL.ll >> 16) & 0xff);
   1419         calData[ptr++] = (unsigned char)((dToLL.ll >> 8) & 0xff);
   1420         calData[ptr++] = (unsigned char)(dToLL.ll & 0xff);
   1421         STORECAL_LOG("compass_bias_ptr[%d] = %lf\n", i,
   1422                      inv_obj.compass_bias_ptr[i]);
   1423     }
   1424     for (i = 0; i < 3; i++) {
   1425         uint32_t t = (uint32_t) inv_obj.compass_scale[i];
   1426         calData[ptr++] = (unsigned char)((t >> 24) & 0xff);
   1427         calData[ptr++] = (unsigned char)((t >> 16) & 0xff);
   1428         calData[ptr++] = (unsigned char)((t >> 8) & 0xff);
   1429         calData[ptr++] = (unsigned char)(t & 0xff);
   1430         STORECAL_LOG("compass_scale[%d] = %ld\n", i, inv_obj.compass_scale[i]);
   1431     }
   1432     for (i = 0; i < 6; i++) {
   1433         dToLL.db = inv_obj.compass_prev_xty[i];
   1434         calData[ptr++] = (unsigned char)((dToLL.ll >> 56) & 0xff);
   1435         calData[ptr++] = (unsigned char)((dToLL.ll >> 48) & 0xff);
   1436         calData[ptr++] = (unsigned char)((dToLL.ll >> 40) & 0xff);
   1437         calData[ptr++] = (unsigned char)((dToLL.ll >> 32) & 0xff);
   1438         calData[ptr++] = (unsigned char)((dToLL.ll >> 24) & 0xff);
   1439         calData[ptr++] = (unsigned char)((dToLL.ll >> 16) & 0xff);
   1440         calData[ptr++] = (unsigned char)((dToLL.ll >> 8) & 0xff);
   1441         calData[ptr++] = (unsigned char)(dToLL.ll & 0xff);
   1442         STORECAL_LOG("compass_prev_xty[%d] = %lf\n", i,
   1443                      inv_obj.compass_prev_xty[i]);
   1444     }
   1445     for (i = 0; i < 36; i++) {
   1446         dToLL.db = inv_obj.compass_prev_m[i];
   1447         calData[ptr++] = (unsigned char)((dToLL.ll >> 56) & 0xff);
   1448         calData[ptr++] = (unsigned char)((dToLL.ll >> 48) & 0xff);
   1449         calData[ptr++] = (unsigned char)((dToLL.ll >> 40) & 0xff);
   1450         calData[ptr++] = (unsigned char)((dToLL.ll >> 32) & 0xff);
   1451         calData[ptr++] = (unsigned char)((dToLL.ll >> 24) & 0xff);
   1452         calData[ptr++] = (unsigned char)((dToLL.ll >> 16) & 0xff);
   1453         calData[ptr++] = (unsigned char)((dToLL.ll >> 8) & 0xff);
   1454         calData[ptr++] = (unsigned char)(dToLL.ll & 0xff);
   1455         STORECAL_LOG("compass_prev_m[%d] = %lf\n", i,
   1456                      inv_obj.compass_prev_m[i]);
   1457     }
   1458 
   1459     /* store the compass offsets and validity flag */
   1460     calData[ptr++] = (unsigned char)inv_obj.flags[INV_COMPASS_OFFSET_VALID];
   1461     calData[ptr++] = (unsigned char)inv_obj.compass_offsets[0];
   1462     calData[ptr++] = (unsigned char)inv_obj.compass_offsets[1];
   1463     calData[ptr++] = (unsigned char)inv_obj.compass_offsets[2];
   1464 
   1465     /* store the compass accuracy */
   1466     calData[ptr++] = (unsigned char)(inv_obj.compass_accuracy);
   1467 
   1468     /* add a checksum */
   1469     chk = inv_checksum(calData + INV_CAL_HDR_LEN,
   1470                        length - (INV_CAL_HDR_LEN + INV_CAL_CHK_LEN));
   1471     calData[ptr++] = (unsigned char)((chk >> 24) & 0xff);
   1472     calData[ptr++] = (unsigned char)((chk >> 16) & 0xff);
   1473     calData[ptr++] = (unsigned char)((chk >> 8) & 0xff);
   1474     calData[ptr++] = (unsigned char)(chk & 0xff);
   1475 
   1476     STORECAL_LOG("Exiting inv_store_cal\n");
   1477     return INV_SUCCESS;
   1478 }
   1479 
   1480 /**
   1481  *  @brief  Load a calibration file.
   1482  *
   1483  *  @pre    Must be in INV_STATE_DMP_OPENED state.
   1484  *          inv_dmp_open() or inv_dmp_stop() must have been called.
   1485  *          inv_dmp_start() and inv_dmp_close() must have <b>NOT</b>
   1486  *          been called.
   1487  *
   1488  *  @return 0 or error code.
   1489  */
   1490 inv_error_t inv_load_calibration(void)
   1491 {
   1492     unsigned char *calData;
   1493     inv_error_t result;
   1494     unsigned int length;
   1495 
   1496     if (inv_get_state() < INV_STATE_DMP_OPENED)
   1497         return INV_ERROR_SM_IMPROPER_STATE;
   1498 
   1499     result = inv_serial_get_cal_length(&length);
   1500     if (result == INV_ERROR_FILE_OPEN) {
   1501         MPL_LOGI("Calibration data not loaded\n");
   1502         return INV_SUCCESS;
   1503     }
   1504     if (result || length <= 0) {
   1505         MPL_LOGE("Could not get file calibration length - "
   1506                  "error %d - aborting\n", result);
   1507         return result;
   1508     }
   1509     calData = (unsigned char *)inv_malloc(length);
   1510     if (!calData) {
   1511         MPL_LOGE("Could not allocate buffer of %d bytes - "
   1512                  "aborting\n", length);
   1513         return INV_ERROR_MEMORY_EXAUSTED;
   1514     }
   1515     result = inv_serial_read_cal(calData, length);
   1516     if (result) {
   1517         MPL_LOGE("Could not read the calibration data from file - "
   1518                  "error %d - aborting\n", result);
   1519         goto free_mem_n_exit;
   1520 
   1521     }
   1522     result = inv_load_cal(calData);
   1523     if (result) {
   1524         MPL_LOGE("Could not load the calibration data - "
   1525                  "error %d - aborting\n", result);
   1526         goto free_mem_n_exit;
   1527 
   1528     }
   1529 
   1530 
   1531 
   1532 free_mem_n_exit:
   1533     inv_free(calData);
   1534     return INV_SUCCESS;
   1535 }
   1536 
   1537 /**
   1538  *  @brief  Store runtime calibration data to a file
   1539  *
   1540  *  @pre    Must be in INV_STATE_DMP_OPENED state.
   1541  *          inv_dmp_open() or inv_dmp_stop() must have been called.
   1542  *          inv_dmp_start() and inv_dmp_close() must have <b>NOT</b>
   1543  *          been called.
   1544  *
   1545  *  @return 0 or error code.
   1546  */
   1547 inv_error_t inv_store_calibration(void)
   1548 {
   1549     unsigned char *calData;
   1550     inv_error_t result;
   1551     unsigned int length;
   1552 
   1553     if (inv_get_state() < INV_STATE_DMP_OPENED)
   1554         return INV_ERROR_SM_IMPROPER_STATE;
   1555 
   1556     length = inv_get_cal_length();
   1557     calData = (unsigned char *)inv_malloc(length);
   1558     if (!calData) {
   1559         MPL_LOGE("Could not allocate buffer of %d bytes - "
   1560                  "aborting\n", length);
   1561         return INV_ERROR_MEMORY_EXAUSTED;
   1562     }
   1563     result = inv_store_cal(calData, length);
   1564     if (result) {
   1565         MPL_LOGE("Could not store calibrated data on file - "
   1566                  "error %d - aborting\n", result);
   1567         goto free_mem_n_exit;
   1568 
   1569     }
   1570     result = inv_serial_write_cal(calData, length);
   1571     if (result) {
   1572         MPL_LOGE("Could not write calibration data - " "error %d\n", result);
   1573         goto free_mem_n_exit;
   1574 
   1575     }
   1576 
   1577 
   1578 
   1579 free_mem_n_exit:
   1580     inv_free(calData);
   1581     return INV_SUCCESS;
   1582 }
   1583 
   1584 /**
   1585  *  @}
   1586  */
   1587