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 * $Id: ml.h 5653 2011-06-16 21:06:55Z nroyer $ 21 * 22 *****************************************************************************/ 23 24/** 25 * @defgroup ML 26 * @brief The Motion Library processes gyroscopes and accelerometers to 27 * provide a physical model of the movement of the sensors. 28 * The results of this processing may be used to control objects 29 * within a user interface environment, detect gestures, track 3D 30 * movement for gaming applications, and analyze the blur created 31 * due to hand movement while taking a picture. 32 * 33 * @{ 34 * @file ml.h 35 * @brief Header file for the Motion Library. 36**/ 37 38#ifndef INV_H 39#define INV_H 40 41#ifdef __cplusplus 42extern "C" { 43#endif 44 45#include "mltypes.h" 46#include "mldmp.h" 47#include "mlsl.h" 48#include "mpu.h" 49#ifdef INV_INCLUDE_LEGACY_HEADERS 50#include "ml_legacy.h" 51#endif 52 53/* ------------ */ 54/* - Defines. - */ 55/* ------------ */ 56 57/* - Module defines. - */ 58 59/*************************************************************************/ 60/* Motion Library Vesion */ 61/*************************************************************************/ 62 63#define INV_VERSION_MAJOR 4 64#define INV_VERSION_MINOR 0 65#define INV_VERSION_SUB_MINOR 0 66 67#define INV_VERSION_MAJOR_STR "4" 68#define INV_VERSION_MINOR_STR "0" 69#define INV_VERSION_SUB_MINOR_STR "0" 70 71#define INV_VERSION_NONE "" 72#define INV_VERSION_PROTOTYPE "ProtoA " 73#define INV_VERSION_ENGINEERING "EngA " 74#define INV_VERSION_PRE_ALPHA "Pre-Alpha " 75#define INV_VERSION_ALPHA "Alpha " 76#define INV_VERSION_BETA "Beta " 77#define INV_VERSION_PRODUCTION "Production " 78 79#ifndef INV_VERSION_TYPE 80#define INV_VERSION_TYPE INV_VERSION_NONE 81#endif 82 83#define INV_VERSION "InvenSense MPL" " " \ 84 "v" INV_VERSION_MAJOR_STR "." INV_VERSION_MINOR_STR "." INV_VERSION_SUB_MINOR_STR " " \ 85 INV_VERSION_TYPE \ 86 __DATE__ " " __TIME__ 87 88/*************************************************************************/ 89/* Motion processing engines */ 90/*************************************************************************/ 91#define INV_MOTION_DETECT (0x0004) 92#define INV_BIAS_UPDATE (0x0008) 93#define INV_GESTURE (0x0020) 94#define INV_CONTROL (0x0040) 95#define INV_ORIENTATION (0x0100) 96#define INV_PEDOMETER (0x0200) 97#define INV_BASIC (INV_MOTION_DETECT | INV_BIAS_UPDATE) 98 99/*************************************************************************/ 100/* Data Source - Obsolete */ 101/*************************************************************************/ 102#define INV_DATA_FIFO (0x1) 103#define INV_DATA_POLL (0x2) 104 105/*************************************************************************/ 106/* Interrupt Source */ 107/*************************************************************************/ 108#define INV_INT_MOTION (0x01) 109#define INV_INT_FIFO (0x02) 110#define INV_INT_TAP (0x04) 111#define INV_INT_ORIENTATION (0x08) 112#define INV_INT_SHAKE_PITCH (0x10) 113#define INV_INT_SHAKE_ROLL (0x20) 114#define INV_INT_SHAKE_YAW (0x40) 115 116/*************************************************************************/ 117/* Bias update functions */ 118/*************************************************************************/ 119#define INV_BIAS_FROM_NO_MOTION 0x0001 120#define INV_BIAS_FROM_GRAVITY 0x0002 121#define INV_BIAS_FROM_TEMPERATURE 0x0004 122#define INV_BIAS_FROM_LPF 0x0008 123#define INV_MAG_BIAS_FROM_MOTION 0x0010 124#define INV_MAG_BIAS_FROM_GYRO 0x0020 125#define INV_LEARN_BIAS_FROM_TEMPERATURE 0x0040 126#define INV_AUTO_RESET_MAG_BIAS 0x0080 127#define INV_REJECT_MAG_DISTURBANCE 0x0100 128#define INV_PROGRESSIVE_NO_MOTION 0x0200 129#define INV_BIAS_FROM_FAST_NO_MOTION 0x0400 130 131/*************************************************************************/ 132/* Euler angles and axis names */ 133/*************************************************************************/ 134#define INV_X_AXIS (0x01) 135#define INV_Y_AXIS (0x02) 136#define INV_Z_AXIS (0x04) 137 138#define INV_PITCH (INV_X_AXIS) 139#define INV_ROLL (INV_Y_AXIS) 140#define INV_YAW (INV_Z_AXIS) 141 142/*************************************************************************/ 143/* Sensor types */ 144/*************************************************************************/ 145#define INV_GYROS 0x0001 146#define INV_ACCELS 0x0002 147 148/*************************************************************************/ 149/* Motion arrays */ 150/*************************************************************************/ 151#define INV_ROTATION_MATRIX 0x0003 152#define INV_QUATERNION 0x0004 153#define INV_EULER_ANGLES 0x0005 154#define INV_LINEAR_ACCELERATION 0x0006 155#define INV_LINEAR_ACCELERATION_WORLD 0x0007 156#define INV_GRAVITY 0x0008 157#define INV_ANGULAR_VELOCITY 0x0009 158 159#define INV_GYRO_CALIBRATION_MATRIX 0x000B 160#define INV_ACCEL_CALIBRATION_MATRIX 0x000C 161#define INV_GYRO_BIAS 0x000D 162#define INV_ACCEL_BIAS 0x000E 163#define INV_GYRO_TEMP_SLOPE 0x000F 164 165#define INV_RAW_DATA 0x0011 166#define INV_DMP_TAP 0x0012 167#define INV_DMP_TAP2 0x0021 168 169#define INV_EULER_ANGLES_X 0x0013 170#define INV_EULER_ANGLES_Y 0x0014 171#define INV_EULER_ANGLES_Z 0x0015 172 173#define INV_BIAS_UNCERTAINTY 0x0016 174#define INV_DMP_PACKET_NUMBER 0x0017 175#define INV_FOOTER 0x0018 176 177#define INV_CONTROL_DATA 0x0019 178 179#define INV_MAGNETOMETER 0x001A 180#define INV_PEDLBS 0x001B 181#define INV_MAG_RAW_DATA 0x001C 182#define INV_MAG_CALIBRATION_MATRIX 0x001D 183#define INV_MAG_BIAS 0x001E 184#define INV_HEADING 0x001F 185 186#define INV_MAG_BIAS_ERROR 0x0020 187 188#define INV_PRESSURE 0x0021 189#define INV_LOCAL_FIELD 0x0022 190#define INV_MAG_SCALE 0x0023 191 192#define INV_RELATIVE_QUATERNION 0x0024 193 194#define SET_QUATERNION 0x0001 195#define SET_GYROS 0x0002 196#define SET_LINEAR_ACCELERATION 0x0004 197#define SET_GRAVITY 0x0008 198#define SET_ACCELS 0x0010 199#define SET_TAP 0x0020 200#define SET_PEDLBS 0x0040 201#define SET_LINEAR_ACCELERATION_WORLD 0x0080 202#define SET_CONTROL 0x0100 203#define SET_PACKET_NUMBER 0x4000 204#define SET_FOOTER 0x8000 205 206/*************************************************************************/ 207/* Integral reset options */ 208/*************************************************************************/ 209#define INV_NO_RESET 0x0000 210#define INV_RESET 0x0001 211 212/*************************************************************************/ 213/* Motion states */ 214/*************************************************************************/ 215#define INV_MOTION 0x0001 216#define INV_NO_MOTION 0x0002 217 218/*************************************************************************/ 219/* Orientation and Gesture states */ 220/*************************************************************************/ 221#define INV_STATE_IDLE (0) 222#define INV_STATE_RUNNING (1) 223 224/*************************************************************************/ 225/* Gyroscope Temperature Compensation bins */ 226/*************************************************************************/ 227#define BINS (25) 228#define PTS_PER_BIN (5) 229#define MIN_TEMP (-40) 230#define MAX_TEMP (+85) 231#define TEMP_PER_BIN ((MAX_TEMP - MIN_TEMP) / BINS) 232 233/*************************************************************************/ 234/* Flags */ 235/*************************************************************************/ 236#define INV_RAW_DATA_READY 0x0001 237#define INV_PROCESSED_DATA_READY 0x0002 238 239#define INV_GOT_GESTURE 0x0004 240 241#define INV_MOTION_STATE_CHANGE 0x0006 242#define INV_COMPASS_OFFSET_VALID 0x0007 243 244/*************************************************************************/ 245/* General */ 246/*************************************************************************/ 247#define INV_NONE (0x0000) 248#define INV_INVALID_FIFO_RATE (0xFFFF) 249 250/*************************************************************************/ 251/* ML Params Structure Default Values */ 252/*************************************************************************/ 253#define INV_BIAS_UPDATE_FUNC_DEFAULT (INV_BIAS_FROM_NO_MOTION | INV_BIAS_FROM_GRAVITY) 254#define INV_ORIENTATION_MASK_DEFAULT 0x3f 255#define INV_PROCESSED_DATA_CALLBACK_DEFAULT 0 256#define INV_ORIENTATION_CALLBACK_DEFAULT 0 257#define INV_MOTION_CALLBACK_DEFAULT 0 258 259/* ------------ */ 260/* - Defines. - */ 261/* ------------ */ 262/* Priority for various features */ 263#define INV_PRIORITY_BUS_ACCEL 100 264#define INV_PRIORITY_EXTERNAL_SLAVE_MAG 110 265#define INV_PRIORITY_FAST_NO_MOTION 120 266#define INV_PRIORITY_BIAS_NO_MOTION 125 267#define INV_PRIORITY_SET_GYRO_BIASES 150 268#define INV_PRIORITY_TEMP_COMP 175 269#define INV_PRIORITY_CONTROL 200 270#define INV_PRIORITY_EIS 300 271#define INV_PRIORITY_ORIENTATION 400 272#define INV_PRIORITY_PEDOMETER_FULLPOWER 500 273#define INV_PRIORITY_NAVIGATION_PEDOMETER 600 274#define INV_PRIORITY_GESTURE 700 275#define INV_PRIORITY_GLYPH 800 276 277#define MAX_INTERRUPT_PROCESSES 5 278/* Number of quantized accel samples */ 279#define INV_MAX_NUM_ACCEL_SAMPLES (8) 280 281#define PRECISION 10000.f 282#define RANGE_FLOAT_TO_FIXEDPOINT(range, x) { \ 283 range.mantissa = (long)x; \ 284 range.fraction = (long)((float)(x-(long)x)*PRECISION); \ 285} 286#define RANGE_FIXEDPOINT_TO_FLOAT(range, x) { \ 287 x = (float)(range.mantissa); \ 288 x += ((float)range.fraction/PRECISION); \ 289} 290 291 /* --------------- */ 292 /* - Structures. - */ 293 /* --------------- */ 294 295struct inv_obj_t { 296 //Calibration parameters 297 /* Raw sensor orientation */ 298 long gyro_bias[3]; 299 long accel_bias[3]; 300 long compass_bias[3]; 301 302 /* Cached values after orietnation is applied */ 303 long scaled_gyro_bias[3]; 304 long scaled_accel_bias[3]; 305 long scaled_compass_bias[3]; 306 307 long compass_scale[3]; 308 long compass_test_bias[3]; 309 long compass_test_scale[3]; 310 long compass_asa[3]; 311 long compass_offsets[3]; 312 313 long compass_bias_error[3]; 314 315 long got_no_motion_bias; 316 long got_compass_bias; 317 long compass_state; 318 long large_field; 319 long acc_state; 320 321 long factory_temp_comp; 322 long got_coarse_heading; 323 long gyro_temp_bias[3]; 324 long prog_no_motion_bias[3]; 325 326 long accel_cal[9]; 327 // Deprecated, used gyro_orient 328 long gyro_cal[GYRO_NUM_AXES * GYRO_NUM_AXES]; 329 long gyro_orient[GYRO_NUM_AXES * GYRO_NUM_AXES]; 330 long accel_sens; 331 long compass_cal[9]; 332 long gyro_sens; 333 long gyro_sf; 334 long temp_slope[GYRO_NUM_AXES]; 335 long compass_sens; 336 long temp_offset[GYRO_NUM_AXES]; 337 338 int cal_loaded_flag; 339 340 /* temperature compensation */ 341 float x_gyro_coef[3]; 342 float y_gyro_coef[3]; 343 float z_gyro_coef[3]; 344 float x_gyro_temp_data[BINS][PTS_PER_BIN]; 345 float y_gyro_temp_data[BINS][PTS_PER_BIN]; 346 float z_gyro_temp_data[BINS][PTS_PER_BIN]; 347 float temp_data[BINS][PTS_PER_BIN]; 348 int temp_ptrs[BINS]; 349 long temp_valid_data[BINS]; 350 351 long compass_correction[4]; 352 long compass_correction_relative[4]; 353 long compass_disturb_correction[4]; 354 long compass_correction_offset[4]; 355 long relative_quat[4]; 356 long local_field[3]; 357 long new_local_field; 358 long sync_grav_body[3]; 359 int gyro_bias_err; 360 361 double compass_bias_ptr[9]; 362 double compass_bias_v[3]; 363 double compass_prev_m[36]; 364 double compass_prev_xty[6]; 365 366 int compass_peaks[18]; 367 int all_sensors_no_motion; 368 369 long init_compass_bias[3]; 370 371 int got_init_compass_bias; 372 int resetting_compass; 373 374 long ang_v_body[GYRO_NUM_AXES]; 375 unsigned char compass_raw_data[24]; /* Sensor data plus status etc */ 376 long compass_sensor_data[3]; /* Raw sensor data only */ 377 long compass_calibrated_data[3]; 378 long compass_test_calibrated_data[3]; 379 long pressure; 380 inv_error_t (*external_slave_callback)(struct inv_obj_t *); 381 int compass_accuracy; 382 int compass_overunder; 383 384 unsigned short flags[8]; 385 unsigned short suspend; 386 387 long no_motion_threshold; 388 unsigned long motion_duration; 389 390 unsigned short motion_state; 391 392 unsigned short data_mode; 393 unsigned short interrupt_sources; 394 395 unsigned short bias_update_time; 396 short last_motion; 397 unsigned short bias_calc_time; 398 399 unsigned char internal_motion_state; 400 long start_time; 401 402 long accel_lpf_gain; 403 long accel_lpf[3]; 404 unsigned long poll_no_motion; 405 long no_motion_accel_threshold; 406 unsigned long no_motion_accel_time; 407 inv_error_t(*mode_change_func) (unsigned long, unsigned long); 408 }; 409 410 typedef inv_error_t(*inv_obj_func) (struct inv_obj_t *); 411 412 extern struct inv_obj_t inv_obj; 413 414 /* --------------------- */ 415 /* - Params Structure. - */ 416 /* --------------------- */ 417 418 struct inv_params_obj { 419 420 unsigned short bias_mode; // A function or bitwise OR of functions that determine how the gyroscope bias will be automatically updated. 421 // Functions include INV_BIAS_FROM_NO_MOTION, INV_BIAS_FROM_GRAVITY, and INV_BIAS_FROM_TEMPERATURE. 422 // The engine INV_BIAS_UPDATE must be enabled for these algorithms to run. 423 424 unsigned short orientation_mask; // Allows a user to register which orientations will trigger the user defined callback function. 425 // The orientations are INV_X_UP, INV_X_DOWN, INV_Y_UP, INV_Y_DOWN, INV_Z_UP, and INV_Z_DOWN. 426 // INV_ORIENTATION_ALL is equivalent to INV_X_UP | INV_X_DOWN | INV_Y_UP | INV_Y_DOWN | INV_Z_UP | INV_Z_DOWN. 427 428 void (*fifo_processed_func) (void); // Callback function that triggers when all the processing has been finished by the motion processing engines. 429 430 void (*orientation_cb_func) (unsigned short orient); // Callback function that will run when a change of orientation is detected. 431 // The new orientation. May be one of INV_X_UP, INV_X_DOWN, INV_Y_UP, INV_Y_DOWN, INV_Z_UP, or INV_Z_DOWN. 432 433 void (*motion_cb_func) (unsigned short motion_state); // Callback function that will run when a change of motion state is detected. 434 // The new motion state. May be one of INV_MOTION, or INV_NO_MOTION. 435 436 unsigned char state; 437 438 }; 439 440 extern struct inv_params_obj inv_params_obj; 441 /* --------------------- */ 442 /* - Function p-types. - */ 443 /* --------------------- */ 444 445 inv_error_t inv_serial_start(char const *port); 446 inv_error_t inv_serial_stop(void); 447 inv_error_t inv_set_mpu_sensors(unsigned long sensors); 448 void *inv_get_serial_handle(void); 449 450 /*API for handling the buffer */ 451 inv_error_t inv_update_data(void); 452 453 /*API for handling polling */ 454 int inv_check_flag(int flag); 455 456 /*API for setting bias update function */ 457 inv_error_t inv_set_bias_update(unsigned short biasFunction); 458 459#if defined CONFIG_MPU_SENSORS_MPU6050A2 || \ 460 defined CONFIG_MPU_SENSORS_MPU6050B1 461 inv_error_t inv_turn_on_bias_from_no_motion(void); 462 inv_error_t inv_turn_off_bias_from_no_motion(void); 463 inv_error_t inv_set_mpu_6050_config(void); 464#endif 465 466 /* Legacy functions for handling augmented data*/ 467 inv_error_t inv_get_array(int dataSet, long *data); 468 inv_error_t inv_get_float_array(int dataSet, float *data); 469 inv_error_t inv_set_array(int dataSet, long *data); 470 inv_error_t inv_set_float_array(int dataSet, float *data); 471 /* Individual functions for augmented data, per specific dataset */ 472 473 474 inv_error_t inv_get_gyro(long *data); 475 inv_error_t inv_get_accel(long *data); 476 inv_error_t inv_get_temperature(long *data); 477 inv_error_t inv_get_temperature_raw(short *data); 478 inv_error_t inv_get_rot_mat(long *data); 479 inv_error_t inv_get_quaternion(long *data); 480 inv_error_t inv_get_linear_accel(long *data); 481 inv_error_t inv_get_linear_accel_in_world(long *data); 482 inv_error_t inv_get_gravity(long *data); 483 inv_error_t inv_get_angular_velocity(long *data); 484 inv_error_t inv_get_euler_angles(long *data); 485 inv_error_t inv_get_euler_angles_x(long *data); 486 inv_error_t inv_get_euler_angles_y(long *data); 487 inv_error_t inv_get_euler_angles_z(long *data); 488 inv_error_t inv_get_gyro_temp_slope(long *data); 489 inv_error_t inv_get_gyro_bias(long *data); 490 inv_error_t inv_get_accel_bias(long *data); 491 inv_error_t inv_get_mag_bias(long *data); 492 inv_error_t inv_get_gyro_and_accel_sensor(long *data); 493 inv_error_t inv_get_mag_raw_data(long *data); 494 inv_error_t inv_get_magnetometer(long *data); 495 inv_error_t inv_get_pressure(long *data); 496 inv_error_t inv_get_heading(long *data); 497 inv_error_t inv_get_gyro_cal_matrix(long *data); 498 inv_error_t inv_get_accel_cal_matrix(long *data); 499 inv_error_t inv_get_mag_cal_matrix(long *data); 500 inv_error_t inv_get_mag_bias_error(long *data); 501 inv_error_t inv_get_mag_scale(long *data); 502 inv_error_t inv_get_local_field(long *data); 503 inv_error_t inv_get_relative_quaternion(long *data); 504 inv_error_t inv_get_gyro_float(float *data); 505 inv_error_t inv_get_accel_float(float *data); 506 inv_error_t inv_get_temperature_float(float *data); 507 inv_error_t inv_get_rot_mat_float(float *data); 508 inv_error_t inv_get_quaternion_float(float *data); 509 inv_error_t inv_get_linear_accel_float(float *data); 510 inv_error_t inv_get_linear_accel_in_world_float(float *data); 511 inv_error_t inv_get_gravity_float(float *data); 512 inv_error_t inv_get_angular_velocity_float(float *data); 513 inv_error_t inv_get_euler_angles_float(float *data); 514 inv_error_t inv_get_euler_angles_x_float(float *data); 515 inv_error_t inv_get_euler_angles_y_float(float *data); 516 inv_error_t inv_get_euler_angles_z_float(float *data); 517 inv_error_t inv_get_gyro_temp_slope_float(float *data); 518 inv_error_t inv_get_gyro_bias_float(float *data); 519 inv_error_t inv_get_accel_bias_float(float *data); 520 inv_error_t inv_get_mag_bias_float(float *data); 521 inv_error_t inv_get_gyro_and_accel_sensor_float(float *data); 522 inv_error_t inv_get_mag_raw_data_float(float *data); 523 inv_error_t inv_get_magnetometer_float(float *data); 524 inv_error_t inv_get_pressure_float(float *data); 525 inv_error_t inv_get_heading_float(float *data); 526 inv_error_t inv_get_gyro_cal_matrix_float(float *data); 527 inv_error_t inv_get_accel_cal_matrix_float(float *data); 528 inv_error_t inv_get_mag_cal_matrix_float(float *data); 529 inv_error_t inv_get_mag_bias_error_float(float *data); 530 inv_error_t inv_get_mag_scale_float(float *data); 531 inv_error_t inv_get_local_field_float(float *data); 532 inv_error_t inv_get_relative_quaternion_float(float *data); 533 inv_error_t inv_get_compass_accuracy(int *accuracy); 534 inv_error_t inv_set_gyro_bias(long *data); 535 inv_error_t inv_set_accel_bias(long *data); 536 inv_error_t inv_set_mag_bias(long *data); 537 inv_error_t inv_set_gyro_temp_slope(long *data); 538 inv_error_t inv_set_local_field(long *data); 539 inv_error_t inv_set_mag_scale(long *data); 540 inv_error_t inv_set_gyro_temp_slope_float(float *data); 541 inv_error_t inv_set_gyro_bias_float(float *data); 542 inv_error_t inv_set_accel_bias_float(float *data); 543 inv_error_t inv_set_mag_bias_float(float *data); 544 inv_error_t inv_set_local_field_float(float *data); 545 inv_error_t inv_set_mag_scale_float(float *data); 546 547 inv_error_t inv_apply_endian_accel(void); 548 inv_error_t inv_apply_calibration(void); 549 inv_error_t inv_set_gyro_calibration(float range, signed char *orientation); 550 inv_error_t inv_set_accel_calibration(float range, 551 signed char *orientation); 552 inv_error_t inv_set_compass_calibration(float range, 553 signed char *orientation); 554 555 /*API for detecting change of state */ 556 inv_error_t 557 inv_set_motion_callback(void (*func) (unsigned short motion_state)); 558 int inv_get_motion_state(void); 559 560 /*API for getting ML version. */ 561 inv_error_t inv_get_version(unsigned char **version); 562 563 inv_error_t inv_set_motion_interrupt(unsigned char on); 564 inv_error_t inv_set_fifo_interrupt(unsigned char on); 565 566 int inv_get_interrupts(void); 567 568 /* Simulated DMP */ 569 int inv_get_gyro_present(void); 570 571 inv_error_t inv_set_no_motion_time(float time); 572 inv_error_t inv_set_no_motion_thresh(float thresh); 573 inv_error_t inv_set_no_motion_threshAccel(long thresh); 574 inv_error_t inv_reset_motion(void); 575 576 inv_error_t inv_update_bias(void); 577 inv_error_t inv_set_dead_zone(void); 578 void inv_start_bias_calc(void); 579 void inv_stop_bias_calc(void); 580 581 // Private functions shared accross modules 582 void inv_init_ml(void); 583 584 inv_error_t inv_register_dmp_interupt_cb(inv_obj_func func); 585 inv_error_t inv_unregister_dmp_interupt_cb(inv_obj_func func); 586 void inv_run_dmp_interupt_cb(void); 587 void inv_set_mode_change(inv_error_t(*mode_change_func) 588 (unsigned long, unsigned long)); 589 590#ifdef __cplusplus 591} 592#endif 593#endif // INV_H 594/** 595 * @} 596 */ 597