ml.h revision 42331858975144405f95243be8427084ee7d478d
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 243/*************************************************************************/ 244/* General */ 245/*************************************************************************/ 246#define INV_NONE (0x0000) 247#define INV_INVALID_FIFO_RATE (0xFFFF) 248 249/*************************************************************************/ 250/* ML Params Structure Default Values */ 251/*************************************************************************/ 252#define INV_BIAS_UPDATE_FUNC_DEFAULT (INV_BIAS_FROM_NO_MOTION | INV_BIAS_FROM_GRAVITY) 253#define INV_ORIENTATION_MASK_DEFAULT 0x3f 254#define INV_PROCESSED_DATA_CALLBACK_DEFAULT 0 255#define INV_ORIENTATION_CALLBACK_DEFAULT 0 256#define INV_MOTION_CALLBACK_DEFAULT 0 257 258/* ------------ */ 259/* - Defines. - */ 260/* ------------ */ 261/* Priority for various features */ 262#define INV_PRIORITY_BUS_ACCEL 100 263#define INV_PRIORITY_EXTERNAL_SLAVE_MAG 110 264#define INV_PRIORITY_FAST_NO_MOTION 120 265#define INV_PRIORITY_BIAS_NO_MOTION 125 266#define INV_PRIORITY_SET_GYRO_BIASES 150 267#define INV_PRIORITY_TEMP_COMP 175 268#define INV_PRIORITY_CONTROL 200 269#define INV_PRIORITY_EIS 300 270#define INV_PRIORITY_ORIENTATION 400 271#define INV_PRIORITY_PEDOMETER_FULLPOWER 500 272#define INV_PRIORITY_NAVIGATION_PEDOMETER 600 273#define INV_PRIORITY_GESTURE 700 274#define INV_PRIORITY_GLYPH 800 275 276#define MAX_INTERRUPT_PROCESSES 5 277/* Number of quantized accel samples */ 278#define INV_MAX_NUM_ACCEL_SAMPLES (8) 279 280#define PRECISION 10000.f 281#define RANGE_FLOAT_TO_FIXEDPOINT(range, x) { \ 282 range.mantissa = (long)x; \ 283 range.fraction = (long)((float)(x-(long)x)*PRECISION); \ 284} 285#define RANGE_FIXEDPOINT_TO_FLOAT(range, x) { \ 286 x = (float)(range.mantissa); \ 287 x += ((float)range.fraction/PRECISION); \ 288} 289 290 /* --------------- */ 291 /* - Structures. - */ 292 /* --------------- */ 293 294struct inv_obj_t { 295 //Calibration parameters 296 /* Raw sensor orientation */ 297 long gyro_bias[3]; 298 long accel_bias[3]; 299 long compass_bias[3]; 300 301 /* Cached values after orietnation is applied */ 302 long scaled_gyro_bias[3]; 303 long scaled_accel_bias[3]; 304 long scaled_compass_bias[3]; 305 306 long compass_scale[3]; 307 long compass_test_bias[3]; 308 long compass_test_scale[3]; 309 long compass_asa[3]; 310 311 long compass_bias_error[3]; 312 313 long got_no_motion_bias; 314 long got_compass_bias; 315 long compass_state; 316 long large_field; 317 long acc_state; 318 319 long factory_temp_comp; 320 long got_coarse_heading; 321 long gyro_temp_bias[3]; 322 long prog_no_motion_bias[3]; 323 324 long accel_cal[9]; 325 // Deprecated, used gyro_orient 326 long gyro_cal[GYRO_NUM_AXES * GYRO_NUM_AXES]; 327 long gyro_orient[GYRO_NUM_AXES * GYRO_NUM_AXES]; 328 long accel_sens; 329 long compass_cal[9]; 330 long gyro_sens; 331 long gyro_sf; 332 long temp_slope[GYRO_NUM_AXES]; 333 long compass_sens; 334 long temp_offset[GYRO_NUM_AXES]; 335 336 int cal_loaded_flag; 337 338 /* temperature compensation */ 339 float x_gyro_coef[3]; 340 float y_gyro_coef[3]; 341 float z_gyro_coef[3]; 342 float x_gyro_temp_data[BINS][PTS_PER_BIN]; 343 float y_gyro_temp_data[BINS][PTS_PER_BIN]; 344 float z_gyro_temp_data[BINS][PTS_PER_BIN]; 345 float temp_data[BINS][PTS_PER_BIN]; 346 int temp_ptrs[BINS]; 347 long temp_valid_data[BINS]; 348 349 long compass_correction[4]; 350 long compass_correction_relative[4]; 351 long compass_disturb_correction[4]; 352 long compass_correction_offset[4]; 353 long relative_quat[4]; 354 long local_field[3]; 355 long new_local_field; 356 long sync_grav_body[3]; 357 int gyro_bias_err; 358 359 double compass_bias_ptr[9]; 360 double compass_bias_v[3]; 361 double compass_prev_m[36]; 362 double compass_prev_xty[6]; 363 364 int compass_peaks[18]; 365 int all_sensors_no_motion; 366 367 long init_compass_bias[3]; 368 369 int got_init_compass_bias; 370 int resetting_compass; 371 372 long ang_v_body[GYRO_NUM_AXES]; 373 unsigned char compass_raw_data[24]; /* Sensor data plus status etc */ 374 long compass_sensor_data[3]; /* Raw sensor data only */ 375 long compass_calibrated_data[3]; 376 long compass_test_calibrated_data[3]; 377 long pressure; 378 inv_error_t (*external_slave_callback)(struct inv_obj_t *); 379 int compass_accuracy; 380 381 unsigned short flags[7]; 382 unsigned short suspend; 383 384 long no_motion_threshold; 385 unsigned long motion_duration; 386 387 unsigned short motion_state; 388 389 unsigned short data_mode; 390 unsigned short interrupt_sources; 391 392 unsigned short bias_update_time; 393 short last_motion; 394 unsigned short bias_calc_time; 395 396 unsigned char internal_motion_state; 397 long start_time; 398 399 long accel_lpf_gain; 400 long accel_lpf[3]; 401 unsigned long poll_no_motion; 402 long no_motion_accel_threshold; 403 unsigned long no_motion_accel_time; 404 inv_error_t(*mode_change_func) (unsigned long, unsigned long); 405 }; 406 407 typedef inv_error_t(*inv_obj_func) (struct inv_obj_t *); 408 409 extern struct inv_obj_t inv_obj; 410 411 /* --------------------- */ 412 /* - Params Structure. - */ 413 /* --------------------- */ 414 415 struct inv_params_obj { 416 417 unsigned short bias_mode; // A function or bitwise OR of functions that determine how the gyroscope bias will be automatically updated. 418 // Functions include INV_BIAS_FROM_NO_MOTION, INV_BIAS_FROM_GRAVITY, and INV_BIAS_FROM_TEMPERATURE. 419 // The engine INV_BIAS_UPDATE must be enabled for these algorithms to run. 420 421 unsigned short orientation_mask; // Allows a user to register which orientations will trigger the user defined callback function. 422 // The orientations are INV_X_UP, INV_X_DOWN, INV_Y_UP, INV_Y_DOWN, INV_Z_UP, and INV_Z_DOWN. 423 // INV_ORIENTATION_ALL is equivalent to INV_X_UP | INV_X_DOWN | INV_Y_UP | INV_Y_DOWN | INV_Z_UP | INV_Z_DOWN. 424 425 void (*fifo_processed_func) (void); // Callback function that triggers when all the processing has been finished by the motion processing engines. 426 427 void (*orientation_cb_func) (unsigned short orient); // Callback function that will run when a change of orientation is detected. 428 // 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. 429 430 void (*motion_cb_func) (unsigned short motion_state); // Callback function that will run when a change of motion state is detected. 431 // The new motion state. May be one of INV_MOTION, or INV_NO_MOTION. 432 433 unsigned char state; 434 435 }; 436 437 extern struct inv_params_obj inv_params_obj; 438 /* --------------------- */ 439 /* - Function p-types. - */ 440 /* --------------------- */ 441 442 inv_error_t inv_serial_start(char const *port); 443 inv_error_t inv_serial_stop(void); 444 inv_error_t inv_set_mpu_sensors(unsigned long sensors); 445 void *inv_get_serial_handle(void); 446 447 /*API for handling the buffer */ 448 inv_error_t inv_update_data(void); 449 450 /*API for handling polling */ 451 int inv_check_flag(int flag); 452 453 /*API for setting bias update function */ 454 inv_error_t inv_set_bias_update(unsigned short biasFunction); 455 456#if defined CONFIG_MPU_SENSORS_MPU6050A2 || \ 457 defined CONFIG_MPU_SENSORS_MPU6050B1 458 inv_error_t inv_turn_on_bias_from_no_motion(void); 459 inv_error_t inv_turn_off_bias_from_no_motion(void); 460 inv_error_t inv_set_mpu_6050_config(void); 461#endif 462 463 /* Legacy functions for handling augmented data*/ 464 inv_error_t inv_get_array(int dataSet, long *data); 465 inv_error_t inv_get_float_array(int dataSet, float *data); 466 inv_error_t inv_set_array(int dataSet, long *data); 467 inv_error_t inv_set_float_array(int dataSet, float *data); 468 /* Individual functions for augmented data, per specific dataset */ 469 470 471 inv_error_t inv_get_gyro(long *data); 472 inv_error_t inv_get_accel(long *data); 473 inv_error_t inv_get_temperature(long *data); 474 inv_error_t inv_get_temperature_raw(short *data); 475 inv_error_t inv_get_rot_mat(long *data); 476 inv_error_t inv_get_quaternion(long *data); 477 inv_error_t inv_get_linear_accel(long *data); 478 inv_error_t inv_get_linear_accel_in_world(long *data); 479 inv_error_t inv_get_gravity(long *data); 480 inv_error_t inv_get_angular_velocity(long *data); 481 inv_error_t inv_get_euler_angles(long *data); 482 inv_error_t inv_get_euler_angles_x(long *data); 483 inv_error_t inv_get_euler_angles_y(long *data); 484 inv_error_t inv_get_euler_angles_z(long *data); 485 inv_error_t inv_get_gyro_temp_slope(long *data); 486 inv_error_t inv_get_gyro_bias(long *data); 487 inv_error_t inv_get_accel_bias(long *data); 488 inv_error_t inv_get_mag_bias(long *data); 489 inv_error_t inv_get_gyro_and_accel_sensor(long *data); 490 inv_error_t inv_get_mag_raw_data(long *data); 491 inv_error_t inv_get_magnetometer(long *data); 492 inv_error_t inv_get_pressure(long *data); 493 inv_error_t inv_get_heading(long *data); 494 inv_error_t inv_get_gyro_cal_matrix(long *data); 495 inv_error_t inv_get_accel_cal_matrix(long *data); 496 inv_error_t inv_get_mag_cal_matrix(long *data); 497 inv_error_t inv_get_mag_bias_error(long *data); 498 inv_error_t inv_get_mag_scale(long *data); 499 inv_error_t inv_get_local_field(long *data); 500 inv_error_t inv_get_relative_quaternion(long *data); 501 inv_error_t inv_get_gyro_float(float *data); 502 inv_error_t inv_get_accel_float(float *data); 503 inv_error_t inv_get_temperature_float(float *data); 504 inv_error_t inv_get_rot_mat_float(float *data); 505 inv_error_t inv_get_quaternion_float(float *data); 506 inv_error_t inv_get_linear_accel_float(float *data); 507 inv_error_t inv_get_linear_accel_in_world_float(float *data); 508 inv_error_t inv_get_gravity_float(float *data); 509 inv_error_t inv_get_angular_velocity_float(float *data); 510 inv_error_t inv_get_euler_angles_float(float *data); 511 inv_error_t inv_get_euler_angles_x_float(float *data); 512 inv_error_t inv_get_euler_angles_y_float(float *data); 513 inv_error_t inv_get_euler_angles_z_float(float *data); 514 inv_error_t inv_get_gyro_temp_slope_float(float *data); 515 inv_error_t inv_get_gyro_bias_float(float *data); 516 inv_error_t inv_get_accel_bias_float(float *data); 517 inv_error_t inv_get_mag_bias_float(float *data); 518 inv_error_t inv_get_gyro_and_accel_sensor_float(float *data); 519 inv_error_t inv_get_mag_raw_data_float(float *data); 520 inv_error_t inv_get_magnetometer_float(float *data); 521 inv_error_t inv_get_pressure_float(float *data); 522 inv_error_t inv_get_heading_float(float *data); 523 inv_error_t inv_get_gyro_cal_matrix_float(float *data); 524 inv_error_t inv_get_accel_cal_matrix_float(float *data); 525 inv_error_t inv_get_mag_cal_matrix_float(float *data); 526 inv_error_t inv_get_mag_bias_error_float(float *data); 527 inv_error_t inv_get_mag_scale_float(float *data); 528 inv_error_t inv_get_local_field_float(float *data); 529 inv_error_t inv_get_relative_quaternion_float(float *data); 530 inv_error_t inv_get_compass_accuracy(int *accuracy); 531 inv_error_t inv_set_gyro_bias(long *data); 532 inv_error_t inv_set_accel_bias(long *data); 533 inv_error_t inv_set_mag_bias(long *data); 534 inv_error_t inv_set_gyro_temp_slope(long *data); 535 inv_error_t inv_set_local_field(long *data); 536 inv_error_t inv_set_mag_scale(long *data); 537 inv_error_t inv_set_gyro_temp_slope_float(float *data); 538 inv_error_t inv_set_gyro_bias_float(float *data); 539 inv_error_t inv_set_accel_bias_float(float *data); 540 inv_error_t inv_set_mag_bias_float(float *data); 541 inv_error_t inv_set_local_field_float(float *data); 542 inv_error_t inv_set_mag_scale_float(float *data); 543 544 inv_error_t inv_apply_endian_accel(void); 545 inv_error_t inv_apply_calibration(void); 546 inv_error_t inv_set_gyro_calibration(float range, signed char *orientation); 547 inv_error_t inv_set_accel_calibration(float range, 548 signed char *orientation); 549 inv_error_t inv_set_compass_calibration(float range, 550 signed char *orientation); 551 552 /*API for detecting change of state */ 553 inv_error_t 554 inv_set_motion_callback(void (*func) (unsigned short motion_state)); 555 int inv_get_motion_state(void); 556 557 /*API for getting ML version. */ 558 inv_error_t inv_get_version(unsigned char **version); 559 560 inv_error_t inv_set_motion_interrupt(unsigned char on); 561 inv_error_t inv_set_fifo_interrupt(unsigned char on); 562 563 int inv_get_interrupts(void); 564 565 /* Simulated DMP */ 566 int inv_get_gyro_present(void); 567 568 inv_error_t inv_set_no_motion_time(float time); 569 inv_error_t inv_set_no_motion_thresh(float thresh); 570 inv_error_t inv_set_no_motion_threshAccel(long thresh); 571 inv_error_t inv_reset_motion(void); 572 573 inv_error_t inv_update_bias(void); 574 inv_error_t inv_set_dead_zone(void); 575 void inv_start_bias_calc(void); 576 void inv_stop_bias_calc(void); 577 578 // Private functions shared accross modules 579 void inv_init_ml(void); 580 581 inv_error_t inv_register_dmp_interupt_cb(inv_obj_func func); 582 inv_error_t inv_unregister_dmp_interupt_cb(inv_obj_func func); 583 void inv_run_dmp_interupt_cb(void); 584 void inv_set_mode_change(inv_error_t(*mode_change_func) 585 (unsigned long, unsigned long)); 586 587#ifdef __cplusplus 588} 589#endif 590#endif // INV_H 591/** 592 * @} 593 */ 594