1 /******************************************************************************* 2 * Copyright (c) 2012 InvenSense Corporation, All Rights Reserved. 3 ******************************************************************************/ 4 5 /******************************************************************************* 6 * 7 * $Id: main.c 6146 2011-10-04 18:33:51Z jcalizo $ 8 * 9 ******************************************************************************/ 10 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <time.h> 14 15 #include "invensense.h" 16 #include "invensense_adv.h" 17 #include "and_constructor.h" 18 #include "ml_math_func.h" 19 #include "datalogger_outputs.h" 20 21 #include "console_helper.h" 22 23 #include "mlos.h" 24 #include "mlsl.h" 25 26 #include "testsupport.h" 27 28 #include "log.h" 29 #undef MPL_LOG_TAG 30 #define MPL_LOG_TAG "MPL-playback" 31 32 /* 33 Defines & Macros 34 */ 35 #define UNPACK_3ELM_ARRAY(a) (a)[0], (a)[1], (a)[2] 36 #define UNPACK_4ELM_ARRAY(a) UNPACK_3ELM_ARRAY(a), (a)[3] 37 #define COMPONENT_NAME_MAX_LEN (30) 38 #define DEF_NAME(x) (#x) 39 40 #define PRINT_ON_CONSOLE(...) \ 41 if (print_on_screen) \ 42 printf(__VA_ARGS__) 43 #define PRINT_ON_FILE(...) \ 44 if(stream_file) \ 45 fprintf(stream_file, __VA_ARGS__) 46 47 #define PRINT(...) \ 48 PRINT_ON_CONSOLE(__VA_ARGS__); \ 49 PRINT_ON_FILE(__VA_ARGS__) 50 #define PRINT_FLOAT(width, prec, data) \ 51 PRINT_ON_CONSOLE("%+*.*f", \ 52 width, prec, data); \ 53 PRINT_ON_FILE("%+f", data) 54 #define PRINT_INT(width, data) \ 55 PRINT_ON_CONSOLE("%+*d", width, data); \ 56 PRINT_ON_FILE("%+d", data); 57 #define PRINT_LONG(width, data) \ 58 PRINT_ON_CONSOLE("%+*ld", width, data); \ 59 PRINT_ON_FILE("%+ld", data); 60 61 #define PRINT_3ELM_ARRAY_FLOAT(w, p, data) \ 62 PRINT_FLOAT(w, p, data[0]); \ 63 PRINT(", "); \ 64 PRINT_FLOAT(w, p, data[1]); \ 65 PRINT(", "); \ 66 PRINT_FLOAT(w, p, data[2]); \ 67 PRINT(", "); 68 #define PRINT_4ELM_ARRAY_FLOAT(w, p, data) \ 69 PRINT_3ELM_ARRAY_FLOAT(w, p, data); \ 70 PRINT_FLOAT(w, p, data[3]); \ 71 PRINT(", "); 72 73 #define PRINT_3ELM_ARRAY_LONG(w, data) \ 74 PRINT_LONG(w, data[0]); \ 75 PRINT(", "); \ 76 PRINT_LONG(w, data[1]); \ 77 PRINT(", "); \ 78 PRINT_LONG(w, data[2]); \ 79 PRINT(", "); 80 #define PRINT_4ELM_ARRAY_LONG(w, data) \ 81 PRINT_3ELM_ARRAY_LONG(w, data); \ 82 PRINT_LONG(w, data[3]); \ 83 PRINT(", "); 84 85 #define PRINT_3ELM_ARRAY_INT(w, data) \ 86 PRINT_INT(w, data[0]); \ 87 PRINT(", "); \ 88 PRINT_INT(w, data[1]); \ 89 PRINT(", "); \ 90 PRINT_INT(w, data[2]); \ 91 PRINT(", "); 92 #define PRINT_4ELM_ARRAY_INT(w, data) \ 93 PRINT_3ELM_ARRAY_LONG(w, data); \ 94 PRINT_INT(w, data[3]); \ 95 PRINT(", "); 96 97 98 #define CASE_NAME(CODE) \ 99 case CODE: \ 100 return #CODE 101 102 #define CALL_CHECK_N_PRINT(f) { \ 103 MPL_LOGI("\n"); \ 104 MPL_LOGI("################################################\n"); \ 105 MPL_LOGI("# %s\n", #f); \ 106 MPL_LOGI("################################################\n"); \ 107 MPL_LOGI("\n"); \ 108 CALL_N_CHECK(f); \ 109 } 110 111 /* 112 Types 113 */ 114 /* A badly named enum type to track state of user input for tracker menu. */ 115 typedef enum { 116 STATE_SELECT_A_TRACKER, 117 STATE_SET_TRACKER_STATE, /* I'm running out of ideas here. */ 118 STATE_COUNT 119 } user_state_t; 120 121 /* bias trackers. */ 122 typedef enum { 123 BIAS_FROM_NO_MOTION, 124 FAST_NO_MOTION, 125 BIAS_FROM_GRAVITY, 126 BIAS_FROM_TEMPERATURE, 127 BIAS_FROM_LPF, 128 DEAD_ZONE, 129 NUM_TRACKERS 130 } bias_t; 131 132 enum comp_ids { 133 TIME = 0, 134 CALIBRATED_GYROSCOPE, 135 CALIBRATED_ACCELEROMETER, 136 CALIBRATED_COMPASS, 137 RAW_GYROSCOPE, 138 RAW_GYROSCOPE_BODY, 139 RAW_ACCELEROMETER, 140 RAW_COMPASS, 141 QUATERNION_9_AXIS, 142 QUATERNION_6_AXIS, 143 GRAVITY, 144 HEADING, 145 COMPASS_BIAS_ERROR, 146 COMPASS_STATE, 147 TEMPERATURE, 148 TEMP_COMP_SLOPE, 149 LINEAR_ACCELERATION, 150 ROTATION_VECTOR, 151 MOTION_STATE, 152 153 NUM_OF_IDS 154 }; 155 156 struct component_list { 157 char name[COMPONENT_NAME_MAX_LEN]; 158 int order; 159 }; 160 161 /* 162 Globals 163 */ 164 static int print_on_screen = true; 165 static int one_time_print = true; 166 static FILE *stream_file = NULL; 167 static unsigned long sample_count = 0; 168 static int enabled_9x = true; 169 170 signed char g_gyro_orientation[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; 171 signed char g_accel_orientation[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; 172 signed char g_compass_orientation[9] = {-1, 0, 0, 0, 1, 0, 0, 0, -1}; 173 174 #ifdef WIN32 175 static double pc_freq; 176 static __int64 counter_start; 177 #else 178 static inv_time_t counter_start; 179 #endif 180 181 struct component_list components[NUM_OF_IDS]; 182 183 /* 184 Prototypes 185 */ 186 void print_tracker_states(bias_t tracker); 187 188 /* 189 Callbacks 190 */ 191 /*--- motion / no motion callback function ---*/ 192 void check_motion_event(void) 193 { 194 long msg = inv_get_message_level_0(1); 195 if (msg) { 196 if (msg & INV_MSG_MOTION_EVENT) { 197 MPL_LOGI("################################################\n"); 198 MPL_LOGI("## Motion\n"); 199 MPL_LOGI("################################################\n"); 200 } 201 if (msg & INV_MSG_NO_MOTION_EVENT) { 202 MPL_LOGI("################################################\n"); 203 MPL_LOGI("## No Motion\n"); 204 MPL_LOGI("################################################\n"); 205 } 206 } 207 } 208 209 /* number to string coversion */ 210 char *compass_state_name(char* out, int state) 211 { 212 switch(state) { 213 CASE_NAME(SF_NORMAL); 214 CASE_NAME(SF_DISTURBANCE); 215 CASE_NAME(SF_FAST_SETTLE); 216 CASE_NAME(SF_SLOW_SETTLE); 217 CASE_NAME(SF_STARTUP_SETTLE); 218 CASE_NAME(SF_UNCALIBRATED); 219 } 220 221 #define UNKNOWN_ERROR_CODE 1234 222 return ERROR_NAME(UNKNOWN_ERROR_CODE); 223 } 224 225 /* component ID to name convertion */ 226 char *component_name(char *out, int comp_id) 227 { 228 switch (comp_id) { 229 CASE_NAME(TIME); 230 CASE_NAME(CALIBRATED_GYROSCOPE); 231 CASE_NAME(CALIBRATED_ACCELEROMETER); 232 CASE_NAME(CALIBRATED_COMPASS); 233 CASE_NAME(RAW_GYROSCOPE); 234 CASE_NAME(RAW_GYROSCOPE_BODY); 235 CASE_NAME(RAW_ACCELEROMETER); 236 CASE_NAME(RAW_COMPASS); 237 CASE_NAME(QUATERNION_9_AXIS); 238 CASE_NAME(QUATERNION_6_AXIS); 239 CASE_NAME(GRAVITY); 240 CASE_NAME(HEADING); 241 CASE_NAME(COMPASS_BIAS_ERROR); 242 CASE_NAME(COMPASS_STATE); 243 CASE_NAME(TEMPERATURE); 244 CASE_NAME(TEMP_COMP_SLOPE); 245 CASE_NAME(LINEAR_ACCELERATION); 246 CASE_NAME(ROTATION_VECTOR); 247 CASE_NAME(MOTION_STATE); 248 } 249 250 return "UNKNOWN"; 251 } 252 253 254 #ifdef WIN32 255 256 /* 257 Karthik Implementation. 258 http://stackoverflow.com/questions/1739259/how-to-use-queryperformancecounter 259 */ 260 double get_counter(__int64 *counter_start, double *pc_freq) 261 { 262 LARGE_INTEGER li; 263 double x; 264 QueryPerformanceCounter(&li); 265 x = (double) (li.QuadPart - (*counter_start)); 266 x = x / (*pc_freq); 267 return(x); 268 } 269 270 void start_counter(double *pc_freq, __int64 *counter_start) 271 { 272 LARGE_INTEGER li; 273 double x; 274 if(!QueryPerformanceFrequency(&li)) 275 printf("QueryPerformanceFrequency failed!\n"); 276 x = (double)(li.QuadPart); 277 *pc_freq = x / 1000.0; 278 QueryPerformanceCounter(&li); 279 *counter_start = li.QuadPart; 280 } 281 282 #else 283 284 unsigned long get_counter(void) 285 { 286 return (inv_get_tick_count() - counter_start); 287 } 288 289 void start_counter(void) 290 { 291 counter_start = inv_get_tick_count(); 292 } 293 294 #endif 295 296 /* processed data callback */ 297 void fifo_callback(void) 298 { 299 int print_on_screen_saved = print_on_screen; 300 int i; 301 302 /* one_time_print causes the data labels to be printed on screen */ 303 if (one_time_print) { 304 print_on_screen = true; 305 } 306 for (i = 0; i < NUM_OF_IDS; i++) { 307 if (components[TIME].order == i) { 308 if (one_time_print) { 309 PRINT("TIME,"); 310 } else { 311 #ifdef WIN32 312 double time_ms; 313 static int first_value = 0; 314 if(first_value == 0){ 315 first_value = 1; 316 start_counter(&pc_freq, &counter_start); 317 time_ms = 0; 318 } else { 319 time_ms = get_counter(&counter_start, &pc_freq); 320 } 321 PRINT("%6.0f, ", time_ms); 322 #else 323 unsigned long time_ms; 324 static int first_value = 0; 325 if(first_value == 0){ 326 first_value = 1; 327 start_counter(); 328 time_ms = 0; 329 } else { 330 time_ms = get_counter(); 331 } 332 PRINT("%6ld, ", time_ms); 333 #endif 334 } 335 } else if (components[CALIBRATED_GYROSCOPE].order == i) { 336 if (one_time_print) { 337 PRINT("CALIBRATED_GYROSCOPE_X," 338 "CALIBRATED_GYROSCOPE_Y," 339 "CALIBRATED_GYROSCOPE_Z,"); 340 /* 341 PRINT("CALIBRATED_GYROSCOPE_X_AVERAGE," 342 "CALIBRATED_GYROSCOPE_Y_AVERAGE," 343 "CALIBRATED_GYROSCOPE_Z_AVERAGE,"); 344 */ 345 } else { 346 /* 347 #define window 20 348 static int cnt = 0; 349 static int valid = 0; 350 static float gyro_keep[window][3]; 351 int kk, jj; 352 float avg[3]; 353 */ 354 float gyro[3]; 355 inv_get_gyro_float(gyro); 356 PRINT_3ELM_ARRAY_FLOAT(10, 5, gyro); 357 PRINT(" "); 358 /* 359 memcpy(gyro_keep[cnt], gyro, sizeof(float) * 3); 360 cnt= (cnt + 1) % window; 361 if (cnt == window - 1) 362 valid = 1; 363 if (valid) { 364 memset(avg, 0, sizeof(float) * 3); 365 jj = (cnt + 1) % window; 366 for (kk = 0; kk < window; kk++) { 367 avg[0] += gyro_keep[jj][0] / window; 368 avg[1] += gyro_keep[jj][1] / window; 369 avg[2] += gyro_keep[jj][2] / window; 370 jj = (jj + 1) % window; 371 } 372 PRINT("%+f, %+f, %+f, ", 373 UNPACK_3ELM_ARRAY(avg)); 374 PRINT_3ELM_ARRAY_FLOAT(10, 5, avg); 375 PRINT(" "); 376 } 377 */ 378 } 379 } else if (components[CALIBRATED_ACCELEROMETER].order == i) { 380 if (one_time_print) { 381 PRINT("CALIBRATED_ACCELEROMETER_X," 382 "CALIBRATED_ACCELEROMETER_Y," 383 "CALIBRATED_ACCELEROMETER_Z,"); 384 } else { 385 float accel[3]; 386 inv_get_accel_float(accel); 387 PRINT_3ELM_ARRAY_FLOAT(10, 5, accel); 388 PRINT(" "); 389 } 390 } else if (components[CALIBRATED_COMPASS].order == i) { 391 if (one_time_print) { 392 PRINT("CALIBRATED_COMPASS_X," 393 "CALIBRATED_COMPASS_Y," 394 "CALIBRATED_COMPASS_Z,"); 395 } else { 396 long lcompass[3]; 397 float compass[3]; 398 inv_get_compass_set(lcompass, 0, 0); 399 compass[0] = inv_q16_to_float(lcompass[0]); 400 compass[1] = inv_q16_to_float(lcompass[1]); 401 compass[2] = inv_q16_to_float(lcompass[2]); 402 PRINT_3ELM_ARRAY_FLOAT(10, 5, compass); 403 PRINT(" "); 404 } 405 } else if (components[RAW_GYROSCOPE].order == i) { 406 if (one_time_print) { 407 PRINT("RAW_GYROSCOPE_X," 408 "RAW_GYROSCOPE_Y," 409 "RAW_GYROSCOPE_Z,"); 410 } else { 411 short raw[3]; 412 inv_get_sensor_type_gyro_raw_short(raw, NULL); 413 PRINT_3ELM_ARRAY_INT(6, raw); 414 PRINT(" "); 415 } 416 } else if (components[RAW_GYROSCOPE_BODY].order == i) { 417 if (one_time_print) { 418 PRINT("RAW_GYROSCOPE_BODY_X," 419 "RAW_GYROSCOPE_BODY_Y," 420 "RAW_GYROSCOPE_BODY_Z,"); 421 } else { 422 float raw_body[3]; 423 inv_get_sensor_type_gyro_raw_body_float(raw_body, NULL); 424 PRINT_3ELM_ARRAY_FLOAT(10, 5, raw_body); 425 PRINT(" "); 426 } 427 } else if (components[RAW_ACCELEROMETER].order == i) { 428 if (one_time_print) { 429 PRINT("RAW_ACCELEROMETER_X," 430 "RAW_ACCELEROMETER_Y," 431 "RAW_ACCELEROMETER_Z,"); 432 } else { 433 short raw[3]; 434 inv_get_sensor_type_accel_raw_short(raw, NULL); 435 PRINT_3ELM_ARRAY_INT(6, raw); 436 PRINT(" "); 437 } 438 } else if (components[RAW_COMPASS].order == i) { 439 if (one_time_print) { 440 PRINT("RAW_COMPASS_X," 441 "RAW_COMPASS_Y," 442 "RAW_COMPASS_Z,"); 443 } else { 444 short raw[3]; 445 inv_get_sensor_type_compass_raw_short(raw, NULL); 446 PRINT_3ELM_ARRAY_INT(6, raw); 447 PRINT(" "); 448 } 449 } else if (components[QUATERNION_9_AXIS].order == i) { 450 if (one_time_print) { 451 PRINT("QUATERNION_9_AXIS_X," 452 "QUATERNION_9_AXIS_Y," 453 "QUATERNION_9_AXIS_Z," 454 "QUATERNION_9_AXIS_w,"); 455 } else { 456 float quat[4]; 457 inv_get_quaternion_float(quat); 458 PRINT_4ELM_ARRAY_FLOAT(10, 5, quat); 459 PRINT(" "); 460 } 461 } else if (components[QUATERNION_6_AXIS].order == i) { 462 if (one_time_print) { 463 PRINT("QUATERNION_6_AXIS_X," 464 "QUATERNION_6_AXIS_Y," 465 "QUATERNION_6_AXIS_Z," 466 "QUATERNION_6_AXIS_w,"); 467 } else { 468 float quat[4]; 469 long temp[4]; 470 int j; 471 inv_time_t timestamp; 472 inv_get_6axis_quaternion(temp, ×tamp); 473 for (j = 0; j < 4; j++) 474 quat[j] = (float)temp[j] / (1 << 30); 475 PRINT_4ELM_ARRAY_FLOAT(10, 5, quat); 476 PRINT(" "); 477 } 478 } else if (components[HEADING].order == i) { 479 if (one_time_print) { 480 PRINT("HEADING,"); 481 } else { 482 float heading[1]; 483 inv_get_sensor_type_compass_float(heading, NULL, NULL, 484 NULL, NULL); 485 PRINT_FLOAT(10, 5, heading[0]); 486 PRINT(", "); 487 } 488 } else if (components[GRAVITY].order == i) { 489 if (one_time_print) { 490 PRINT("GRAVITY_X," 491 "GRAVITY_Y," 492 "GRAVITY_Z,"); 493 } else { 494 float gravity[3]; 495 inv_get_sensor_type_gravity_float(gravity, NULL, NULL); 496 PRINT_3ELM_ARRAY_FLOAT(10, 5, gravity); 497 PRINT(" "); 498 } 499 } else if (components[COMPASS_STATE].order == i) { 500 if (one_time_print) { 501 PRINT("COMPASS_STATE," 502 "GOT_COARSE_HEADING,"); 503 } else { 504 PRINT_INT(1, inv_get_compass_state()); 505 PRINT(", "); 506 PRINT_INT(1, inv_got_compass_bias()); 507 PRINT(", "); 508 } 509 } else if (components[COMPASS_BIAS_ERROR].order == i) { 510 if (one_time_print) { 511 PRINT("COMPASS_BIAS_ERROR_X," 512 "COMPASS_BIAS_ERROR_Y," 513 "COMPASS_BIAS_ERROR_Z,"); 514 } else { 515 long mbe[3]; 516 inv_get_compass_bias_error(mbe); 517 PRINT_3ELM_ARRAY_LONG(6, mbe); 518 } 519 } else if (components[TEMPERATURE].order == i) { 520 if (one_time_print) { 521 PRINT("TEMPERATURE,"); 522 } else { 523 float temp; 524 inv_get_sensor_type_temperature_float(&temp, NULL); 525 PRINT_FLOAT(8, 4, temp); 526 PRINT(", "); 527 } 528 } else if (components[TEMP_COMP_SLOPE].order == i) { 529 if (one_time_print) { 530 PRINT("TEMP_COMP_SLOPE_X," 531 "TEMP_COMP_SLOPE_Y," 532 "TEMP_COMP_SLOPE_Z,"); 533 } else { 534 long temp_slope[3]; 535 float temp_slope_f[3]; 536 (void)inv_get_gyro_ts(temp_slope); 537 temp_slope_f[0] = inv_q16_to_float(temp_slope[0]); 538 temp_slope_f[1] = inv_q16_to_float(temp_slope[1]); 539 temp_slope_f[2] = inv_q16_to_float(temp_slope[2]); 540 PRINT_3ELM_ARRAY_FLOAT(10, 5, temp_slope_f); 541 PRINT(" "); 542 } 543 } else if (components[LINEAR_ACCELERATION].order == i) { 544 if (one_time_print) { 545 PRINT("LINEAR_ACCELERATION_X," 546 "LINEAR_ACCELERATION_Y," 547 "LINEAR_ACCELERATION_Z,"); 548 } else { 549 float lin_acc[3]; 550 inv_get_linear_accel_float(lin_acc); 551 PRINT_3ELM_ARRAY_FLOAT(10, 5, lin_acc); 552 PRINT(" "); 553 } 554 } else if (components[ROTATION_VECTOR].order == i) { 555 if (one_time_print) { 556 PRINT("ROTATION_VECTOR_X," 557 "ROTATION_VECTOR_Y," 558 "ROTATION_VECTOR_Z,"); 559 } else { 560 float rot_vec[3]; 561 inv_get_sensor_type_rotation_vector_float(rot_vec, NULL, NULL); 562 PRINT_3ELM_ARRAY_FLOAT(10, 5, rot_vec); 563 PRINT(" "); 564 } 565 } else if (components[MOTION_STATE].order == i) { 566 if (one_time_print) { 567 PRINT("MOTION_STATE,"); 568 } else { 569 unsigned int counter; 570 PRINT_INT(1, inv_get_motion_state(&counter)); 571 PRINT(", "); 572 } 573 } else { 574 ; 575 } 576 } 577 PRINT("\n"); 578 579 if (one_time_print) { 580 one_time_print = false; 581 print_on_screen = print_on_screen_saved; 582 } 583 sample_count++; 584 } 585 586 void print_help(char *exename) 587 { 588 printf( 589 "\n" 590 "Usage:\n" 591 "\t%s [options]\n" 592 "\n" 593 "Options:\n" 594 " [-h|--help] = shows this help\n" 595 " [-o|--output PREFIX] = to dump data on csv file whose file\n" 596 " prefix is specified by the parameter,\n" 597 " e.g. '<PREFIX>-<timestamp>.csv'\n" 598 " [-i|--input NAME] = to read the provided playback.bin file\n" 599 " [-c|--comp C] = enable the following components in the\n" 600 " given order:\n" 601 " t = TIME\n" 602 " T = TEMPERATURE,\n" 603 " s = TEMP_COMP_SLOPE,\n" 604 " G = CALIBRATED_GYROSCOPE,\n" 605 " A = CALIBRATED_ACCELEROMETER,\n" 606 " C = CALIBRATED_COMPASS,\n" 607 " g = RAW_GYROSCOPE,\n" 608 " b = RAW_GYROSCOPE_BODY,\n" 609 " a = RAW_ACCELEROMETER,\n" 610 " c = RAW_COMPASS,\n" 611 " Q = QUATERNION_9_AXIS,\n" 612 " 6 = QUATERNION_6_AXIS,\n" 613 " V = GRAVITY,\n" 614 " L = LINEAR_ACCELERATION,\n" 615 " R = ROTATION_VECTOR,\n" 616 " H = HEADING,\n" 617 " E = COMPASS_BIAS_ERROR,\n" 618 " S = COMPASS_STATE,\n" 619 " M = MOTION_STATE.\n" 620 "\n" 621 "Note on compass state values:\n" 622 " SF_NORMAL = 0\n" 623 " SF_DISTURBANCE = 1\n" 624 " SF_FAST_SETTLE = 2\n" 625 " SF_SLOW_SETTLE = 3\n" 626 " SF_STARTUP_SETTLE = 4\n" 627 " SF_UNCALIBRATED = 5\n" 628 "\n", 629 exename); 630 } 631 632 char *output_filename_datetimestamp(char *out) 633 { 634 time_t t; 635 struct tm *now; 636 t = time(NULL); 637 now = localtime(&t); 638 639 sprintf(out, 640 "%02d%02d%02d_%02d%02d%02d.csv", 641 now->tm_year - 100, now->tm_mon + 1, now->tm_mday, 642 now->tm_hour, now->tm_min, now->tm_sec); 643 return out; 644 } 645 646 int components_parser(char pname[], char requested[], int length) 647 { 648 int j; 649 650 /* forcibly disable all */ 651 for (j = 0; j < NUM_OF_IDS; j++) 652 components[j].order = -1; 653 654 /* parse each character one a time */ 655 for (j = 0; j < length; j++) { 656 switch (requested[j]) { 657 case 'T': 658 components[TEMPERATURE].order = j; 659 break; 660 case 'G': 661 components[CALIBRATED_GYROSCOPE].order = j; 662 break; 663 case 'A': 664 components[CALIBRATED_ACCELEROMETER].order = j; 665 break; 666 case 'g': 667 components[RAW_GYROSCOPE].order = j; 668 break; 669 case 'b': 670 components[RAW_GYROSCOPE_BODY].order = j; 671 break; 672 case 'a': 673 components[RAW_ACCELEROMETER].order = j; 674 break; 675 case 'Q': 676 components[QUATERNION_9_AXIS].order = j; 677 break; 678 case '6': 679 components[QUATERNION_6_AXIS].order = j; 680 break; 681 case 'V': 682 components[GRAVITY].order = j; 683 break; 684 case 'L': 685 components[LINEAR_ACCELERATION].order = j; 686 break; 687 case 'R': 688 components[ROTATION_VECTOR].order = j; 689 break; 690 691 /* these components don't need to be enabled */ 692 case 't': 693 components[TIME].order = j; 694 break; 695 case 'C': 696 components[CALIBRATED_COMPASS].order = j; 697 break; 698 case 'c': 699 components[RAW_COMPASS].order = j; 700 break; 701 case 'H': 702 components[HEADING].order = j; 703 break; 704 case 'E': 705 components[COMPASS_BIAS_ERROR].order = j; 706 break; 707 case 'S': 708 components[COMPASS_STATE].order = j; 709 break; 710 case 'M': 711 components[MOTION_STATE].order = j; 712 break; 713 714 default: 715 MPL_LOGI("Error : unrecognized component '%c'\n", 716 requested[j]); 717 print_help(pname); 718 return 1; 719 break; 720 } 721 } 722 return 0; 723 } 724 725 int main(int argc, char *argv[]) 726 { 727 #ifndef INV_PLAYBACK_DBG 728 MPL_LOGI("Error : this application was not compiled with the " 729 "INV_PLAYBACK_DBG define and cannot work.\n"); 730 MPL_LOGI(" Recompile the libmllite libraries with #define " 731 "INV_PLAYBACK_DBG uncommented\n"); 732 MPL_LOGI(" in 'software/core/mllite/data_builder.h'.\n"); 733 return INV_ERROR; 734 #endif 735 736 inv_time_t start_time; 737 double total_time; 738 char req_component_list[50] = "tQGACH"; 739 char input_filename[101] = "/data/playback.bin"; 740 int i = 0; 741 char *ver_str; 742 /* flags */ 743 int use_nm_detection = true; 744 745 /* make sure there is no buffering of the print messages */ 746 setvbuf(stdout, NULL, _IONBF, 0); 747 748 /* forcibly disable all and populate the names */ 749 for (i = 0; i < NUM_OF_IDS; i++) { 750 char str_tmp[COMPONENT_NAME_MAX_LEN]; 751 strcpy(components[i].name, component_name(str_tmp, i)); 752 components[i].order = -1; 753 } 754 755 CALL_N_CHECK( inv_get_version(&ver_str) ); 756 MPL_LOGI("\n"); 757 MPL_LOGI("%s\n", ver_str); 758 MPL_LOGI("\n"); 759 760 for (i = 1; i < argc; i++) { 761 if(strcmp(argv[i], "-h") == 0 762 || strcmp(argv[i], "--help") == 0) { 763 print_help(argv[0]); 764 return INV_SUCCESS; 765 766 } else if(strcmp(argv[i], "-o") == 0 767 || strcmp(argv[i], "--output") == 0) { 768 char output_filename[200]; 769 char end[50] = ""; 770 i++; 771 772 snprintf(output_filename, sizeof(output_filename), "%s-%s", 773 argv[i], output_filename_datetimestamp(end)); 774 stream_file = fopen(output_filename, "w+"); 775 if (!stream_file) { 776 printf("Unable to open file '%s'\n", output_filename); 777 return INV_ERROR; 778 } 779 MPL_LOGI("-- Output on file '%s'\n", output_filename); 780 781 } else if(strcmp(argv[i], "-i") == 0 782 || strcmp(argv[i], "--input") == 0) { 783 i++; 784 strncpy(input_filename, argv[i], sizeof(input_filename)); 785 MPL_LOGI("-- Playing back file '%s'\n", input_filename); 786 787 } else if(strcmp(argv[i], "-n") == 0 788 || strcmp(argv[i], "--nm") == 0) { 789 i++; 790 if (!strcmp(argv[i], "none")) { 791 use_nm_detection = 0; 792 } else if (!strcmp(argv[i], "regular")) { 793 use_nm_detection = 1; 794 } else if (!strcmp(argv[i], "fast")) { 795 use_nm_detection = 2; 796 } else { 797 MPL_LOGI("Error : unrecognized no-motion type '%s'\n", 798 argv[i]); 799 return INV_ERROR_INVALID_PARAMETER; 800 } 801 MPL_LOGI("-- No motion algorithm : '%s', %d\n", 802 argv[i], use_nm_detection); 803 804 } else if(strcmp(argv[i], "-9") == 0 805 || strcmp(argv[i], "--nine") == 0) { 806 MPL_LOGI("-- using 9 axis sensor fusion by default\n"); 807 enabled_9x = true; 808 809 } else if(strcmp(argv[i], "-c") == 0 810 || strcmp(argv[i], "--comp") == 0) { 811 i++; 812 strcpy(req_component_list, argv[i]); 813 814 } else { 815 MPL_LOGI("Unrecognized command-line parameter '%s'\n", argv[i]); 816 return INV_ERROR_INVALID_PARAMETER; 817 } 818 } 819 820 CALL_CHECK_N_RETURN_ERROR( 821 components_parser( 822 argv[0], 823 req_component_list, strlen(req_component_list))); 824 825 /* set up callbacks */ 826 CALL_N_CHECK(inv_set_fifo_processed_callback(fifo_callback)); 827 828 /* algorithm init */ 829 CALL_N_CHECK(inv_enable_quaternion()); 830 if (use_nm_detection == 1) { 831 CALL_N_CHECK(inv_enable_motion_no_motion()); 832 } else if (use_nm_detection == 2) { 833 CALL_N_CHECK(inv_enable_fast_nomot()); 834 } 835 CALL_N_CHECK(inv_enable_gyro_tc()); 836 CALL_N_CHECK(inv_enable_in_use_auto_calibration()); 837 CALL_N_CHECK(inv_enable_no_gyro_fusion()); 838 CALL_N_CHECK(inv_enable_results_holder()); 839 if (enabled_9x) { 840 CALL_N_CHECK(inv_enable_heading_from_gyro()); 841 CALL_N_CHECK(inv_enable_compass_bias_w_gyro()); 842 CALL_N_CHECK(inv_enable_vector_compass_cal()); 843 CALL_N_CHECK(inv_enable_9x_sensor_fusion()); 844 } 845 846 CALL_CHECK_N_RETURN_ERROR(inv_enable_datalogger_outputs()); 847 CALL_CHECK_N_RETURN_ERROR(inv_constructor_start()); 848 849 /* load persistent data */ 850 { 851 FILE *fc = fopen("invcal.bin", "rb"); 852 if (fc != NULL) { 853 size_t sz, rd; 854 inv_error_t result = 0; 855 // Read amount of memory we need to hold data 856 rd = fread(&sz, sizeof(size_t), 1, fc); 857 if (rd == sizeof(size_t)) { 858 unsigned char *cal_data = (unsigned char *)malloc(sizeof(sz)); 859 unsigned char *cal_ptr; 860 cal_ptr = cal_data; 861 *(size_t *)cal_ptr = sz; 862 cal_ptr += sizeof(sz); 863 /* read rest of the file */ 864 fread(cal_ptr, sz - sizeof(size_t), 1, fc); 865 //result = inv_load_mpl_states(cal_data, sz); 866 if (result) { 867 MPL_LOGE("Cal Load error\n"); 868 } 869 MPL_LOGI("inv_load_mpl_states()\n"); 870 free(cal_data); 871 } else { 872 MPL_LOGE("Cal Load error with size read\n"); 873 } 874 fclose(fc); 875 } 876 } 877 878 sample_count = 0; 879 start_time = inv_get_tick_count(); 880 881 /* playback data that was recorded */ 882 inv_set_playback_filename(input_filename, strlen(input_filename) + 1); 883 inv_set_debug_mode(RD_PLAYBACK); 884 CALL_N_CHECK(inv_playback()); 885 886 total_time = (1.0 * inv_get_tick_count() - start_time) / 1000; 887 if (total_time > 0) { 888 MPL_LOGI("\nPlayed back %ld samples in %.2f s (%.1f Hz)\n", 889 sample_count, total_time , 1.0 * sample_count / total_time); 890 } 891 892 if (stream_file) 893 fclose(stream_file); 894 895 return INV_SUCCESS; 896 } 897 898 899