1c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/*
2c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro $License:
3c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    Copyright (C) 2011-2012 InvenSense Corporation, All Rights Reserved.
4c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    See included License.txt for License information.
5c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro $
6c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
7c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
8c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
9c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *   @defgroup  Data_Builder data_builder
10c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *   @brief     Motion Library - Data Builder
11c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              Constructs and Creates the data for MPL
12c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *
13c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *   @{
14c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *       @file data_builder.c
15c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *       @brief Data Builder.
16c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
17c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
18c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#undef MPL_LOG_NDEBUG
19c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#define MPL_LOG_NDEBUG 1 /* Use 0 to turn on MPL_LOGV output */
20c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
21c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include <string.h>
22c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
23c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "ml_math_func.h"
24c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "data_builder.h"
25c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "mlmath.h"
26c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "storage_manager.h"
27c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "message_layer.h"
28c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "results_holder.h"
29c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
30c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#include "log.h"
31c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#undef MPL_LOG_TAG
32c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#define MPL_LOG_TAG "MLLITE"
33c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
34c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarotypedef inv_error_t (*inv_process_cb_func)(struct inv_sensor_cal_t *data);
35c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
36c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostruct process_t {
37c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_process_cb_func func;
38c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int priority;
39c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int data_required;
40c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro};
41c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
42c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostruct inv_data_builder_t {
43c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int num_cb;
44c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    struct process_t process[INV_MAX_DATA_CB];
45c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    struct inv_db_save_t save;
46c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    struct inv_db_save_mpl_t save_mpl;
47c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    struct inv_db_save_accel_mpl_t save_accel_mpl;
48c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int compass_disturbance;
49c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int mode;
50c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
51c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int debug_mode;
52c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int last_mode;
53c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    FILE *file;
54c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
55c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro};
56c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
57c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_apply_calibration(struct inv_single_sensor_t *sensor, const long *bias);
58c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic void inv_set_contiguous(void);
59c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
60c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic struct inv_data_builder_t inv_data_builder;
61c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic struct inv_sensor_cal_t sensors;
62c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
63c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
64c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
65c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Turn on data logging to allow playback of same scenario at a later time.
66c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] file File to write to, must be open.
67c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
68c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_turn_on_data_logging(FILE *file)
69c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
70c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    MPL_LOGV("input data logging started\n");
71c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.file = file;
72c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.debug_mode = RD_RECORD;
73c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
74c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
75c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Turn off data logging to allow playback of same scenario at a later time.
76c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* File passed to inv_turn_on_data_logging() must be closed after calling this.
77c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
78c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_turn_off_data_logging()
79c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
80c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    MPL_LOGV("input data logging stopped\n");
81c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.debug_mode = RD_NO_DEBUG;
82c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.file = NULL;
83c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
84c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
85c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
86c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets last value of raw compass data.
87c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] raw Raw compass data in mounting frame in hardware units. Length 3.
88c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
89c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_raw_compass(short *raw)
90c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
91c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(raw, sensors.compass.raw, sizeof(sensors.compass.raw));
92c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
93c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
94c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This function receives the data that was stored in non-volatile memory between power off */
95c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic inv_error_t inv_db_load_func(const unsigned char *data)
96c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
97c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(&inv_data_builder.save, data, sizeof(inv_data_builder.save));
98c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // copy in the saved accuracy in the actual sensors accuracy
99c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.accuracy = inv_data_builder.save.gyro_accuracy;
100c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.accuracy = inv_data_builder.save.accel_accuracy;
101c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.accuracy = inv_data_builder.save.compass_accuracy;
102c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // TODO
103c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.accel.accuracy == 3) {
104c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_set_accel_bias_found(1);
105c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
106c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.compass.accuracy == 3) {
107c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_set_compass_bias_found(1);
108c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
109c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
110c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
111c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
112c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This function returns the data to be stored in non-volatile memory between power off */
113c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic inv_error_t inv_db_save_func(unsigned char *data)
114c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
115c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(data, &inv_data_builder.save, sizeof(inv_data_builder.save));
116c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
117c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
118c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
119c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This function receives the data for mpl that was stored in non-volatile memory between power off */
120c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic inv_error_t inv_db_load_mpl_func(const unsigned char *data)
121c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
122c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(&inv_data_builder.save_mpl, data, sizeof(inv_data_builder.save_mpl));
123c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
124c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
125c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
126c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
127c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This function returns the data for mpl to be stored in non-volatile memory between power off */
128c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic inv_error_t inv_db_save_mpl_func(unsigned char *data)
129c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
130c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(data, &inv_data_builder.save_mpl, sizeof(inv_data_builder.save_mpl));
131c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
132c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
133c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
134c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This function receives the data for mpl that was stored in non-volatile memory between power off */
135c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic inv_error_t inv_db_load_accel_mpl_func(const unsigned char *data)
136c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
137c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(&inv_data_builder.save_accel_mpl, data, sizeof(inv_data_builder.save_accel_mpl));
138c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
139c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
140c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
141c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
142c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This function returns the data for mpl to be stored in non-volatile memory between power off */
143c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic inv_error_t inv_db_save_accel_mpl_func(unsigned char *data)
144c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
145c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(data, &inv_data_builder.save_accel_mpl, sizeof(inv_data_builder.save_accel_mpl));
146c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
147c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
148c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
149c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Initialize the data builder
150c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
151c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_init_data_builder(void)
152c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
153c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /* TODO: Hardcode temperature scale/offset here. */
154c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memset(&inv_data_builder, 0, sizeof(inv_data_builder));
155c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memset(&sensors, 0, sizeof(sensors));
156c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
157c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // disable the soft iron transform process
158c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_reset_compass_soft_iron_matrix();
159c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
160c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return ((inv_register_load_store(inv_db_load_func, inv_db_save_func,
161c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                   sizeof(inv_data_builder.save),
162c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                   INV_DB_SAVE_KEY))
163c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro          | (inv_register_load_store(inv_db_load_mpl_func, inv_db_save_mpl_func,
164c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                   sizeof(inv_data_builder.save_mpl),
165c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                   INV_DB_SAVE_MPL_KEY))
166c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro          | (inv_register_load_store(inv_db_load_accel_mpl_func, inv_db_save_accel_mpl_func,
167c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                   sizeof(inv_data_builder.save_accel_mpl),
168c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                   INV_DB_SAVE_ACCEL_MPL_KEY)) );
169c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
170c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
171c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gyro sensitivity.
172c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return A scale factor to convert device units to degrees per second scaled by 2^16
173c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* such that degrees_per_second  = device_units * sensitivity / 2^30. Typically
174c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* it works out to be the maximum rate * 2^15.
175c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
176c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_get_gyro_sensitivity(void)
177c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
178c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return sensors.gyro.sensitivity;
179c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
180c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
181c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Accel sensitivity.
182c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return A scale factor to convert device units to g's scaled by 2^16
183c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* such that g_s  = device_units * sensitivity / 2^30. Typically
184c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* it works out to be the maximum accel value in g's * 2^15.
185c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
186c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_get_accel_sensitivity(void)
187c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
188c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return sensors.accel.sensitivity;
189c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
190c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
191c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Compass sensitivity.
192c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return A scale factor to convert device units to micro Tesla scaled by 2^16
193c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* such that uT  = device_units * sensitivity / 2^30. Typically
194c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* it works out to be the maximum uT * 2^15.
195c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
196c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarolong inv_get_compass_sensitivity(void)
197c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
198c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return sensors.compass.sensitivity;
199c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
200c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
201c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets orientation and sensitivity field for a sensor.
202c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] sensor Structure to apply settings to
203c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] orientation Orientation description of how part is mounted.
204c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sensitivity A Scale factor to convert from hardware units to
205c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            standard units (dps, uT, g).
206c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
207c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid set_sensor_orientation_and_scale(struct inv_single_sensor_t *sensor,
208c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                 int orientation, long sensitivity)
209c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
210c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int error = 0;
211c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
212c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (!sensitivity) {
213c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // Sensitivity can't be zero
214c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensitivity = 1L<<16;
215c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        MPL_LOGE("\n\nCritical error! Sensitivity is zero.\n\n");
216c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
217c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
218c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensor->sensitivity = sensitivity;
219c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Make sure we don't describe some impossible orientation
220c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((orientation & 3) == 3) {
221c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        error = 1;
222c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
223c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((orientation & 0x18) == 0x18) {
224c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        error = 1;
225c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
226c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((orientation & 0xc0) == 0xc0) {
227c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        error = 1;
228c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
229c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (error) {
230c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        orientation = 0x88; // Identity
231c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        MPL_LOGE("\n\nCritical error! Impossible mounting orientation given. Using Identity instead\n\n");
232c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
233c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensor->orientation = orientation;
234c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
235c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
236c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets the Orientation and Sensitivity of the gyro data.
237c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] orientation A scalar defining the transformation from chip mounting
238c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            to the body frame. The function inv_orientation_matrix_to_scalar()
239c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            can convert the transformation matrix to this scalar and describes the
240c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            scalar in further detail.
241c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sensitivity A scale factor to convert device units to degrees per second scaled by 2^16
242c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            such that degrees_per_second  = device_units * sensitivity / 2^30. Typically
243c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            it works out to be the maximum rate * 2^15.
244c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
245c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_gyro_orientation_and_scale(int orientation, long sensitivity)
246c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
247c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
248c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
249c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_G_ORIENT;
250c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
251c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&orientation, sizeof(orientation), 1, inv_data_builder.file);
252c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&sensitivity, sizeof(sensitivity), 1, inv_data_builder.file);
253c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
254c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
255c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    set_sensor_orientation_and_scale(&sensors.gyro, orientation,
256c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                     sensitivity);
257c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
258c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
259c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Set Gyro Sample rate in micro seconds.
260c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sample_rate_us Set Gyro Sample rate in us
261c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
262c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_gyro_sample_rate(long sample_rate_us)
263c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
264c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
265c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
266c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_G_SAMPLE_RATE;
267c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
268c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&sample_rate_us, sizeof(sample_rate_us), 1, inv_data_builder.file);
269c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
270c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
271c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.sample_rate_us = sample_rate_us;
272c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.sample_rate_ms = sample_rate_us / 1000;
273c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.gyro.bandwidth == 0) {
274c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.gyro.bandwidth = (int)(1000000L / sample_rate_us);
275c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
276c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
277c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
278c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Set Accel Sample rate in micro seconds.
279c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sample_rate_us Set Accel Sample rate in us
280c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
281c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_accel_sample_rate(long sample_rate_us)
282c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
283c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
284c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
285c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_A_SAMPLE_RATE;
286c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
287c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&sample_rate_us, sizeof(sample_rate_us), 1, inv_data_builder.file);
288c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
289c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
290c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.sample_rate_us = sample_rate_us;
291c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.sample_rate_ms = sample_rate_us / 1000;
292c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.accel.bandwidth == 0) {
293c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.bandwidth = (int)(1000000L / sample_rate_us);
294c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
295c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
296c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
297c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Pick the smallest non-negative number. Priority to td1 on equal
298c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* If both are negative, return the largest.
299c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
300c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic int inv_pick_best_time_difference(long td1, long td2)
301c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
302c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (td1 >= 0) {
303c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (td2 >= 0) {
304c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (td1 <= td2) {
305c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                // td1
306c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                return 0;
307c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            } else {
308c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                // td2
309c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                return 1;
310c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            }
311c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        } else {
312c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            // td1
313c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            return 0;
314c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
315c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else if (td2 >= 0) {
316c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // td2
317c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 1;
318c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
319c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // Both are negative
320c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (td1 >= td2) {
321c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            // td1
322c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            return 0;
323c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        } else {
324c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            // td2
325c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            return 1;
326c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
327c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
328c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
329c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
330c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Returns timestame based upon a raw sensor, and returns if that sample has a new piece of data.
331c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
332c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic int inv_raw_sensor_timestamp(int sensor_number, inv_time_t *ts)
333c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
334c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int status = 0;
335c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    switch (sensor_number) {
336c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    case 0: // Quat
337c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *ts = sensors.quat.timestamp;
338c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (inv_data_builder.mode & INV_QUAT_NEW)
339c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (sensors.quat.timestamp_prev != sensors.quat.timestamp)
340c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                status = 1;
341c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return status;
342c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    case 1: // Gyro
343c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *ts = sensors.gyro.timestamp;
344c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (inv_data_builder.mode & INV_GYRO_NEW)
345c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (sensors.gyro.timestamp_prev != sensors.gyro.timestamp)
346c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                status = 1;
3472eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro        return status;
3482eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro    case 2: // Accel
3492eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro        *ts = sensors.accel.timestamp;
3502eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro        if (inv_data_builder.mode & INV_ACCEL_NEW)
3512eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro            if (sensors.accel.timestamp_prev != sensors.accel.timestamp)
3522eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro                status = 1;
353c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return status;
3542eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro   case 3: // Compass
355c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *ts = sensors.compass.timestamp;
356c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (inv_data_builder.mode & INV_MAG_NEW)
357c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (sensors.compass.timestamp_prev != sensors.compass.timestamp)
358c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                status = 1;
359c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return status;
360c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    default:
361c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *ts = 0;
362c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0;
363c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
364c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return 0;
365c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
366c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
367c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets best timestamp and if there is a new piece of data for a 9-axis sensor combination.
368c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* It does this by finding a raw sensor that has the closest sample rate that is at least as
369c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* often desired. It also returns if that raw sensor has a new piece of data.
370c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Priority is 9-axis quat, 6-axis quat, 3-axis quat, gyro, compass, accel on ties.
371c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns 1, if the raw sensor being attached has new data, 0 otherwise.
372c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
373c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_9_axis_timestamp(long sample_rate_us, inv_time_t *ts)
374c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
375c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int status = 0;
376c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long td[3];
377c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int idx,idx2;
378c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
379c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.quat.status & (INV_QUAT_9AXIS | INV_SENSOR_ON)) == (INV_QUAT_9AXIS | INV_SENSOR_ON)) {
380c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // 9-axis from DMP
381c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *ts = sensors.quat.timestamp;
382c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (inv_data_builder.mode & INV_QUAT_NEW)
383c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (sensors.quat.timestamp_prev != sensors.quat.timestamp)
384c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                status = 1;
385c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return status;
386c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
387c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
388c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.compass.status & INV_SENSOR_ON) == 0) {
389c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0; // Compass must be on
390c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
391c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
392c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // At this point, we know compass is on. Check if accel or 6-axis quat is on
393c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    td[0] = sample_rate_us - sensors.quat.sample_rate_us;
394c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    td[1] = sample_rate_us - sensors.compass.sample_rate_us;
395c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.quat.status & (INV_QUAT_6AXIS | INV_SENSOR_ON)) == (INV_QUAT_6AXIS | INV_SENSOR_ON)) {
396c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // Sensor tied to compass or 6-axis
397c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        idx = inv_pick_best_time_difference(td[0], td[1]);
3982eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro        idx *= 3; // Sensor number is 0 (Quat) or 3 (Compass)
399c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return inv_raw_sensor_timestamp(idx, ts);
400c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else if ((sensors.accel.status & INV_SENSOR_ON) == 0) {
401c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0; // Accel must be on or 6-axis quat must be on
402c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
403c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
404c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // At this point, we know accel is on. Check if 3-axis quat is on
405c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    td[2] = sample_rate_us - sensors.accel.sample_rate_us;
406c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.quat.status & (INV_QUAT_3AXIS | INV_SENSOR_ON)) == (INV_QUAT_3AXIS | INV_SENSOR_ON)) {
407c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        idx = inv_pick_best_time_difference(td[0], td[1]);
408c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        idx2 = inv_pick_best_time_difference(td[idx], td[2]);
409c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (idx2 == 1)
410c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            idx = 2;
411c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (idx > 0)
412c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            idx++; // Skip gyro sensor in next function call
413c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // 0 = quat, 2 = compass, 3=accel
414c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return inv_raw_sensor_timestamp(idx, ts);
415c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
416c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
417c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // No Quaternion data from outside, Gyro must be on
418c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.gyro.status & INV_SENSOR_ON) == 0) {
419c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0; // Gyro must be on
420c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
421c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
422c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    td[0] = sample_rate_us - sensors.gyro.sample_rate_us;
423c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    idx = inv_pick_best_time_difference(td[0], td[1]);
424c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    idx2 = inv_pick_best_time_difference(td[idx], td[2]);
425c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (idx2 == 1)
426c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        idx = 2;
427c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    idx++;
428c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // 1 = gyro, 2 = compass, 3=accel
429c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return inv_raw_sensor_timestamp(idx, ts);
430c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
431c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
432c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets best timestamp and if there is a new piece of data for a 9-axis sensor combination.
433c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* It does this by finding a raw sensor that has the closest sample rate that is at least as
434c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* often desired. It also returns if that raw sensor has a new piece of data.
435c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Priority compass, accel on a tie
436c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns 1, if the raw sensor being attached has new data, 0 otherwise.
437c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
438c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_6_axis_compass_accel_timestamp(long sample_rate_us, inv_time_t *ts)
439c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
440c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long td[2];
441c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int idx;
442c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
443c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.compass.status & INV_SENSOR_ON) == 0) {
444c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0; // Compass must be on
445c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
446c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.accel.status & INV_SENSOR_ON) == 0) {
447c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0; // Accel must be on
448c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
449c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
450c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // At this point, we know compass & accel are both on.
4512eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro    td[0] = sample_rate_us - sensors.accel.sample_rate_us;
4522eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro    td[1] = sample_rate_us - sensors.compass.sample_rate_us;
453c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    idx = inv_pick_best_time_difference(td[0], td[1]);
454c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    idx += 2;
455c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return inv_raw_sensor_timestamp(idx, ts);
456c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
457c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
458c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets best timestamp and if there is a new piece of data for a 9-axis sensor combination.
459c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* It does this by finding a raw sensor that has the closest sample rate that is at least as
460c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* often desired. It also returns if that raw sensor has a new piece of data.
461c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* Priority is Quaternion-6axis, Quaternion 3-axis, Gyro, Accel
462c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns 1, if the raw sensor being attached has new data, 0 otherwise.
463c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
464c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_6_axis_gyro_accel_timestamp(long sample_rate_us, inv_time_t *ts)
465c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
466c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long td[2];
467c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int idx;
468c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
469c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.quat.status & (INV_QUAT_6AXIS | INV_SENSOR_ON)) == (INV_QUAT_6AXIS | INV_SENSOR_ON)) {
470c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // Sensor number is 0 (Quat)
471c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return inv_raw_sensor_timestamp(0, ts);
472c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else if ((sensors.accel.status & INV_SENSOR_ON) == 0) {
473c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0; // Accel must be on or 6-axis quat must be on
474c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
475c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
476c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // At this point, we know accel is on. Check if 3-axis quat is on
477c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    td[0] = sample_rate_us - sensors.quat.sample_rate_us;
478c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    td[1] = sample_rate_us - sensors.accel.sample_rate_us;
479c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.quat.status & (INV_QUAT_3AXIS | INV_SENSOR_ON)) == (INV_QUAT_3AXIS | INV_SENSOR_ON)) {
480c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        idx = inv_pick_best_time_difference(td[0], td[1]);
4812eed2d4028b5706e977b016e49b010ee5595e48aNick Vaccaro        idx *= 2;
482c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // 0 = quat, 3=accel
483c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return inv_raw_sensor_timestamp(idx, ts);
484c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
485c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
486c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // No Quaternion data from outside, Gyro must be on
487c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((sensors.gyro.status & INV_SENSOR_ON) == 0) {
488c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0; // Gyro must be on
489c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
490c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
491c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    td[0] = sample_rate_us - sensors.gyro.sample_rate_us;
492c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    idx = inv_pick_best_time_difference(td[0], td[1]);
493c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    idx *= 2; // 0=gyro 2=accel
494c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    idx++;
495c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // 1 = gyro, 3=accel
496c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return inv_raw_sensor_timestamp(idx, ts);
497c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
498c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
499c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Set Compass Sample rate in micro seconds.
500c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sample_rate_us Set Gyro Sample rate in micro seconds.
501c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
502c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_compass_sample_rate(long sample_rate_us)
503c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
504c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
505c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
506c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_C_SAMPLE_RATE;
507c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
508c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&sample_rate_us, sizeof(sample_rate_us), 1, inv_data_builder.file);
509c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
510c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
511c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.sample_rate_us = sample_rate_us;
512c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.sample_rate_ms = sample_rate_us / 1000;
513c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.compass.bandwidth == 0) {
514c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.bandwidth = (int)(1000000L / sample_rate_us);
515c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
516c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
517c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
518c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_gyro_sample_rate_ms(long *sample_rate_ms)
519c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
520c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	*sample_rate_ms = sensors.gyro.sample_rate_ms;
521c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
522c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
523c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_accel_sample_rate_ms(long *sample_rate_ms)
524c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
525c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	*sample_rate_ms = sensors.accel.sample_rate_ms;
526c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
527c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
528c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_compass_sample_rate_ms(long *sample_rate_ms)
529c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
530c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	*sample_rate_ms = sensors.compass.sample_rate_ms;
531c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
532c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
533c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Set Quat Sample rate in micro seconds.
534c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sample_rate_us Set Quat Sample rate in us
535c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
536c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_quat_sample_rate(long sample_rate_us)
537c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
538c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
539c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
540c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_Q_SAMPLE_RATE;
541c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
542c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&sample_rate_us, sizeof(sample_rate_us), 1, inv_data_builder.file);
543c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
544c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
545c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.sample_rate_us = sample_rate_us;
546c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.sample_rate_ms = sample_rate_us / 1000;
547c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
548c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
549c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Set Gyro Bandwidth in Hz
550c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] bandwidth_hz Gyro bandwidth in Hz
551c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
552c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_gyro_bandwidth(int bandwidth_hz)
553c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
554c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.bandwidth = bandwidth_hz;
555c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
556c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
557c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Set Accel Bandwidth in Hz
558c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] bandwidth_hz Gyro bandwidth in Hz
559c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
560c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_accel_bandwidth(int bandwidth_hz)
561c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
562c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.bandwidth = bandwidth_hz;
563c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
564c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
565c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Set Compass Bandwidth in Hz
566c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in]  bandwidth_hz Gyro bandwidth in Hz
567c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
568c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_compass_bandwidth(int bandwidth_hz)
569c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
570c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.bandwidth = bandwidth_hz;
571c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
572c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
573c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Helper function stating whether the compass is on or off.
574c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return TRUE if compass if on, 0 if compass if off
575c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
576c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_compass_on()
577c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
578c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return (sensors.compass.status & INV_SENSOR_ON) == INV_SENSOR_ON;
579c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
580c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
581c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Helper function stating whether the gyro is on or off.
582c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return TRUE if gyro if on, 0 if gyro if off
583c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
584c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_gyro_on()
585c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
586c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return (sensors.gyro.status & INV_SENSOR_ON) == INV_SENSOR_ON;
587c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
588c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
589c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Helper function stating whether the acceleromter is on or off.
590c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return TRUE if accel if on, 0 if accel if off
591c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
592c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_accel_on()
593c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
594c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return (sensors.accel.status & INV_SENSOR_ON) == INV_SENSOR_ON;
595c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
596c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
597c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Get last timestamp across all 3 sensors that are on.
598c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* This find out which timestamp has the largest value for sensors that are on.
599c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns INV_SUCCESS if successful or an error code if not.
600c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
601c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_time_t inv_get_last_timestamp()
602c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
603c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_time_t timestamp = 0;
604c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.accel.status & INV_SENSOR_ON) {
605c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        timestamp = sensors.accel.timestamp;
606c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
607c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.gyro.status & INV_SENSOR_ON) {
608c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (timestamp < sensors.gyro.timestamp) {
609c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            timestamp = sensors.gyro.timestamp;
610c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
611c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        MPL_LOGV("g ts: %lld", timestamp);
612c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
613c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.compass.status & INV_SENSOR_ON) {
614c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (timestamp < sensors.compass.timestamp) {
615c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            timestamp = sensors.compass.timestamp;
616c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
617c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
618c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.temp.status & INV_SENSOR_ON) {
619c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (timestamp < sensors.temp.timestamp) {
620c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            timestamp = sensors.temp.timestamp;
621c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
622c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
623c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.quat.status & INV_SENSOR_ON) {
624c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (timestamp < sensors.quat.timestamp) {
625c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            timestamp = sensors.quat.timestamp;
626c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
627c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        MPL_LOGV("q ts: %lld", timestamp);
628c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
629c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
630c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return timestamp;
631c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
632c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
633c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets the orientation and sensitivity of the gyro data.
634c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] orientation A scalar defining the transformation from chip mounting
635c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            to the body frame. The function inv_orientation_matrix_to_scalar()
636c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            can convert the transformation matrix to this scalar and describes the
637c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            scalar in further detail.
638c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sensitivity A scale factor to convert device units to g's
639c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            such that g's = device_units * sensitivity / 2^30. Typically
640c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            it works out to be the maximum g_value * 2^15.
641c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
642c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_accel_orientation_and_scale(int orientation, long sensitivity)
643c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
644c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
645c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
646c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_A_ORIENT;
647c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
648c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&orientation, sizeof(orientation), 1, inv_data_builder.file);
649c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&sensitivity, sizeof(sensitivity), 1, inv_data_builder.file);
650c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
651c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
652c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    set_sensor_orientation_and_scale(&sensors.accel, orientation,
653c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                     sensitivity);
654c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
655c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
656c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets the Orientation and Sensitivity of the gyro data.
657c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] orientation A scalar defining the transformation from chip mounting
658c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            to the body frame. The function inv_orientation_matrix_to_scalar()
659c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            can convert the transformation matrix to this scalar and describes the
660c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            scalar in further detail.
661c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sensitivity A scale factor to convert device units to uT
662c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            such that uT = device_units * sensitivity / 2^30. Typically
663c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            it works out to be the maximum uT_value * 2^15.
664c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
665c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_compass_orientation_and_scale(int orientation, long sensitivity)
666c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
667c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
668c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
669c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_C_ORIENT;
670c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
671c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&orientation, sizeof(orientation), 1, inv_data_builder.file);
672c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&sensitivity, sizeof(sensitivity), 1, inv_data_builder.file);
673c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
674c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
675c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    set_sensor_orientation_and_scale(&sensors.compass, orientation, sensitivity);
676c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
677c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
678c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_matrix_vector_mult(const long *A, const long *x, long *y)
679c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
680c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    y[0] = inv_q30_mult(A[0], x[0]) + inv_q30_mult(A[1], x[1]) + inv_q30_mult(A[2], x[2]);
681c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    y[1] = inv_q30_mult(A[3], x[0]) + inv_q30_mult(A[4], x[1]) + inv_q30_mult(A[5], x[2]);
682c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    y[2] = inv_q30_mult(A[6], x[0]) + inv_q30_mult(A[7], x[1]) + inv_q30_mult(A[8], x[2]);
683c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
684c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
685c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Takes raw data stored in the sensor, removes bias, and converts it to
686c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* calibrated data in the body frame. Also store raw data for body frame.
687c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in,out] sensor structure to modify
688c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] bias bias in the mounting frame, in hardware units scaled by
689c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*                 2^16. Length 3.
690c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
691c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_apply_calibration(struct inv_single_sensor_t *sensor, const long *bias)
692c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
693c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long raw32[3];
694c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
695c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Convert raw to calibrated
696c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    raw32[0] = (long)sensor->raw[0] << 15;
697c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    raw32[1] = (long)sensor->raw[1] << 15;
698c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    raw32[2] = (long)sensor->raw[2] << 15;
699c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
700c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_convert_to_body_with_scale(sensor->orientation, sensor->sensitivity << 1, raw32, sensor->raw_scaled);
701c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
702c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    raw32[0] -= bias[0] >> 1;
703c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    raw32[1] -= bias[1] >> 1;
704c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    raw32[2] -= bias[2] >> 1;
705c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
706c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_convert_to_body_with_scale(sensor->orientation, sensor->sensitivity << 1, raw32, sensor->calibrated);
707c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
708c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensor->status |= INV_CALIBRATED;
709c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
710c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
711c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Returns the current bias for the compass
712c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] bias Compass bias in hardware units scaled by 2^16. In mounting frame.
713c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*             Length 3.
714c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
715c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_compass_bias(long *bias)
716c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
717c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias != NULL) {
718c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(bias, inv_data_builder.save.compass_bias, sizeof(inv_data_builder.save.compass_bias));
719c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
720c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
721c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
722c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets the compass bias
723c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] bias Length 3, in body frame, in hardware units scaled by 2^16 to allow fractional bit correction.
724c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] accuracy Accuracy of compass data, where 3=most accurate, and 0=least accurate.
725c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
726c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_compass_bias(const long *bias, int accuracy)
727c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
728c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (memcmp(inv_data_builder.save.compass_bias, bias, sizeof(inv_data_builder.save.compass_bias))) {
729c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(inv_data_builder.save.compass_bias, bias, sizeof(inv_data_builder.save.compass_bias));
730c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_apply_calibration(&sensors.compass, inv_data_builder.save.compass_bias);
731c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
732c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.accuracy = accuracy;
733c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.save.compass_accuracy = accuracy;
734c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_set_message(INV_MSG_NEW_CB_EVENT, INV_MSG_NEW_CB_EVENT, 0);
735c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
736c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
737c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Set the state of a compass disturbance
738c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] dist 1=disturbance, 0=no disturbance
739c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
740c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_compass_disturbance(int dist)
741c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
742c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.compass_disturbance = dist;
743c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
744c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
745c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_compass_disturbance(void) {
746c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return inv_data_builder.compass_disturbance;
747c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
748c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
749c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
750c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  Sets the factory accel bias
751c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in] bias
752c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *               Accel bias in hardware units (+/- 2 gee full scale assumed)
753c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *               scaled by 2^16. In chip mounting frame. Length of 3.
754c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
755c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_accel_bias(const long *bias)
756c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
757c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (!bias)
758c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return;
759c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
760c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (memcmp(inv_data_builder.save.factory_accel_bias, bias,
761c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               sizeof(inv_data_builder.save.factory_accel_bias))) {
762c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(inv_data_builder.save.factory_accel_bias, bias,
763c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               sizeof(inv_data_builder.save.factory_accel_bias));
764c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
765c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_set_message(INV_MSG_NEW_FAB_EVENT, INV_MSG_NEW_FAB_EVENT, 0);
766c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
767c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
768c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets the accel accuracy.
769c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] accuracy Accuracy rating from 0 to 3, with 3 being most accurate.
770c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
771c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_accel_accuracy(int accuracy)
772c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
773c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.accuracy = accuracy;
774c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.save.accel_accuracy = accuracy;
775c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
776c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
777c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets the accel bias with control over which axis.
778c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] bias Accel bias, length 3. In HW units scaled by 2^16 in body frame
779c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] accuracy Accuracy rating from 0 to 3, with 3 being most accurate.
780c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] mask Mask to select axis to apply bias set.
781c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
782c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_accel_bias_mask(const long *bias, int accuracy, int mask)
783c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
784c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias) {
785c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (mask & 1){
786c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            inv_data_builder.save_accel_mpl.accel_bias[0] = bias[0];
787c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
788c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (mask & 2){
789c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            inv_data_builder.save_accel_mpl.accel_bias[1] = bias[1];
790c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
791c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (mask & 4){
792c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            inv_data_builder.save_accel_mpl.accel_bias[2] = bias[2];
793c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
794c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
795c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_apply_calibration(&sensors.accel, inv_data_builder.save_accel_mpl.accel_bias);
796c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
797c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_set_accel_accuracy(accuracy);
798c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_set_message(INV_MSG_NEW_AB_EVENT, INV_MSG_NEW_AB_EVENT, 0);
799c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
800c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
801c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef WIN32
802c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sends out a message to activate writing 9-axis quaternion to the DMP.
803c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
804c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_overwrite_dmp_9quat(void)
805c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
806c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_set_message(INV_MSG_NEW_DMP_QUAT_WRITE_EVENT, INV_MSG_NEW_DMP_QUAT_WRITE_EVENT, 0);
807c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
808c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
809c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
810c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
811c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  Sets the factory gyro bias
812c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in] bias
813c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *               Gyro bias in hardware units (+/- 2000 dps full scale assumed)
814c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *               scaled by 2^16. In chip mounting frame. Length of 3.
815c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
816c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_gyro_bias(const long *bias)
817c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
818c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (!bias)
819c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return;
820c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
821c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (memcmp(inv_data_builder.save.factory_gyro_bias, bias,
822c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               sizeof(inv_data_builder.save.factory_gyro_bias))) {
823c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(inv_data_builder.save.factory_gyro_bias, bias,
824c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               sizeof(inv_data_builder.save.factory_gyro_bias));
825c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
826c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_set_message(INV_MSG_NEW_FGB_EVENT, INV_MSG_NEW_FGB_EVENT, 0);
827c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
828c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
829c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
830c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  Sets the mpl gyro bias
831c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in] bias
832c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              Gyro bias in hardware units scaled by 2^16  (+/- 2000 dps full
833c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              scale assumed). In chip mounting frame. Length 3.
834c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in] accuracy
835c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              Accuracy of bias. 0 = least accurate, 3 = most accurate.
836c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
837c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_mpl_gyro_bias(const long *bias, int accuracy)
838c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
839c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias != NULL) {
840c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (memcmp(inv_data_builder.save_mpl.gyro_bias, bias,
841c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                   sizeof(inv_data_builder.save_mpl.gyro_bias))) {
842c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            memcpy(inv_data_builder.save_mpl.gyro_bias, bias,
843c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                   sizeof(inv_data_builder.save_mpl.gyro_bias));
844c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            inv_apply_calibration(&sensors.gyro,
845c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                  inv_data_builder.save_mpl.gyro_bias);
846c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
847c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
848c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.accuracy = accuracy;
849c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.save.gyro_accuracy = accuracy;
850c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
851c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /* TODO: What should we do if there's no temperature data? */
852c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.temp.calibrated[0])
853c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.save.gyro_temp = sensors.temp.calibrated[0];
854c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    else
855c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        /* Set to 27 deg C for now until we've got a better solution. */
856c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.save.gyro_temp = 27L << 16;
857c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_set_message(INV_MSG_NEW_GB_EVENT, INV_MSG_NEW_GB_EVENT, 0);
858c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
859c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /* TODO: this flag works around the synchronization problem seen with using
860c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       the user-exposed message layer to signal the temperature compensation
861c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       module that gyro biases were set.
862c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro       A better, cleaner method is certainly needed. */
863c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.save.gyro_bias_tc_set = true;
864c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
865c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
866c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
867c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @internal
868c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @brief  Return whether gyro biases were set to signal the temperature
869c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *          compensation algorithm that it can collect a data point to build
870c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *          the temperature slope while in no motion state.
871c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *          The flag clear automatically after is read.
872c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @return true if the flag was set, indicating gyro biases were set.
873c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *          false if the flag was not set.
874c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
875c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_gyro_bias_tc_set(void)
876c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
877c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int flag = (inv_data_builder.save.gyro_bias_tc_set == true);
878c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.save.gyro_bias_tc_set = false;
879c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return flag;
880c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
881c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
882c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
883c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
884c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  Get the mpl gyro biases
885c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in] bias
886c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              Gyro calibrated bias.
887c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              Length 3.
888c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
889c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_mpl_gyro_bias(long *bias, long *temp)
890c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
891c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias != NULL)
892c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(bias, inv_data_builder.save_mpl.gyro_bias,
893c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               sizeof(inv_data_builder.save_mpl.gyro_bias));
894c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
895c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (temp != NULL)
896c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        temp[0] = inv_data_builder.save.gyro_temp;
897c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
898c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
899c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gyro Bias in the form used by the DMP.
900c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] bias Gyro Bias in the form used by the DMP. It is scaled appropriately
901c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*             and is in the body frame as needed. If this bias is applied in the DMP
902c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*             then any quaternion must have the flag INV_BIAS_APPLIED set if it is a
903c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*             3-axis quaternion, or INV_QUAT_6AXIS if it is a 6-axis quaternion
904c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
905c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_gyro_bias_dmp_units(long *bias)
906c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
907c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias == NULL)
908c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return;
909c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_convert_to_body_with_scale(sensors.gyro.orientation, 46850825L,
910c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                   inv_data_builder.save_mpl.gyro_bias, bias);
911c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
912c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
913c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/* TODO: Add this information to inv_sensor_cal_t */
914c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
915c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  Get the gyro biases and temperature record from MPL
916c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in] bias
917c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              Gyro bias in hardware units scaled by 2^16.
918c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              In chip mounting frame.
919c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *              Length 3.
920c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
921c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_gyro_bias(long *bias)
922c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
923c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias != NULL)
924c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(bias, inv_data_builder.save.factory_gyro_bias,
925c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               sizeof(inv_data_builder.save.factory_gyro_bias));
926c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
927c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
928c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
929c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * Get factory accel bias mask
930c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] bias
931c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             Accel bias mask
932c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             1 is set, 0 is not set, Length 3 = x,y,z.
933c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
934c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_factory_accel_bias_mask()
935c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
936c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    long bias[3];
937c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	int bias_mask = 0;
938c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_get_accel_bias(bias);
939c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias != NULL) {
940c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int i;
941c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        for(i = 0; i < 3; i++) {
942c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if(bias[i] != 0) {
943c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                bias_mask |= 1 << i;
944c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			} else {
945c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                bias_mask &= ~ (1 << i);
946c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro			}
947c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
948c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
949c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro	return bias_mask;
950c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
951c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
952c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
953c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * Get accel bias from MPL
954c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] bias
955c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             Accel bias in hardware units scaled by 2^16.
956c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             In chp mounting frame.
957c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *             Length 3.
958c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
959c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_accel_bias(long *bias)
960c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
961c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias != NULL)
962c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(bias, inv_data_builder.save.factory_accel_bias,
963c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               sizeof(inv_data_builder.save.factory_accel_bias));
964c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
965c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
966c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Get Accel Bias
967c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] bias Accel bias
968c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] temp Temperature where 1 C = 2^16
969c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
970c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_mpl_accel_bias(long *bias, long *temp)
971c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
972c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias != NULL)
973c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(bias, inv_data_builder.save_accel_mpl.accel_bias,
974c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro               sizeof(inv_data_builder.save_accel_mpl.accel_bias));
975c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (temp != NULL)
976c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        temp[0] = inv_data_builder.save.accel_temp;
977c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
978c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
979c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Accel Bias in the form used by the DMP.
980c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] bias Accel Bias in the form used by the DMP. It is scaled appropriately
981c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*             and is in the body frame as needed.
982c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
983c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_accel_bias_dmp_units(long *bias)
984c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
985c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (bias == NULL)
986c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return;
987c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_convert_to_body_with_scale(sensors.accel.orientation, 536870912L,
988c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                                   inv_data_builder.save_accel_mpl.accel_bias, bias);
989c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
990c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
991c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
992c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  Record new accel data for use when inv_execute_on_data() is called
993c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in]  accel
994c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                accel data, length 3.
995c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                Calibrated data is in m/s^2 scaled by 2^16 in body frame.
996c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                Raw data is in device units in chip mounting frame.
997c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in]  status
998c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                Lower 2 bits are the accuracy, with 0 being inaccurate, and 3
999c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                being most accurate.
1000c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                The upper bit INV_CALIBRATED, is set if the data was calibrated
1001c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                outside MPL and it is not set if the data being passed is raw.
1002c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                Raw data should be in device units, typically in a 16-bit range.
1003c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in]  timestamp
1004c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                Monotonic time stamp, for Android it's in nanoseconds.
1005c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @return     Returns INV_SUCCESS if successful or an error code if not.
1006c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
1007c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_build_accel(const long *accel, int status, inv_time_t timestamp)
1008c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1009c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1010c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1011c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_ACCEL;
1012c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1013c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(accel, sizeof(accel[0]), 3, inv_data_builder.file);
1014c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&timestamp, sizeof(timestamp), 1, inv_data_builder.file);
1015c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1016c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1017c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1018c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((status & INV_CALIBRATED) == 0) {
1019c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.raw[0] = (short)accel[0];
1020c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.raw[1] = (short)accel[1];
1021c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.raw[2] = (short)accel[2];
1022c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.status |= INV_RAW_DATA;
1023c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_apply_calibration(&sensors.accel, inv_data_builder.save_accel_mpl.accel_bias);
1024c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
1025c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.calibrated[0] = accel[0];
1026c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.calibrated[1] = accel[1];
1027c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.calibrated[2] = accel[2];
1028c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.status |= INV_CALIBRATED;
1029c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.accuracy = status & 3;
1030c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.save.accel_accuracy = status & 3;
1031c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1032c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.status |= INV_NEW_DATA | INV_SENSOR_ON;
1033c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.timestamp_prev = sensors.accel.timestamp;
1034c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.timestamp = timestamp;
1035c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1036c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
1037c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1038c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1039c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Record new gyro data and calls inv_execute_on_data() if previous
1040c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* sample has not been processed.
1041c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] gyro Data is in device units. Length 3.
1042c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] timestamp Monotonic time stamp, for Android it's in nanoseconds.
1043c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] executed Set to 1 if data processing was done.
1044c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns INV_SUCCESS if successful or an error code if not.
1045c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1046c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_build_gyro(const short *gyro, inv_time_t timestamp)
1047c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1048c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1049c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1050c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_GYRO;
1051c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1052c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(gyro, sizeof(gyro[0]), 3, inv_data_builder.file);
1053c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&timestamp, sizeof(timestamp), 1, inv_data_builder.file);
1054c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1055c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1056c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1057c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(sensors.gyro.raw, gyro, 3 * sizeof(short));
1058c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.status |= INV_NEW_DATA | INV_RAW_DATA | INV_SENSOR_ON;
1059c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.timestamp_prev = sensors.gyro.timestamp;
1060c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.timestamp = timestamp;
1061c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_apply_calibration(&sensors.gyro, inv_data_builder.save_mpl.gyro_bias);
1062c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1063c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
1064c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1065c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1066c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Record new compass data for use when inv_execute_on_data() is called
1067c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] compass Compass data, if it was calibrated outside MPL, the units are uT scaled by 2^16.
1068c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            Length 3.
1069c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] status Lower 2 bits are the accuracy, with 0 being inaccurate, and 3 being most accurate.
1070c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            The upper bit INV_CALIBRATED, is set if the data was calibrated outside MPL and it is
1071c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            not set if the data being passed is raw. Raw data should be in device units, typically
1072c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            in a 16-bit range.
1073c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] timestamp Monotonic time stamp, for Android it's in nanoseconds.
1074c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] executed Set to 1 if data processing was done.
1075c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns INV_SUCCESS if successful or an error code if not.
1076c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1077c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_build_compass(const long *compass, int status,
1078c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                              inv_time_t timestamp)
1079c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1080c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1081c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1082c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_COMPASS;
1083c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1084c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(compass, sizeof(compass[0]), 3, inv_data_builder.file);
1085c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&timestamp, sizeof(timestamp), 1, inv_data_builder.file);
1086c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1087c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1088c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1089c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if ((status & INV_CALIBRATED) == 0) {
1090c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        long data[3];
1091c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_set_compass_soft_iron_input_data(compass);
1092c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_get_compass_soft_iron_output_data(data);
1093c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.raw[0] = (short)data[0];
1094c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.raw[1] = (short)data[1];
1095c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.raw[2] = (short)data[2];
1096c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_apply_calibration(&sensors.compass, inv_data_builder.save.compass_bias);
1097c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.status |= INV_RAW_DATA;
1098c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
1099c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.calibrated[0] = compass[0];
1100c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.calibrated[1] = compass[1];
1101c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.calibrated[2] = compass[2];
1102c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.status |= INV_CALIBRATED;
1103c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.accuracy = status & 3;
1104c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.save.compass_accuracy = status & 3;
1105c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1106c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.timestamp_prev = sensors.compass.timestamp;
1107c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.timestamp = timestamp;
1108c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.status |= INV_NEW_DATA | INV_SENSOR_ON;
1109c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1110c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
1111c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1112c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1113c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Record new temperature data for use when inv_execute_on_data() is called.
1114c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in]  temp Temperature data in q16 format.
1115c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[in]  timestamp   Monotonic time stamp; for Android it's in
1116c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *                          nanoseconds.
1117c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns INV_SUCCESS if successful or an error code if not.
1118c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
1119c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_build_temp(const long temp, inv_time_t timestamp)
1120c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1121c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1122c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1123c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_TEMPERATURE;
1124c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1125c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&temp, sizeof(temp), 1, inv_data_builder.file);
1126c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&timestamp, sizeof(timestamp), 1, inv_data_builder.file);
1127c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1128c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1129c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.temp.calibrated[0] = temp;
1130c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.temp.status |= INV_NEW_DATA | INV_RAW_DATA | INV_SENSOR_ON;
1131c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.temp.timestamp_prev = sensors.temp.timestamp;
1132c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.temp.timestamp = timestamp;
1133c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /* TODO: Apply scale, remove offset. */
1134c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1135c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
1136c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1137c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** quaternion data
1138c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] quat Quaternion data. 2^30 = 1.0 or 2^14=1 for 16-bit data.
1139c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*                 Real part first. Length 4.
1140c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] status number of axis, 16-bit or 32-bit
1141c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            set INV_QUAT_3ELEMENT if input quaternion has only 3 elements (no scalar).
1142c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            inv_compute_scalar_part() assumes 32-bit data.  If using 16-bit quaternion,
1143c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            shift 16 bits first before calling this function.
1144c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] timestamp
1145c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in]  timestamp   Monotonic time stamp; for Android it's in
1146c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*                         nanoseconds.
1147c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] executed Set to 1 if data processing was done.
1148c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns INV_SUCCESS if successful or an error code if not.
1149c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1150c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_build_quat(const long *quat, int status, inv_time_t timestamp)
1151c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1152c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1153c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1154c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_QUAT;
1155c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1156c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(quat, sizeof(quat[0]), 4, inv_data_builder.file);
1157c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&timestamp, sizeof(timestamp), 1, inv_data_builder.file);
1158c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1159c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1160c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1161c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /* Android version DMP does not have scalar part */
1162c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (status & INV_QUAT_3ELEMENT) {
1163c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        long resultQuat[4];
1164c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        MPL_LOGV("3q: %ld,%ld,%ld\n", quat[0], quat[1], quat[2]);
1165c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_compute_scalar_part(quat, resultQuat);
1166c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        MPL_LOGV("4q: %ld,%ld,%ld,%ld\n", resultQuat[0], resultQuat[1], resultQuat[2], resultQuat[3]);
1167c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(sensors.quat.raw, resultQuat, sizeof(sensors.quat.raw));
1168c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
1169c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(sensors.quat.raw, quat, sizeof(sensors.quat.raw));
1170c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1171c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.timestamp_prev = sensors.quat.timestamp;
1172c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.timestamp = timestamp;
1173c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status |= INV_NEW_DATA | INV_RAW_DATA | INV_SENSOR_ON;
1174c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status |= (INV_QUAT_3AXIS & status);
1175c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status |= (INV_QUAT_6AXIS & status);
1176c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status |= (INV_QUAT_9AXIS & status);
1177c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status |= (INV_BIAS_APPLIED & status);
1178c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status |= (INV_DMP_BIAS_APPLIED & status);
1179c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status |= (INV_QUAT_3ELEMENT & status);
1180c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    MPL_LOGV("quat.status: %d", sensors.quat.status);
1181c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.quat.status & (INV_QUAT_9AXIS | INV_QUAT_6AXIS)) {
1182c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // Set quaternion
1183c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_store_gaming_quaternion(quat, timestamp);
1184c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1185c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.quat.status & INV_QUAT_9AXIS) {
1186c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        long identity[4] = {(1L<<30), 0, 0, 0};
1187c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_set_compass_correction(identity, timestamp);
1188c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1189c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
1190c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1191c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1192c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_build_pressure(const long pressure, int status, inv_time_t timestamp)
1193c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1194c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.pressure.status |= INV_NEW_DATA;
1195c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;
1196c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1197c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1198c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This should be called when the accel has been turned off. This is so
1199c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* that we will know if the data is contiguous.
1200c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1201c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_accel_was_turned_off()
1202c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1203c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1204c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1205c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_COMPASS_OFF;
1206c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1207c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1208c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1209c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.status = 0;
1210c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1211c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1212c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This should be called when the compass has been turned off. This is so
1213c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* that we will know if the data is contiguous.
1214c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1215c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_compass_was_turned_off()
1216c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1217c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1218c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1219c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_COMPASS_OFF;
1220c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1221c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1222c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1223c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.status = 0;
1224c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1225c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1226c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This should be called when the quaternion data from the DMP has been turned off. This is so
1227c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* that we will know if the data is contiguous.
1228c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1229c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_quaternion_sensor_was_turned_off(void)
1230c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1231c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1232c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1233c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_QUAT_OFF;
1234c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1235c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1236c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1237c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status = 0;
1238c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1239c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1240c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This should be called when the gyro has been turned off. This is so
1241c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* that we will know if the data is contiguous.
1242c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1243c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_gyro_was_turned_off()
1244c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1245c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1246c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1247c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_GYRO_OFF;
1248c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1249c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1250c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1251c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.status = 0;
1252c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1253c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1254c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This should be called when the temperature sensor has been turned off.
1255c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  This is so that we will know if the data is contiguous.
1256c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
1257c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_temperature_was_turned_off()
1258c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1259c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.temp.status = 0;
1260c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1261c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1262c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Registers to receive a callback when there is new sensor data.
1263c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @internal
1264c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] func Function pointer to receive callback when there is new sensor data
1265c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] priority Lower priority numbers receive a callback before larger numbers. All priority
1266c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            numbers must be unique.
1267c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sensor_type Sets the type of data that triggers the callback. Must be non-zero. May be
1268c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            a combination. INV_ACCEL_NEW = accel data, INV_GYRO_NEW =
1269c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            gyro data, INV_MAG_NEW = compass data. So passing in
1270c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            INV_ACCEL_NEW | INV_MAG_NEW, a
1271c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            callback would be generated if there was new magnetomer data OR new accel data.
1272c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1273c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_register_data_cb(
1274c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_error_t (*func)(struct inv_sensor_cal_t *data),
1275c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int priority, int sensor_type)
1276c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1277c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_error_t result = INV_SUCCESS;
1278c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int kk, nn;
1279c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1280c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Make sure we haven't registered this function already
1281c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Or used the same priority
1282c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (kk = 0; kk < inv_data_builder.num_cb; ++kk) {
1283c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if ((inv_data_builder.process[kk].func == func) ||
1284c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                (inv_data_builder.process[kk].priority == priority)) {
1285c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            return INV_ERROR_INVALID_PARAMETER;    //fixme give a warning
1286c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
1287c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1288c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1289c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Make sure we have not filled up our number of allowable callbacks
1290c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.num_cb <= INV_MAX_DATA_CB - 1) {
1291c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        kk = 0;
1292c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (inv_data_builder.num_cb != 0) {
1293c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            // set kk to be where this new callback goes in the array
1294c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            while ((kk < inv_data_builder.num_cb) &&
1295c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                    (inv_data_builder.process[kk].priority < priority)) {
1296c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                kk++;
1297c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            }
1298c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (kk != inv_data_builder.num_cb) {
1299c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                // We need to move the others
1300c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                for (nn = inv_data_builder.num_cb; nn > kk; --nn) {
1301c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                    inv_data_builder.process[nn] =
1302c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                        inv_data_builder.process[nn - 1];
1303c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                }
1304c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            }
1305c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
1306c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // Add new callback
1307c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.process[kk].func = func;
1308c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.process[kk].priority = priority;
1309c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.process[kk].data_required = sensor_type;
1310c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.num_cb++;
1311c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
1312c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        MPL_LOGE("Unable to add feature callback as too many were already registered\n");
1313c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        result = INV_ERROR_MEMORY_EXAUSTED;
1314c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1315c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1316c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return result;
1317c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1318c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1319c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Unregisters the callback that happens when new sensor data is received.
1320c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @internal
1321c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] func Function pointer to receive callback when there is new sensor data
1322c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] priority Lower priority numbers receive a callback before larger numbers. All priority
1323c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            numbers must be unique.
1324c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[in] sensor_type Sets the type of data that triggers the callback. Must be non-zero. May be
1325c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            a combination. INV_ACCEL_NEW = accel data, INV_GYRO_NEW =
1326c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            gyro data, INV_MAG_NEW = compass data. So passing in
1327c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            INV_ACCEL_NEW | INV_MAG_NEW, a
1328c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*            callback would be generated if there was new magnetomer data OR new accel data.
1329c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1330c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_unregister_data_cb(
1331c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_error_t (*func)(struct inv_sensor_cal_t *data))
1332c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1333c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int kk, nn;
1334c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1335c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (kk = 0; kk < inv_data_builder.num_cb; ++kk) {
1336c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (inv_data_builder.process[kk].func == func) {
1337c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            // Delete this callback
1338c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            for (nn = kk + 1; nn < inv_data_builder.num_cb; ++nn) {
1339c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                inv_data_builder.process[nn - 1] =
1340c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                    inv_data_builder.process[nn];
1341c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            }
1342c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            inv_data_builder.num_cb--;
1343c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            return INV_SUCCESS;
1344c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
1345c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1346c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1347c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return INV_SUCCESS;    // We did not find the callback
1348c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1349c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1350c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** After at least one of inv_build_gyro(), inv_build_accel(), or
1351c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* inv_build_compass() has been called, this function should be called.
1352c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* It will process the data it has received and update all the internal states
1353c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* and features that have been turned on.
1354c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @return Returns INV_SUCCESS if successful or an error code if not.
1355c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1356c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_execute_on_data(void)
1357c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1358c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_error_t result, first_error;
1359c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int kk;
1360c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1361c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#ifdef INV_PLAYBACK_DBG
1362c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.debug_mode == RD_RECORD) {
1363c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        int type = PLAYBACK_DBG_TYPE_EXECUTE;
1364c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        fwrite(&type, sizeof(type), 1, inv_data_builder.file);
1365c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1366c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1367c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    // Determine what new data we have
1368c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_data_builder.mode = 0;
1369c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.gyro.status & INV_NEW_DATA)
1370c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.mode |= INV_GYRO_NEW;
1371c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.accel.status & INV_NEW_DATA)
1372c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.mode |= INV_ACCEL_NEW;
1373c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.compass.status & INV_NEW_DATA)
1374c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.mode |= INV_MAG_NEW;
1375c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.temp.status & INV_NEW_DATA)
1376c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.mode |= INV_TEMP_NEW;
1377c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.quat.status & INV_NEW_DATA)
1378c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.mode |= INV_QUAT_NEW;
1379c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.pressure.status & INV_NEW_DATA)
1380c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_data_builder.mode |= INV_PRESSURE_NEW;
1381c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1382c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    first_error = INV_SUCCESS;
1383c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1384c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (kk = 0; kk < inv_data_builder.num_cb; ++kk) {
1385c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (inv_data_builder.mode & inv_data_builder.process[kk].data_required) {
1386c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            result = inv_data_builder.process[kk].func(&sensors);
1387c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            if (result && !first_error) {
1388c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro                first_error = result;
1389c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            }
1390c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
1391c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1392c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1393c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_set_contiguous();
1394c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1395c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return first_error;
1396c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1397c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1398c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Cleans up status bits after running all the callbacks. It sets the contiguous flag.
1399c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*
1400c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1401c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarostatic void inv_set_contiguous(void)
1402c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1403c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_time_t current_time = 0;
1404c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.gyro.status & INV_NEW_DATA) {
1405c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.gyro.status |= INV_CONTIGUOUS;
1406c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        current_time = sensors.gyro.timestamp;
1407c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1408c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.accel.status & INV_NEW_DATA) {
1409c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.accel.status |= INV_CONTIGUOUS;
1410c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        current_time = MAX(current_time, sensors.accel.timestamp);
1411c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1412c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.compass.status & INV_NEW_DATA) {
1413c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.compass.status |= INV_CONTIGUOUS;
1414c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        current_time = MAX(current_time, sensors.compass.timestamp);
1415c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1416c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.temp.status & INV_NEW_DATA) {
1417c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.temp.status |= INV_CONTIGUOUS;
1418c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        current_time = MAX(current_time, sensors.temp.timestamp);
1419c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1420c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.quat.status & INV_NEW_DATA) {
1421c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.quat.status |= INV_CONTIGUOUS;
1422c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        current_time = MAX(current_time, sensors.quat.timestamp);
1423c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1424c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1425c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#if 0
1426c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /* See if sensors are still on. These should be turned off by inv_*_was_turned_off()
1427c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro     * type functions. This is just in case that breaks down. We make sure
1428c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro     * all the data is within 2 seconds of the newest piece of data*/
1429c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_delta_time_ms(current_time, sensors.gyro.timestamp) >= 2000)
1430c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_gyro_was_turned_off();
1431c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_delta_time_ms(current_time, sensors.accel.timestamp) >= 2000)
1432c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_accel_was_turned_off();
1433c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_delta_time_ms(current_time, sensors.compass.timestamp) >= 2000)
1434c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_compass_was_turned_off();
1435c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /* TODO: Temperature might not need to be read this quickly. */
1436c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_delta_time_ms(current_time, sensors.temp.timestamp) >= 2000)
1437c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        inv_temperature_was_turned_off();
1438c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro#endif
1439c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1440c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    /* clear bits */
1441c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.gyro.status &= ~INV_NEW_DATA;
1442c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.accel.status &= ~INV_NEW_DATA;
1443c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.compass.status &= ~INV_NEW_DATA;
1444c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.temp.status &= ~INV_NEW_DATA;
1445c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.quat.status &= ~INV_NEW_DATA;
1446c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.pressure.status &= ~INV_NEW_DATA;
1447c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1448c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1449c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets a whole set of accel data including data, accuracy and timestamp.
1450c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] data Accel Data where 1g = 2^16
1451c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] accuracy Accuracy 0 being not accurate, and 3 being most accurate.
1452c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] timestamp The timestamp of the data sample.
1453c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1454c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_accel_set(long *data, int8_t *accuracy, inv_time_t *timestamp)
1455c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1456c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (data != NULL) {
1457c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        memcpy(data, sensors.accel.calibrated, sizeof(sensors.accel.calibrated));
1458c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1459c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (timestamp != NULL) {
1460c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *timestamp = sensors.accel.timestamp;
1461c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1462c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (accuracy != NULL) {
1463c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *accuracy = sensors.accel.accuracy;
1464c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1465c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1466c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1467c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets a whole set of gyro data including data, accuracy and timestamp.
1468c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] data Gyro Data where 1 dps = 2^16
1469c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] accuracy Accuracy 0 being not accurate, and 3 being most accurate.
1470c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] timestamp The timestamp of the data sample.
1471c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1472c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_gyro_set(long *data, int8_t *accuracy, inv_time_t *timestamp)
1473c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1474c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(data, sensors.gyro.calibrated, sizeof(sensors.gyro.calibrated));
1475c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (timestamp != NULL) {
1476c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *timestamp = sensors.gyro.timestamp;
1477c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1478c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (accuracy != NULL) {
1479c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *accuracy = sensors.gyro.accuracy;
1480c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1481c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1482c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1483c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets a whole set of gyro raw data including data, accuracy and timestamp.
1484c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] data Gyro Data where 1 dps = 2^16
1485c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] accuracy Accuracy 0 being not accurate, and 3 being most accurate.
1486c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] timestamp The timestamp of the data sample.
1487c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1488c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_gyro_set_raw(long *data, int8_t *accuracy, inv_time_t *timestamp)
1489c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1490c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(data, sensors.gyro.raw_scaled, sizeof(sensors.gyro.raw_scaled));
1491c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (timestamp != NULL) {
1492c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *timestamp = sensors.gyro.timestamp;
1493c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1494c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (accuracy != NULL) {
1495c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *accuracy = 0;
1496c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1497c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1498c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1499c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Get's latest gyro data.
1500c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro* @param[out] gyro Gyro Data, Length 3. 1 dps = 2^16.
1501c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1502c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_gyro(long *gyro)
1503c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1504c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(gyro, sensors.gyro.calibrated, sizeof(sensors.gyro.calibrated));
1505c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1506c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1507c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets a whole set of compass data including data, accuracy and timestamp.
1508c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] data Compass Data where 1 uT = 2^16
1509c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] accuracy Accuracy 0 being not accurate, and 3 being most accurate.
1510c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] timestamp The timestamp of the data sample.
1511c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1512c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_compass_set(long *data, int8_t *accuracy, inv_time_t *timestamp)
1513c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1514c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(data, sensors.compass.calibrated, sizeof(sensors.compass.calibrated));
1515c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (timestamp != NULL) {
1516c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *timestamp = sensors.compass.timestamp;
1517c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1518c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (accuracy != NULL) {
1519c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        if (inv_data_builder.compass_disturbance)
1520c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            *accuracy = 0;
1521c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        else
1522c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            *accuracy = sensors.compass.accuracy;
1523c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1524c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1525c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1526c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets a whole set of compass raw data including data, accuracy and timestamp.
1527c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] data Compass Data where 1 uT = 2^16
1528c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] accuracy Accuracy 0 being not accurate, and 3 being most accurate.
1529c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] timestamp The timestamp of the data sample.
1530c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1531c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_compass_set_raw(long *data, int8_t *accuracy, inv_time_t *timestamp)
1532c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1533c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memcpy(data, sensors.compass.raw_scaled, sizeof(sensors.compass.raw_scaled));
1534c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (timestamp != NULL) {
1535c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *timestamp = sensors.compass.timestamp;
1536c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1537c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    //per Michele, since data is raw, accuracy should = 0
1538c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    *accuracy = 0;
1539c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1540c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1541c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets a whole set of temperature data including data, accuracy and timestamp.
1542c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[out] data        Temperature data where 1 degree C = 2^16
1543c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[out] accuracy    0 to 3, where 3 is most accurate.
1544c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro *  @param[out] timestamp   The timestamp of the data sample.
1545c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
1546c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_temp_set(long *data, int *accuracy, inv_time_t *timestamp)
1547c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1548c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    data[0] = sensors.temp.calibrated[0];
1549c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (timestamp)
1550c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *timestamp = sensors.temp.timestamp;
1551c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (accuracy)
1552c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        *accuracy = sensors.temp.accuracy;
1553c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1554c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1555c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Returns accuracy of gyro.
1556c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return Accuracy of gyro with 0 being not accurate, and 3 being most accurate.
1557c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1558c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_gyro_accuracy(void)
1559c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1560c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return sensors.gyro.accuracy;
1561c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1562c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1563c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Returns accuracy of compass.
1564c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return Accuracy of compass with 0 being not accurate, and 3 being most accurate.
1565c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1566c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_mag_accuracy(void)
1567c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1568c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (inv_data_builder.compass_disturbance)
1569c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        return 0;
1570c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return sensors.compass.accuracy;
1571c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1572c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1573c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Returns accuracy of accel.
1574c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @return Accuracy of accel with 0 being not accurate, and 3 being most accurate.
1575c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1576c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroint inv_get_accel_accuracy(void)
1577c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1578c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return sensors.accel.accuracy;
1579c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1580c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1581c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_get_gyro_orient(int *orient)
1582c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1583c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    *orient = sensors.gyro.orientation;
1584c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return 0;
1585c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1586c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1587c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaroinv_error_t inv_get_accel_orient(int *orient)
1588c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro{
1589c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    *orient = sensors.accel.orientation;
1590c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    return 0;
1591c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1592c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1593c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/*======================================================================*/
1594c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/*   compass soft iron module                                           */
1595c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/*======================================================================*/
1596c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1597c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets the 3x3 compass transform matrix in 32 bit Q30 fixed point format.
1598c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] the pointer of the 3x3 matrix in Q30 format
1599c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1600c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_compass_soft_iron_matrix_d(long *matrix) {
1601c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
1602c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<9; i++)  {
1603c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        matrix[i] = sensors.soft_iron.matrix_d[i];
1604c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1605c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1606c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1607c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets the 3x3 compass transform matrix in 32 bit Q30 fixed point format.
1608c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] the pointer of the 3x3 matrix in Q30 format
1609c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1610c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_compass_soft_iron_matrix_d(long *matrix)  {
1611c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
1612c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<9; i++)  {
1613c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // set the floating point matrix
1614c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.soft_iron.matrix_d[i] = matrix[i];
1615c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // convert to Q30 format
1616c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.soft_iron.matrix_f[i] = inv_q30_to_float(matrix[i]);
1617c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1618c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1619c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Gets the 3x3 compass transform matrix in 32 bit floating point format.
1620c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] the pointer of the 3x3 matrix in floating point format
1621c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1622c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_compass_soft_iron_matrix_f(float *matrix)  {
1623c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
1624c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<9; i++)  {
1625c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        matrix[i] = sensors.soft_iron.matrix_f[i];
1626c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1627c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1628c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** Sets the 3x3 compass transform matrix in 32 bit floating point format.
1629c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[in] the pointer of the 3x3 matrix in floating point format
1630c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1631c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_compass_soft_iron_matrix_f(float *matrix)   {
1632c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
1633c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<9; i++)  {
1634c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // set the floating point matrix
1635c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.soft_iron.matrix_f[i] = matrix[i];
1636c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // convert to Q30 format
1637c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.soft_iron.matrix_d[i] = (long )(matrix[i]*ROT_MATRIX_SCALE_LONG);
1638c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1639c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1640c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1641c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This subroutine gets the fixed point Q30 compass data after the soft iron transformation.
1642c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] the pointer of the 3x1 vector compass data in MPL format
1643c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1644c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_compass_soft_iron_output_data(long *data) {
1645c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
1646c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<3; i++)  {
1647c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        data[i] = sensors.soft_iron.trans[i];
1648c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1649c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1650c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This subroutine gets the fixed point Q30 compass data before the soft iron transformation.
1651c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[out] the pointer of the 3x1 vector compass data in MPL format
1652c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1653c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_get_compass_soft_iron_input_data(long *data)  {
1654c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
1655c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<3; i++)  {
1656c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        data[i] = sensors.soft_iron.raw[i];
1657c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1658c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1659c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This subroutine sets the compass raw data for the soft iron transformation.
1660c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @param[int] the pointer of the 3x1 vector compass raw data in MPL format
1661c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1662c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_set_compass_soft_iron_input_data(const long *data)  {
1663c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
1664c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<3; i++)  {
1665c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.soft_iron.raw[i] = data[i];
1666c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1667c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    if (sensors.soft_iron.enable == 1)  {
1668c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        mlMatrixVectorMult(sensors.soft_iron.matrix_d, data, sensors.soft_iron.trans);
1669c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    } else {
1670c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        for (i=0; i<3; i++)  {
1671c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro            sensors.soft_iron.trans[i] = data[i];
1672c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        }
1673c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1674c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1675c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1676c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This subroutine resets the the soft iron transformation to unity matrix and
1677c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * disable the soft iron transformation process by default.
1678c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1679c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_reset_compass_soft_iron_matrix(void)  {
1680c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    int i;
1681c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<9; i++) {
1682c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.soft_iron.matrix_f[i] = 0.0f;
1683c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1684c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1685c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    memset(&sensors.soft_iron.matrix_d,0,sizeof(sensors.soft_iron.matrix_d));
1686c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1687c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    for (i=0; i<3; i++)  {
1688c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // set the floating point matrix
1689c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.soft_iron.matrix_f[i*4] = 1.0;
1690c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        // set the fixed point matrix
1691c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro        sensors.soft_iron.matrix_d[i*4] = ROT_MATRIX_SCALE_LONG;
1692c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    }
1693c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1694c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    inv_disable_compass_soft_iron_matrix();
1695c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1696c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1697c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This subroutine enables the the soft iron transformation process.
1698c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1699c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_enable_compass_soft_iron_matrix(void)   {
1700c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.soft_iron.enable = 1;
1701c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1702c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1703c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/** This subroutine disables the the soft iron transformation process.
1704c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro*/
1705c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccarovoid inv_disable_compass_soft_iron_matrix(void)   {
1706c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro    sensors.soft_iron.enable = 0;
1707c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro}
1708c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro
1709c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro/**
1710c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro * @}
1711c3d4ca9f2df5ddf9894b36d1554fdfc95d625d3fNick Vaccaro */
1712