1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "calibration/gyroscope/gyro_cal.h"
18 
19 #include <float.h>
20 #include <math.h>
21 #include <string.h>
22 
23 #include "calibration/util/cal_log.h"
24 #include "common/math/vec.h"
25 
26 /////// DEFINITIONS AND MACROS ///////////////////////////////////////
27 
28 // Maximum gyro bias correction (should be set based on expected max bias
29 // of the given sensor).
30 #define MAX_GYRO_BIAS (0.1f)  // [rad/sec]
31 
32 // Converts units of radians to milli-degrees.
33 #define RAD_TO_MILLI_DEGREES (float)(1e3f * 180.0f / NANO_PI)
34 
35 #ifdef GYRO_CAL_DBG_ENABLED
36 // The time value used to throttle debug messaging.
37 #define GYROCAL_WAIT_TIME_NANOS (300000000)
38 
39 // Unit conversion: nanoseconds to seconds.
40 #define NANOS_TO_SEC (1.0e-9f)
41 
42 // A debug version label to help with tracking results.
43 #define GYROCAL_DEBUG_VERSION_STRING "[Jan 20, 2017]"
44 
45 // Debug log tag string used to identify debug report output data.
46 #define GYROCAL_REPORT_TAG "[GYRO_CAL:REPORT]"
47 
48 // Debug log tag string used to identify debug tuning output data.
49 #define GYROCAL_TUNE_TAG "[GYRO_CAL:TUNE]"
50 #endif  // GYRO_CAL_DBG_ENABLED
51 
52 /////// FORWARD DECLARATIONS /////////////////////////////////////////
53 
54 static void deviceStillnessCheck(struct GyroCal* gyro_cal,
55                                  uint64_t sample_time_nanos);
56 
57 static void computeGyroCal(struct GyroCal* gyro_cal,
58                            uint64_t calibration_time_nanos);
59 
60 static void checkWatchdog(struct GyroCal* gyro_cal, uint64_t sample_time_nanos);
61 
62 // Data tracker command enumeration.
63 enum GyroCalTrackerCommand {
64   DO_RESET = 0,    // Resets the local data used for data tracking.
65   DO_UPDATE_DATA,  // Updates the local tracking data.
66   DO_STORE_DATA,   // Stores intermediate results for later recall.
67   DO_EVALUATE      // Computes and provides the results of the gate function.
68 };
69 
70 /*
71  * Updates the temperature min/max and mean during the stillness period. Returns
72  * 'true' if the min and max temperature values exceed the range set by
73  * 'temperature_delta_limit_celsius'.
74  *
75  * INPUTS:
76  *   gyro_cal:     Pointer to the GyroCal data structure.
77  *   temperature_celsius:  New temperature sample to include.
78  *   do_this:      Command enumerator that controls function behavior:
79  */
80 static bool gyroTemperatureStatsTracker(struct GyroCal* gyro_cal,
81                                         float temperature_celsius,
82                                         enum GyroCalTrackerCommand do_this);
83 
84 /*
85  * Tracks the minimum and maximum gyroscope stillness window means.
86  * Returns 'true' when the difference between gyroscope min and max window
87  * means are outside the range set by 'stillness_mean_delta_limit'.
88  *
89  * INPUTS:
90  *   gyro_cal:     Pointer to the GyroCal data structure.
91  *   do_this:      Command enumerator that controls function behavior.
92  */
93 static bool gyroStillMeanTracker(struct GyroCal* gyro_cal,
94                                  enum GyroCalTrackerCommand do_this);
95 
96 #ifdef GYRO_CAL_DBG_ENABLED
97 // Defines the type of debug data to print.
98 enum DebugPrintData {
99   OFFSET = 0,
100   STILLNESS_DATA,
101   SAMPLE_RATE_AND_TEMPERATURE,
102   GYRO_MINMAX_STILLNESS_MEAN,
103   ACCEL_STATS,
104   GYRO_STATS,
105   MAG_STATS,
106   ACCEL_STATS_TUNING,
107   GYRO_STATS_TUNING,
108   MAG_STATS_TUNING
109 };
110 
111 /*
112  * Updates running calculation of the gyro's mean sampling rate.
113  *
114  * Behavior:
115  *   1)  If 'debug_mean_sampling_rate_hz' pointer is not NULL then the local
116  *       calculation of the sampling rate is copied, and the function returns.
117  *   2)  Else, if 'reset_stats' is 'true' then the local estimate is reset and
118  *       the function returns.
119  *   3)  Otherwise, the local estimate of the mean sampling rates is updated.
120  *
121  * INPUTS:
122  *   debug_mean_sampling_rate_hz:   Pointer to the mean sampling rate to update.
123  *   timestamp_nanos:  Time stamp (nanoseconds).
124  *   reset_stats:  Flag that signals a reset of the sampling rate estimate.
125  */
126 static void gyroSamplingRateUpdate(float* debug_mean_sampling_rate_hz,
127                                    uint64_t timestamp_nanos, bool reset_stats);
128 
129 // Updates the information used for debug printouts.
130 static void gyroCalUpdateDebug(struct GyroCal* gyro_cal);
131 
132 // Helper function for printing out common debug data.
133 static void gyroCalDebugPrintData(const struct GyroCal* gyro_cal,
134                                   char* debug_tag,
135                                   enum DebugPrintData print_data);
136 
137 // This conversion function is necessary for Nanohub firmware compilation (i.e.,
138 // can't cast a uint64_t to a float directly). This conversion function was
139 // copied from: /third_party/contexthub/firmware/src/floatRt.c
floatFromUint64(uint64_t v)140 static float floatFromUint64(uint64_t v)
141 {
142     uint32_t hi = v >> 32, lo = v;
143 
144     if (!hi) //this is very fast for cases where we fit into a uint32_t
145         return(float)lo;
146     else {
147         return ((float)hi) * 4294967296.0f + (float)lo;
148     }
149 }
150 
151 #ifdef GYRO_CAL_DBG_TUNE_ENABLED
152 // Prints debug information useful for tuning the GyroCal parameters.
153 static void gyroCalTuneDebugPrint(const struct GyroCal* gyro_cal,
154                                   uint64_t timestamp_nanos);
155 #endif  // GYRO_CAL_DBG_TUNE_ENABLED
156 #endif  // GYRO_CAL_DBG_ENABLED
157 
158 /////// FUNCTION DEFINITIONS /////////////////////////////////////////
159 
160 // Initialize the gyro calibration data structure.
gyroCalInit(struct GyroCal * gyro_cal,uint64_t min_still_duration_nanos,uint64_t max_still_duration_nanos,float bias_x,float bias_y,float bias_z,uint64_t calibration_time_nanos,uint64_t window_time_duration_nanos,float gyro_var_threshold,float gyro_confidence_delta,float accel_var_threshold,float accel_confidence_delta,float mag_var_threshold,float mag_confidence_delta,float stillness_threshold,float stillness_mean_delta_limit,float temperature_delta_limit_celsius,bool gyro_calibration_enable)161 void gyroCalInit(struct GyroCal* gyro_cal, uint64_t min_still_duration_nanos,
162                  uint64_t max_still_duration_nanos, float bias_x, float bias_y,
163                  float bias_z, uint64_t calibration_time_nanos,
164                  uint64_t window_time_duration_nanos, float gyro_var_threshold,
165                  float gyro_confidence_delta, float accel_var_threshold,
166                  float accel_confidence_delta, float mag_var_threshold,
167                  float mag_confidence_delta, float stillness_threshold,
168                  float stillness_mean_delta_limit,
169                  float temperature_delta_limit_celsius,
170                  bool gyro_calibration_enable) {
171   // Clear gyro_cal structure memory.
172   memset(gyro_cal, 0, sizeof(struct GyroCal));
173 
174   // Initialize the stillness detectors.
175   // Gyro parameter input units are [rad/sec].
176   // Accel parameter input units are [m/sec^2].
177   // Magnetometer parameter input units are [uT].
178   gyroStillDetInit(&gyro_cal->gyro_stillness_detect, gyro_var_threshold,
179                    gyro_confidence_delta);
180   gyroStillDetInit(&gyro_cal->accel_stillness_detect, accel_var_threshold,
181                    accel_confidence_delta);
182   gyroStillDetInit(&gyro_cal->mag_stillness_detect, mag_var_threshold,
183                    mag_confidence_delta);
184 
185   // Reset stillness flag and start timestamp.
186   gyro_cal->prev_still = false;
187   gyro_cal->start_still_time_nanos = 0;
188 
189   // Set the min and max window stillness duration.
190   gyro_cal->min_still_duration_nanos = min_still_duration_nanos;
191   gyro_cal->max_still_duration_nanos = max_still_duration_nanos;
192 
193   // Sets the duration of the stillness processing windows.
194   gyro_cal->window_time_duration_nanos = window_time_duration_nanos;
195 
196   // Set the watchdog timeout duration.
197   gyro_cal->gyro_watchdog_timeout_duration_nanos =
198       2 * window_time_duration_nanos;
199 
200   // Load the last valid cal from system memory.
201   gyro_cal->bias_x = bias_x;  // [rad/sec]
202   gyro_cal->bias_y = bias_y;  // [rad/sec]
203   gyro_cal->bias_z = bias_z;  // [rad/sec]
204   gyro_cal->calibration_time_nanos = calibration_time_nanos;
205 
206   // Set the stillness threshold required for gyro bias calibration.
207   gyro_cal->stillness_threshold = stillness_threshold;
208 
209   // Current window end-time used to assist in keeping sensor data collection in
210   // sync. Setting this to zero signals that sensor data will be dropped until a
211   // valid end-time is set from the first gyro timestamp received.
212   gyro_cal->stillness_win_endtime_nanos = 0;
213 
214   // Gyro calibrations will be applied (see, gyroCalRemoveBias()).
215   gyro_cal->gyro_calibration_enable = (gyro_calibration_enable > 0);
216 
217   // Sets the stability limit for the stillness window mean acceptable delta.
218   gyro_cal->stillness_mean_delta_limit = stillness_mean_delta_limit;
219 
220   // Sets the min/max temperature delta limit for the stillness period.
221   gyro_cal->temperature_delta_limit_celsius = temperature_delta_limit_celsius;
222 
223   // Ensures that the data tracking functionality is reset.
224   gyroStillMeanTracker(gyro_cal, DO_RESET);
225   gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
226 
227 #ifdef GYRO_CAL_DBG_ENABLED
228   CAL_DEBUG_LOG("[GYRO_CAL:MEMORY]", "sizeof(struct GyroCal): %lu",
229                 (unsigned long int)sizeof(struct GyroCal));
230 
231   if (gyro_cal->gyro_calibration_enable) {
232     CAL_DEBUG_LOG("[GYRO_CAL:INIT]", "Online gyroscope calibration ENABLED.");
233   } else {
234     CAL_DEBUG_LOG("[GYRO_CAL:INIT]", "Online gyroscope calibration DISABLED.");
235   }
236 
237   // Ensures that the gyro sampling rate estimate is reset.
238   gyroSamplingRateUpdate(NULL, 0, /*reset_stats=*/true);
239 #endif  // GYRO_CAL_DBG_ENABLED
240 }
241 
242 // Void pointer in the gyro calibration data structure (doesn't do anything
243 // except prevent compiler warnings).
gyroCalDestroy(struct GyroCal * gyro_cal)244 void gyroCalDestroy(struct GyroCal* gyro_cal) {
245   (void)gyro_cal;
246 }
247 
248 // Get the most recent bias calibration value.
gyroCalGetBias(struct GyroCal * gyro_cal,float * bias_x,float * bias_y,float * bias_z,float * temperature_celsius)249 void gyroCalGetBias(struct GyroCal* gyro_cal, float* bias_x, float* bias_y,
250                     float* bias_z, float* temperature_celsius) {
251   *bias_x = gyro_cal->bias_x;
252   *bias_y = gyro_cal->bias_y;
253   *bias_z = gyro_cal->bias_z;
254   *temperature_celsius = gyro_cal->bias_temperature_celsius;
255 }
256 
257 // Set an initial bias calibration value.
gyroCalSetBias(struct GyroCal * gyro_cal,float bias_x,float bias_y,float bias_z,uint64_t calibration_time_nanos)258 void gyroCalSetBias(struct GyroCal* gyro_cal, float bias_x, float bias_y,
259                     float bias_z, uint64_t calibration_time_nanos) {
260   gyro_cal->bias_x = bias_x;
261   gyro_cal->bias_y = bias_y;
262   gyro_cal->bias_z = bias_z;
263   gyro_cal->calibration_time_nanos = calibration_time_nanos;
264 
265 #ifdef GYRO_CAL_DBG_ENABLED
266   CAL_DEBUG_LOG("[GYRO_CAL:RECALL]",
267                 "Gyro Bias Calibration [mdps]: %s%d.%06d, %s%d.%06d, %s%d.%06d",
268                 CAL_ENCODE_FLOAT(gyro_cal->bias_x * RAD_TO_MILLI_DEGREES, 6),
269                 CAL_ENCODE_FLOAT(gyro_cal->bias_y * RAD_TO_MILLI_DEGREES, 6),
270                 CAL_ENCODE_FLOAT(gyro_cal->bias_z * RAD_TO_MILLI_DEGREES, 6));
271 #endif  // GYRO_CAL_DBG_ENABLED
272 }
273 
274 // Remove bias from a gyro measurement [rad/sec].
gyroCalRemoveBias(struct GyroCal * gyro_cal,float xi,float yi,float zi,float * xo,float * yo,float * zo)275 void gyroCalRemoveBias(struct GyroCal* gyro_cal, float xi, float yi, float zi,
276                        float* xo, float* yo, float* zo) {
277   if (gyro_cal->gyro_calibration_enable) {
278     *xo = xi - gyro_cal->bias_x;
279     *yo = yi - gyro_cal->bias_y;
280     *zo = zi - gyro_cal->bias_z;
281   }
282 }
283 
284 // Returns true when a new gyro calibration is available.
gyroCalNewBiasAvailable(struct GyroCal * gyro_cal)285 bool gyroCalNewBiasAvailable(struct GyroCal* gyro_cal) {
286   bool new_gyro_cal_available =
287       (gyro_cal->gyro_calibration_enable && gyro_cal->new_gyro_cal_available);
288 
289   // Clear the flag.
290   gyro_cal->new_gyro_cal_available = false;
291 
292   return new_gyro_cal_available;
293 }
294 
295 // Update the gyro calibration with gyro data [rad/sec].
gyroCalUpdateGyro(struct GyroCal * gyro_cal,uint64_t sample_time_nanos,float x,float y,float z,float temperature_celsius)296 void gyroCalUpdateGyro(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
297                        float x, float y, float z, float temperature_celsius) {
298   static float latest_temperature_celsius = 0.0f;
299 
300   // Make sure that a valid window end-time is set, and start the watchdog
301   // timer.
302   if (gyro_cal->stillness_win_endtime_nanos <= 0) {
303     gyro_cal->stillness_win_endtime_nanos =
304         sample_time_nanos + gyro_cal->window_time_duration_nanos;
305 
306     // Start the watchdog timer.
307     gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
308   }
309 
310   // Update the temperature statistics (only on a temperature change).
311   if (NANO_ABS(temperature_celsius - latest_temperature_celsius) > FLT_MIN) {
312     gyroTemperatureStatsTracker(gyro_cal, temperature_celsius, DO_UPDATE_DATA);
313   }
314 
315 #ifdef GYRO_CAL_DBG_ENABLED
316   // Update the gyro sampling rate estimate.
317   gyroSamplingRateUpdate(NULL, sample_time_nanos, /*reset_stats=*/false);
318 #endif  // GYRO_CAL_DBG_ENABLED
319 
320   // Pass gyro data to stillness detector
321   gyroStillDetUpdate(&gyro_cal->gyro_stillness_detect,
322                      gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
323                      x, y, z);
324 
325   // Perform a device stillness check, set next window end-time, and
326   // possibly do a gyro bias calibration and stillness detector reset.
327   deviceStillnessCheck(gyro_cal, sample_time_nanos);
328 }
329 
330 // Update the gyro calibration with mag data [micro Tesla].
gyroCalUpdateMag(struct GyroCal * gyro_cal,uint64_t sample_time_nanos,float x,float y,float z)331 void gyroCalUpdateMag(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
332                       float x, float y, float z) {
333   // Pass magnetometer data to stillness detector.
334   gyroStillDetUpdate(&gyro_cal->mag_stillness_detect,
335                      gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
336                      x, y, z);
337 
338   // Received a magnetometer sample; incorporate it into detection.
339   gyro_cal->using_mag_sensor = true;
340 
341   // Perform a device stillness check, set next window end-time, and
342   // possibly do a gyro bias calibration and stillness detector reset.
343   deviceStillnessCheck(gyro_cal, sample_time_nanos);
344 }
345 
346 // Update the gyro calibration with accel data [m/sec^2].
gyroCalUpdateAccel(struct GyroCal * gyro_cal,uint64_t sample_time_nanos,float x,float y,float z)347 void gyroCalUpdateAccel(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
348                         float x, float y, float z) {
349   // Pass accelerometer data to stillnesss detector.
350   gyroStillDetUpdate(&gyro_cal->accel_stillness_detect,
351                      gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
352                      x, y, z);
353 
354   // Perform a device stillness check, set next window end-time, and
355   // possibly do a gyro bias calibration and stillness detector reset.
356   deviceStillnessCheck(gyro_cal, sample_time_nanos);
357 }
358 
359 // TODO(davejacobs): Consider breaking this function up to improve readability.
360 // Checks the state of all stillness detectors to determine
361 // whether the device is "still".
deviceStillnessCheck(struct GyroCal * gyro_cal,uint64_t sample_time_nanos)362 void deviceStillnessCheck(struct GyroCal* gyro_cal,
363                           uint64_t sample_time_nanos) {
364   bool stillness_duration_exceeded = false;
365   bool stillness_duration_too_short = false;
366   bool min_max_temp_exceeded = false;
367   bool mean_not_stable = false;
368   bool device_is_still = false;
369   float conf_not_rot = 0;
370   float conf_not_accel = 0;
371   float conf_still = 0;
372 
373   // Check the watchdog timer.
374   checkWatchdog(gyro_cal, sample_time_nanos);
375 
376   // Is there enough data to do a stillness calculation?
377   if ((!gyro_cal->mag_stillness_detect.stillness_window_ready &&
378        gyro_cal->using_mag_sensor) ||
379       !gyro_cal->accel_stillness_detect.stillness_window_ready ||
380       !gyro_cal->gyro_stillness_detect.stillness_window_ready) {
381     return;  // Not yet, wait for more data.
382   }
383 
384   // Set the next window end-time for the stillness detectors.
385   gyro_cal->stillness_win_endtime_nanos =
386       sample_time_nanos + gyro_cal->window_time_duration_nanos;
387 
388   // Update the confidence scores for all sensors.
389   gyroStillDetCompute(&gyro_cal->accel_stillness_detect);
390   gyroStillDetCompute(&gyro_cal->gyro_stillness_detect);
391   if (gyro_cal->using_mag_sensor) {
392     gyroStillDetCompute(&gyro_cal->mag_stillness_detect);
393   } else {
394     // Not using magnetometer, force stillness confidence to 100%.
395     gyro_cal->mag_stillness_detect.stillness_confidence = 1.0f;
396   }
397 
398   // Updates the mean tracker data.
399   gyroStillMeanTracker(gyro_cal, DO_UPDATE_DATA);
400 
401   // Determine motion confidence scores (rotation, accelerating, and stillness).
402   conf_not_rot = gyro_cal->gyro_stillness_detect.stillness_confidence *
403                  gyro_cal->mag_stillness_detect.stillness_confidence;
404   conf_not_accel = gyro_cal->accel_stillness_detect.stillness_confidence;
405   conf_still = conf_not_rot * conf_not_accel;
406 
407   // Evaluate the mean and temperature gate functions.
408   mean_not_stable = gyroStillMeanTracker(gyro_cal, DO_EVALUATE);
409   min_max_temp_exceeded =
410       gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_EVALUATE);
411 
412   // Determines if the device is currently still.
413   device_is_still = (conf_still > gyro_cal->stillness_threshold) &&
414       !mean_not_stable && !min_max_temp_exceeded ;
415 
416   if (device_is_still) {
417     // Device is "still" logic:
418     // If not previously still, then record the start time.
419     // If stillness period is too long, then do a calibration.
420     // Otherwise, continue collecting stillness data.
421 
422     // If device was not previously still, set new start timestamp.
423     if (!gyro_cal->prev_still) {
424       // Record the starting timestamp of the current stillness window.
425       // This enables the calculation of total duration of the stillness period.
426       gyro_cal->start_still_time_nanos =
427           gyro_cal->gyro_stillness_detect.window_start_time;
428     }
429 
430     // Check to see if current stillness period exceeds the desired limit.
431     stillness_duration_exceeded =
432         ((gyro_cal->gyro_stillness_detect.last_sample_time -
433           gyro_cal->start_still_time_nanos) >
434          gyro_cal->max_still_duration_nanos);
435 
436     // Track the new stillness mean and temperature data.
437     gyroStillMeanTracker(gyro_cal, DO_STORE_DATA);
438     gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_STORE_DATA);
439 
440     if (stillness_duration_exceeded) {
441       // The current stillness has gone too long. Do a calibration with the
442       // current data and reset.
443 
444       // Updates the gyro bias estimate with the current window data and
445       // resets the stats.
446       gyroStillDetReset(&gyro_cal->accel_stillness_detect,
447                         /*reset_stats=*/true);
448       gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
449       gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
450 
451       // Resets the local calculations because the stillness period is over.
452       gyroStillMeanTracker(gyro_cal, DO_RESET);
453       gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
454 
455       // Computes a new gyro offset estimate.
456       computeGyroCal(gyro_cal,
457                      gyro_cal->gyro_stillness_detect.last_sample_time);
458 
459 #ifdef GYRO_CAL_DBG_ENABLED
460       // Resets the sampling rate estimate.
461       gyroSamplingRateUpdate(NULL, sample_time_nanos, /*reset_stats=*/true);
462 #endif  // GYRO_CAL_DBG_ENABLED
463 
464       // Update stillness flag. Force the start of a new stillness period.
465       gyro_cal->prev_still = false;
466     } else {
467       // Continue collecting stillness data.
468 
469       // Extend the stillness period.
470       gyroStillDetReset(&gyro_cal->accel_stillness_detect,
471                         /*reset_stats=*/false);
472       gyroStillDetReset(&gyro_cal->gyro_stillness_detect,
473                         /*reset_stats=*/false);
474       gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/false);
475 
476       // Update the stillness flag.
477       gyro_cal->prev_still = true;
478     }
479   } else {
480     // Device is NOT still; motion detected.
481 
482     // If device was previously still and the total stillness duration is not
483     // "too short", then do a calibration with the data accumulated thus far.
484     stillness_duration_too_short =
485         ((gyro_cal->gyro_stillness_detect.window_start_time -
486           gyro_cal->start_still_time_nanos) <
487          gyro_cal->min_still_duration_nanos);
488 
489     if (gyro_cal->prev_still && !stillness_duration_too_short) {
490       computeGyroCal(gyro_cal,
491                      gyro_cal->gyro_stillness_detect.window_start_time);
492     }
493 
494     // Reset the stillness detectors and the stats.
495     gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
496     gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
497     gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
498 
499     // Resets the temperature and sensor mean data.
500     gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
501     gyroStillMeanTracker(gyro_cal, DO_RESET);
502 
503 #ifdef GYRO_CAL_DBG_ENABLED
504     // Resets the sampling rate estimate.
505     gyroSamplingRateUpdate(NULL, sample_time_nanos, /*reset_stats=*/true);
506 #endif  // GYRO_CAL_DBG_ENABLED
507 
508     // Update stillness flag.
509     gyro_cal->prev_still = false;
510   }
511 
512   // Reset the watchdog timer after we have processed data.
513   gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
514 }
515 
516 // Calculates a new gyro bias offset calibration value.
computeGyroCal(struct GyroCal * gyro_cal,uint64_t calibration_time_nanos)517 void computeGyroCal(struct GyroCal* gyro_cal, uint64_t calibration_time_nanos) {
518   // Check to see if new calibration values is within acceptable range.
519   if (!(gyro_cal->gyro_stillness_detect.prev_mean_x < MAX_GYRO_BIAS &&
520         gyro_cal->gyro_stillness_detect.prev_mean_x > -MAX_GYRO_BIAS &&
521         gyro_cal->gyro_stillness_detect.prev_mean_y < MAX_GYRO_BIAS &&
522         gyro_cal->gyro_stillness_detect.prev_mean_y > -MAX_GYRO_BIAS &&
523         gyro_cal->gyro_stillness_detect.prev_mean_z < MAX_GYRO_BIAS &&
524         gyro_cal->gyro_stillness_detect.prev_mean_z > -MAX_GYRO_BIAS)) {
525 #ifdef GYRO_CAL_DBG_ENABLED
526     CAL_DEBUG_LOG("[GYRO_CAL:REJECT]",
527                   "Offset|Temp|Time [mdps|C|nsec]: %s%d.%06d, %s%d.%06d, "
528                   "%s%d.%06d, %s%d.%06d, %llu",
529                   CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_x *
530                                        RAD_TO_MILLI_DEGREES,
531                                    6),
532                   CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_y *
533                                        RAD_TO_MILLI_DEGREES,
534                                    6),
535                   CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_z *
536                                        RAD_TO_MILLI_DEGREES,
537                                    6),
538                   CAL_ENCODE_FLOAT(gyro_cal->temperature_mean_celsius, 6),
539                   (unsigned long long int)calibration_time_nanos);
540 #endif  // GYRO_CAL_DBG_ENABLED
541 
542     // Outside of range. Ignore, reset, and continue.
543     return;
544   }
545 
546   // Record the new gyro bias offset calibration.
547   gyro_cal->bias_x = gyro_cal->gyro_stillness_detect.prev_mean_x;
548   gyro_cal->bias_y = gyro_cal->gyro_stillness_detect.prev_mean_y;
549   gyro_cal->bias_z = gyro_cal->gyro_stillness_detect.prev_mean_z;
550 
551   // Store the calibration temperature (using the mean temperature over the
552   // "stillness" period).
553   gyro_cal->bias_temperature_celsius = gyro_cal->temperature_mean_celsius;
554 
555   // Store the calibration time stamp.
556   gyro_cal->calibration_time_nanos = calibration_time_nanos;
557 
558   // Record the final stillness confidence.
559   gyro_cal->stillness_confidence =
560       gyro_cal->gyro_stillness_detect.prev_stillness_confidence *
561       gyro_cal->accel_stillness_detect.prev_stillness_confidence *
562       gyro_cal->mag_stillness_detect.prev_stillness_confidence;
563 
564   // Set flag to indicate a new gyro calibration value is available.
565   gyro_cal->new_gyro_cal_available = true;
566 
567 #ifdef GYRO_CAL_DBG_ENABLED
568   // Increment the total count of calibration updates.
569   gyro_cal->debug_calibration_count++;
570 
571   // Update the calibration debug information and trigger a printout.
572   gyroCalUpdateDebug(gyro_cal);
573 #endif
574 }
575 
576 // Check for a watchdog timeout condition.
checkWatchdog(struct GyroCal * gyro_cal,uint64_t sample_time_nanos)577 void checkWatchdog(struct GyroCal* gyro_cal, uint64_t sample_time_nanos) {
578   bool watchdog_timeout;
579 
580   // Check for initialization of the watchdog time (=0).
581   if (gyro_cal->gyro_watchdog_start_nanos <= 0) {
582     return;
583   }
584 
585   // Check for the watchdog timeout condition (i.e., the time elapsed since the
586   // last received sample has exceeded the allowed watchdog duration).
587   watchdog_timeout =
588       (sample_time_nanos > gyro_cal->gyro_watchdog_timeout_duration_nanos +
589                                gyro_cal->gyro_watchdog_start_nanos);
590 
591   // If a timeout occurred then reset to known good state.
592   if (watchdog_timeout) {
593     // Reset stillness detectors and restart data capture.
594     gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
595     gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
596     gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
597 
598     // Resets the temperature and sensor mean data.
599     gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
600     gyroStillMeanTracker(gyro_cal, DO_RESET);
601 
602 #ifdef GYRO_CAL_DBG_ENABLED
603     // Resets the sampling rate estimate.
604     gyroSamplingRateUpdate(NULL, sample_time_nanos, /*reset_stats=*/true);
605 #endif  // GYRO_CAL_DBG_ENABLED
606 
607     // Resets the stillness window end-time.
608     gyro_cal->stillness_win_endtime_nanos = 0;
609 
610     // Force stillness confidence to zero.
611     gyro_cal->accel_stillness_detect.prev_stillness_confidence = 0;
612     gyro_cal->gyro_stillness_detect.prev_stillness_confidence = 0;
613     gyro_cal->mag_stillness_detect.prev_stillness_confidence = 0;
614     gyro_cal->stillness_confidence = 0;
615     gyro_cal->prev_still = false;
616 
617     // If there are no magnetometer samples being received then
618     // operate the calibration algorithm without this sensor.
619     if (!gyro_cal->mag_stillness_detect.stillness_window_ready &&
620         gyro_cal->using_mag_sensor) {
621       gyro_cal->using_mag_sensor = false;
622     }
623 
624     // Assert watchdog timeout flags.
625     gyro_cal->gyro_watchdog_timeout |= watchdog_timeout;
626     gyro_cal->gyro_watchdog_start_nanos = 0;
627 #ifdef GYRO_CAL_DBG_ENABLED
628     gyro_cal->debug_watchdog_count++;
629     CAL_DEBUG_LOG("[GYRO_CAL:WATCHDOG]", "Total#, Timestamp [nsec]: %lu, %llu",
630                   (unsigned long int)gyro_cal->debug_watchdog_count,
631                   (unsigned long long int)sample_time_nanos);
632 #endif  // GYRO_CAL_DBG_ENABLED
633   }
634 }
635 
636 // TODO(davejacobs) -- Combine the following two functions into one or consider
637 // implementing a separate helper module for tracking the temperature and mean
638 // statistics.
gyroTemperatureStatsTracker(struct GyroCal * gyro_cal,float temperature_celsius,enum GyroCalTrackerCommand do_this)639 bool gyroTemperatureStatsTracker(struct GyroCal* gyro_cal,
640                                  float temperature_celsius,
641                                  enum GyroCalTrackerCommand do_this) {
642   // This is used for local calculations of the running mean.
643   static float mean_accumulator = 0.0f;
644   static float temperature_min_max_celsius[2] = {0.0f, 0.0f};
645   static size_t num_points = 0;
646   bool min_max_temp_exceeded = false;
647 
648   switch (do_this) {
649     case DO_RESET:
650       // Resets the mean accumulator.
651       num_points = 0;
652       mean_accumulator = 0.0f;
653 
654       // Initializes the min/max temperatures values.
655       temperature_min_max_celsius[0] = FLT_MAX;
656       temperature_min_max_celsius[1] = -1.0f * (FLT_MAX - 1.0f);
657       break;
658 
659     case DO_UPDATE_DATA:
660       // Does the mean accumulation.
661       mean_accumulator += temperature_celsius;
662       num_points++;
663 
664       // Tracks the min and max temperature values.
665       if (temperature_min_max_celsius[0] > temperature_celsius) {
666         temperature_min_max_celsius[0] = temperature_celsius;
667       }
668       if (temperature_min_max_celsius[1] < temperature_celsius) {
669         temperature_min_max_celsius[1] = temperature_celsius;
670       }
671       break;
672 
673     case DO_STORE_DATA:
674       // Store the most recent "stillness" mean data to the GyroCal data
675       // structure. This functionality allows previous results to be recalled
676       // when the device suddenly becomes "not still".
677       if (num_points > 0) {
678         memcpy(gyro_cal->temperature_min_max_celsius,
679                temperature_min_max_celsius, 2 * sizeof(float));
680         gyro_cal->temperature_mean_celsius = mean_accumulator / num_points;
681       }
682       break;
683 
684     case DO_EVALUATE:
685       // Determines if the min/max delta exceeded the set limit.
686       if (num_points > 0) {
687         min_max_temp_exceeded =
688             (temperature_min_max_celsius[1] -
689              temperature_min_max_celsius[0]) >
690             gyro_cal->temperature_delta_limit_celsius;
691 
692 #ifdef GYRO_CAL_DBG_ENABLED
693         if (min_max_temp_exceeded) {
694           CAL_DEBUG_LOG(
695               "[GYRO_CAL:TEMP_GATE]",
696               "Exceeded the max temperature variation during stillness.");
697         }
698 #endif  // GYRO_CAL_DBG_ENABLED
699       }
700       break;
701 
702     default:
703       break;
704   }
705 
706   return min_max_temp_exceeded;
707 }
708 
gyroStillMeanTracker(struct GyroCal * gyro_cal,enum GyroCalTrackerCommand do_this)709 bool gyroStillMeanTracker(struct GyroCal* gyro_cal,
710                           enum GyroCalTrackerCommand do_this) {
711   static float gyro_winmean_min[3] = {0.0f, 0.0f, 0.0f};
712   static float gyro_winmean_max[3] = {0.0f, 0.0f, 0.0f};
713   bool mean_not_stable = false;
714   size_t i;
715 
716   switch (do_this) {
717     case DO_RESET:
718       // Resets the min/max window mean values to a default value.
719       for (i = 0; i < 3; i++) {
720         gyro_winmean_min[i] = FLT_MAX;
721         gyro_winmean_max[i] = -1.0f * (FLT_MAX - 1.0f);
722       }
723       break;
724 
725     case DO_UPDATE_DATA:
726       // Computes the min/max window mean values.
727       if (gyro_winmean_min[0] > gyro_cal->gyro_stillness_detect.win_mean_x) {
728         gyro_winmean_min[0] = gyro_cal->gyro_stillness_detect.win_mean_x;
729       }
730       if (gyro_winmean_max[0] < gyro_cal->gyro_stillness_detect.win_mean_x) {
731         gyro_winmean_max[0] = gyro_cal->gyro_stillness_detect.win_mean_x;
732       }
733 
734       if (gyro_winmean_min[1] > gyro_cal->gyro_stillness_detect.win_mean_y) {
735         gyro_winmean_min[1] = gyro_cal->gyro_stillness_detect.win_mean_y;
736       }
737       if (gyro_winmean_max[1] < gyro_cal->gyro_stillness_detect.win_mean_y) {
738         gyro_winmean_max[1] = gyro_cal->gyro_stillness_detect.win_mean_y;
739       }
740 
741       if (gyro_winmean_min[2] > gyro_cal->gyro_stillness_detect.win_mean_z) {
742         gyro_winmean_min[2] = gyro_cal->gyro_stillness_detect.win_mean_z;
743       }
744       if (gyro_winmean_max[2] < gyro_cal->gyro_stillness_detect.win_mean_z) {
745         gyro_winmean_max[2] = gyro_cal->gyro_stillness_detect.win_mean_z;
746       }
747       break;
748 
749     case DO_STORE_DATA:
750       // Store the most recent "stillness" mean data to the GyroCal data
751       // structure. This functionality allows previous results to be recalled
752       // when the device suddenly becomes "not still".
753       memcpy(gyro_cal->gyro_winmean_min, gyro_winmean_min, 3 * sizeof(float));
754       memcpy(gyro_cal->gyro_winmean_max, gyro_winmean_max, 3 * sizeof(float));
755     break;
756 
757     case DO_EVALUATE:
758       // Performs the stability check and returns the 'true' if the difference
759       // between min/max window mean value is outside the stable range.
760       for (i = 0; i < 3; i++) {
761         mean_not_stable |= (gyro_winmean_max[i] - gyro_winmean_min[i]) >
762                            gyro_cal->stillness_mean_delta_limit;
763       }
764 #ifdef GYRO_CAL_DBG_ENABLED
765       if (mean_not_stable) {
766         CAL_DEBUG_LOG("[GYRO_CAL:MEAN_STABILITY_GATE]",
767                       "Exceeded the max variation in the gyro's stillness "
768                       "window mean values.");
769       }
770 #endif  // GYRO_CAL_DBG_ENABLED
771       break;
772 
773     default:
774       break;
775   }
776 
777   return mean_not_stable;
778 }
779 
780 #ifdef GYRO_CAL_DBG_ENABLED
gyroSamplingRateUpdate(float * debug_mean_sampling_rate_hz,uint64_t timestamp_nanos,bool reset_stats)781 void gyroSamplingRateUpdate(float* debug_mean_sampling_rate_hz,
782                             uint64_t timestamp_nanos, bool reset_stats) {
783   // This is used for local calculations of average sampling rate.
784   static uint64_t last_timestamp_nanos = 0;
785   static uint64_t time_delta_accumulator = 0;
786   static size_t num_samples = 0;
787 
788   // If 'debug_mean_sampling_rate_hz' is not NULL then this function just reads
789   // out the estimate of the sampling rate.
790   if (debug_mean_sampling_rate_hz) {
791     if (num_samples > 1 && time_delta_accumulator > 0) {
792       // Computes the final mean calculation.
793       *debug_mean_sampling_rate_hz =
794           num_samples /
795           (floatFromUint64(time_delta_accumulator) * NANOS_TO_SEC);
796     } else {
797       // Not enough samples to compute a valid sample rate estimate. Indicate
798       // this with a -1 value.
799       *debug_mean_sampling_rate_hz = -1.0f;
800     }
801     reset_stats = true;
802   }
803 
804   // Resets the sampling rate mean estimator data.
805   if (reset_stats) {
806     last_timestamp_nanos = 0;
807     time_delta_accumulator = 0;
808     num_samples = 0;
809     return;
810   }
811 
812   // Skip adding this data to the accumulator if:
813   //   1. A bad timestamp was received (i.e., time not monotonic).
814   //   2. 'last_timestamp_nanos' is zero.
815   if (timestamp_nanos <= last_timestamp_nanos || last_timestamp_nanos == 0) {
816     last_timestamp_nanos = timestamp_nanos;
817     return;
818   }
819 
820   // Increments the number of samples.
821   num_samples++;
822 
823   // Accumulate the time steps.
824   time_delta_accumulator += timestamp_nanos - last_timestamp_nanos;
825   last_timestamp_nanos = timestamp_nanos;
826 }
827 
gyroCalUpdateDebug(struct GyroCal * gyro_cal)828 void gyroCalUpdateDebug(struct GyroCal* gyro_cal) {
829   // Only update this data if debug printing is not currently in progress
830   // (i.e., don't want to risk overwriting debug information that is actively
831   // being reported).
832   if (gyro_cal->debug_state != GYRO_IDLE) {
833     return;
834   }
835 
836   // Probability of stillness (acc, rot, still), duration, timestamp.
837   gyro_cal->debug_gyro_cal.accel_stillness_conf =
838       gyro_cal->accel_stillness_detect.prev_stillness_confidence;
839   gyro_cal->debug_gyro_cal.gyro_stillness_conf =
840       gyro_cal->gyro_stillness_detect.prev_stillness_confidence;
841   gyro_cal->debug_gyro_cal.mag_stillness_conf =
842       gyro_cal->mag_stillness_detect.prev_stillness_confidence;
843 
844   // Magnetometer usage.
845   gyro_cal->debug_gyro_cal.using_mag_sensor = gyro_cal->using_mag_sensor;
846 
847   // Stillness start, stop, and duration times.
848   gyro_cal->debug_gyro_cal.start_still_time_nanos =
849       gyro_cal->start_still_time_nanos;
850   gyro_cal->debug_gyro_cal.end_still_time_nanos =
851       gyro_cal->calibration_time_nanos;
852   gyro_cal->debug_gyro_cal.stillness_duration_nanos =
853       gyro_cal->calibration_time_nanos - gyro_cal->start_still_time_nanos;
854 
855   // Records the current calibration values.
856   gyro_cal->debug_gyro_cal.calibration[0] = gyro_cal->bias_x;
857   gyro_cal->debug_gyro_cal.calibration[1] = gyro_cal->bias_y;
858   gyro_cal->debug_gyro_cal.calibration[2] = gyro_cal->bias_z;
859 
860   // Records the mean gyroscope sampling rate.
861   gyroSamplingRateUpdate(&gyro_cal->debug_gyro_cal.mean_sampling_rate_hz, 0,
862                          /*reset_stats=*/true);
863 
864   // Records the min/max and mean temperature values.
865   gyro_cal->debug_gyro_cal.temperature_mean_celsius =
866       gyro_cal->temperature_mean_celsius;
867   memcpy(gyro_cal->debug_gyro_cal.temperature_min_max_celsius,
868          gyro_cal->temperature_min_max_celsius, 2 * sizeof(float));
869 
870   // Records the min/max gyroscope window stillness mean values.
871   memcpy(gyro_cal->debug_gyro_cal.gyro_winmean_min, gyro_cal->gyro_winmean_min,
872          3 * sizeof(float));
873   memcpy(gyro_cal->debug_gyro_cal.gyro_winmean_max, gyro_cal->gyro_winmean_max,
874          3 * sizeof(float));
875 
876   // Records the previous stillness window means.
877   gyro_cal->debug_gyro_cal.accel_mean[0] =
878       gyro_cal->accel_stillness_detect.prev_mean_x;
879   gyro_cal->debug_gyro_cal.accel_mean[1] =
880       gyro_cal->accel_stillness_detect.prev_mean_y;
881   gyro_cal->debug_gyro_cal.accel_mean[2] =
882       gyro_cal->accel_stillness_detect.prev_mean_z;
883 
884   gyro_cal->debug_gyro_cal.gyro_mean[0] =
885       gyro_cal->gyro_stillness_detect.prev_mean_x;
886   gyro_cal->debug_gyro_cal.gyro_mean[1] =
887       gyro_cal->gyro_stillness_detect.prev_mean_y;
888   gyro_cal->debug_gyro_cal.gyro_mean[2] =
889       gyro_cal->gyro_stillness_detect.prev_mean_z;
890 
891   gyro_cal->debug_gyro_cal.mag_mean[0] =
892       gyro_cal->mag_stillness_detect.prev_mean_x;
893   gyro_cal->debug_gyro_cal.mag_mean[1] =
894       gyro_cal->mag_stillness_detect.prev_mean_y;
895   gyro_cal->debug_gyro_cal.mag_mean[2] =
896       gyro_cal->mag_stillness_detect.prev_mean_z;
897 
898   // Records the variance data.
899   // NOTE: These statistics include the final captured window, which may be
900   // outside of the "stillness" period. Therefore, these values may exceed the
901   // stillness thresholds.
902   gyro_cal->debug_gyro_cal.accel_var[0] =
903       gyro_cal->accel_stillness_detect.win_var_x;
904   gyro_cal->debug_gyro_cal.accel_var[1] =
905       gyro_cal->accel_stillness_detect.win_var_y;
906   gyro_cal->debug_gyro_cal.accel_var[2] =
907       gyro_cal->accel_stillness_detect.win_var_z;
908 
909   gyro_cal->debug_gyro_cal.gyro_var[0] =
910       gyro_cal->gyro_stillness_detect.win_var_x;
911   gyro_cal->debug_gyro_cal.gyro_var[1] =
912       gyro_cal->gyro_stillness_detect.win_var_y;
913   gyro_cal->debug_gyro_cal.gyro_var[2] =
914       gyro_cal->gyro_stillness_detect.win_var_z;
915 
916   gyro_cal->debug_gyro_cal.mag_var[0] =
917       gyro_cal->mag_stillness_detect.win_var_x;
918   gyro_cal->debug_gyro_cal.mag_var[1] =
919       gyro_cal->mag_stillness_detect.win_var_y;
920   gyro_cal->debug_gyro_cal.mag_var[2] =
921       gyro_cal->mag_stillness_detect.win_var_z;
922 
923   // Trigger a printout of the debug information.
924   gyro_cal->debug_print_trigger = true;
925 }
926 
gyroCalDebugPrintData(const struct GyroCal * gyro_cal,char * debug_tag,enum DebugPrintData print_data)927 void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
928                            enum DebugPrintData print_data) {
929   // Prints out the desired debug data.
930   float mag_data;
931   switch (print_data) {
932     case OFFSET:
933       CAL_DEBUG_LOG(debug_tag,
934                     "Cal#|Offset|Temp|Time [mdps|C|nsec]: %lu, %s%d.%06d, "
935                     "%s%d.%06d, %s%d.%06d, %s%d.%03d, %llu",
936                     (unsigned long int)gyro_cal->debug_calibration_count,
937                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.calibration[0] *
938                                          RAD_TO_MILLI_DEGREES,
939                                      6),
940                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.calibration[1] *
941                                          RAD_TO_MILLI_DEGREES,
942                                      6),
943                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.calibration[2] *
944                                          RAD_TO_MILLI_DEGREES,
945                                      6),
946                     CAL_ENCODE_FLOAT(
947                         gyro_cal->debug_gyro_cal.temperature_mean_celsius, 3),
948                     (unsigned long long int)
949                         gyro_cal->debug_gyro_cal.end_still_time_nanos);
950       break;
951 
952     case STILLNESS_DATA:
953       mag_data = (gyro_cal->debug_gyro_cal.using_mag_sensor)
954                      ? gyro_cal->debug_gyro_cal.mag_stillness_conf
955                      : -1.0f;  // Signals that magnetometer was not used.
956       CAL_DEBUG_LOG(
957           debug_tag,
958           "Cal#|Start|End|Confidence [nsec]: %lu, %llu, %llu, "
959           "%s%d.%03d, %s%d.%03d, %s%d.%03d",
960           (unsigned long int)gyro_cal->debug_calibration_count,
961           (unsigned long long int)
962               gyro_cal->debug_gyro_cal.start_still_time_nanos,
963           (unsigned long long int)gyro_cal->debug_gyro_cal.end_still_time_nanos,
964           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_stillness_conf, 3),
965           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_stillness_conf, 3),
966           CAL_ENCODE_FLOAT(mag_data, 3));
967       break;
968 
969     case SAMPLE_RATE_AND_TEMPERATURE:
970       CAL_DEBUG_LOG(
971           debug_tag,
972           "Cal#|Mean|Min|Max|Delta|Sample Rate [C|Hz]: %lu, %s%d.%03d, "
973           "%s%d.%03d, %s%d.%03d, %s%d.%04d, %s%d.%03d",
974           (unsigned long int)gyro_cal->debug_calibration_count,
975           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_mean_celsius,
976                            3),
977           CAL_ENCODE_FLOAT(
978               gyro_cal->debug_gyro_cal.temperature_min_max_celsius[0], 3),
979           CAL_ENCODE_FLOAT(
980               gyro_cal->debug_gyro_cal.temperature_min_max_celsius[1], 3),
981           CAL_ENCODE_FLOAT(
982               gyro_cal->debug_gyro_cal.temperature_min_max_celsius[1] -
983                   gyro_cal->debug_gyro_cal.temperature_min_max_celsius[0],
984               4),
985           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mean_sampling_rate_hz, 3));
986       break;
987 
988     case GYRO_MINMAX_STILLNESS_MEAN:
989       CAL_DEBUG_LOG(
990           debug_tag,
991           "Cal#|Gyro Peak Stillness Variation [mdps]: %lu, %s%d.%06d, "
992           "%s%d.%06d, %s%d.%06d",
993           (unsigned long int)gyro_cal->debug_calibration_count,
994           CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[0] -
995                             gyro_cal->debug_gyro_cal.gyro_winmean_min[0]) *
996                                RAD_TO_MILLI_DEGREES,
997                            6),
998           CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[1] -
999                             gyro_cal->debug_gyro_cal.gyro_winmean_min[1]) *
1000                                RAD_TO_MILLI_DEGREES,
1001                            6),
1002           CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[2] -
1003                             gyro_cal->debug_gyro_cal.gyro_winmean_min[2]) *
1004                                RAD_TO_MILLI_DEGREES,
1005                            6));
1006       break;
1007 
1008     case ACCEL_STATS:
1009       CAL_DEBUG_LOG(
1010           debug_tag,
1011           "Cal#|Accel Mean|Var [m/sec^2|(m/sec^2)^2]: %lu, "
1012           "%s%d.%06d, %s%d.%06d, %s%d.%06d, %s%d.%08d, %s%d.%08d, %s%d.%08d",
1013           (unsigned long int)gyro_cal->debug_calibration_count,
1014           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[0], 6),
1015           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[1], 6),
1016           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[2], 6),
1017           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[0], 8),
1018           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[1], 8),
1019           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[2], 8));
1020       break;
1021 
1022     case GYRO_STATS:
1023       CAL_DEBUG_LOG(
1024           debug_tag,
1025           "Cal#|Gyro Mean|Var [mdps|(rad/sec)^2]: %lu, %s%d.%06d, "
1026           "%s%d.%06d, %s%d.%06d, %s%d.%08d, %s%d.%08d, %s%d.%08d",
1027           (unsigned long int)gyro_cal->debug_calibration_count,
1028           CAL_ENCODE_FLOAT(
1029               gyro_cal->debug_gyro_cal.gyro_mean[0] * RAD_TO_MILLI_DEGREES, 6),
1030           CAL_ENCODE_FLOAT(
1031               gyro_cal->debug_gyro_cal.gyro_mean[1] * RAD_TO_MILLI_DEGREES, 6),
1032           CAL_ENCODE_FLOAT(
1033               gyro_cal->debug_gyro_cal.gyro_mean[2] * RAD_TO_MILLI_DEGREES, 6),
1034           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_var[0], 8),
1035           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_var[1], 8),
1036           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_var[2], 8));
1037       break;
1038 
1039     case MAG_STATS:
1040       if (gyro_cal->debug_gyro_cal.using_mag_sensor) {
1041         CAL_DEBUG_LOG(debug_tag,
1042                       "Cal#|Mag Mean|Var [uT|uT^2]: %lu, %s%d.%06d, "
1043                       "%s%d.%06d, %s%d.%06d, %s%d.%08d, %s%d.%08d, %s%d.%08d",
1044                       (unsigned long int)gyro_cal->debug_calibration_count,
1045                       CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[0], 6),
1046                       CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[1], 6),
1047                       CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[2], 6),
1048                       CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[0], 8),
1049                       CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[1], 8),
1050                       CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[2], 8));
1051       } else {
1052         CAL_DEBUG_LOG(debug_tag,
1053                       "Cal#|Mag Mean|Var [uT|uT^2]: %lu, 0, 0, 0, -1.0, -1.0, "
1054                       "-1.0",
1055                       (unsigned long int)gyro_cal->debug_calibration_count);
1056       }
1057       break;
1058 
1059 #ifdef GYRO_CAL_DBG_TUNE_ENABLED
1060     case ACCEL_STATS_TUNING:
1061       CAL_DEBUG_LOG(
1062           debug_tag,
1063           "Accel Mean|Var [m/sec^2|(m/sec^2)^2]: %s%d.%06d, "
1064           "%s%d.%06d, %s%d.%06d, %s%d.%08d, %s%d.%08d, %s%d.%08d",
1065           CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.prev_mean_x, 6),
1066           CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.prev_mean_y, 6),
1067           CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.prev_mean_z, 6),
1068           CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.win_var_x, 8),
1069           CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.win_var_y, 8),
1070           CAL_ENCODE_FLOAT(gyro_cal->accel_stillness_detect.win_var_z, 8));
1071       break;
1072 
1073     case GYRO_STATS_TUNING:
1074       CAL_DEBUG_LOG(
1075           debug_tag,
1076           "Gyro Mean|Var [mdps|(rad/sec)^2]: %s%d.%06d, %s%d.%06d, %s%d.%06d, "
1077           "%s%d.%08d, %s%d.%08d, %s%d.%08d",
1078           CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_x *
1079                                RAD_TO_MILLI_DEGREES,
1080                            6),
1081           CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_y *
1082                                RAD_TO_MILLI_DEGREES,
1083                            6),
1084           CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.prev_mean_z *
1085                                RAD_TO_MILLI_DEGREES,
1086                            6),
1087           CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.win_var_x, 8),
1088           CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.win_var_y, 8),
1089           CAL_ENCODE_FLOAT(gyro_cal->gyro_stillness_detect.win_var_z, 8));
1090       break;
1091 
1092     case MAG_STATS_TUNING:
1093       if (gyro_cal->using_mag_sensor) {
1094         CAL_DEBUG_LOG(
1095             debug_tag,
1096             "Mag Mean|Var [uT|uT^2]: %s%d.%06d, %s%d.%06d, %s%d.%06d, "
1097             "%s%d.%08d, %s%d.%08d, %s%d.%08d",
1098             CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.prev_mean_x, 6),
1099             CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.prev_mean_y, 6),
1100             CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.prev_mean_z, 6),
1101             CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.win_var_x, 8),
1102             CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.win_var_y, 8),
1103             CAL_ENCODE_FLOAT(gyro_cal->mag_stillness_detect.win_var_z, 8));
1104       } else {
1105         CAL_DEBUG_LOG(GYROCAL_TUNE_TAG,
1106                       "Mag Mean|Var [uT|uT^2]: 0, 0, 0, -1.0, -1.0, -1.0");
1107       }
1108       break;
1109 #endif  // GYRO_CAL_DBG_TUNE_ENABLED
1110 
1111     default:
1112       break;
1113   }
1114 }
1115 
gyroCalDebugPrint(struct GyroCal * gyro_cal,uint64_t timestamp_nanos)1116 void gyroCalDebugPrint(struct GyroCal* gyro_cal, uint64_t timestamp_nanos) {
1117   static enum GyroCalDebugState next_state = GYRO_IDLE;
1118   static uint64_t wait_timer_nanos = 0;
1119 
1120   // This is a state machine that controls the reporting out of debug data.
1121   switch (gyro_cal->debug_state) {
1122     case GYRO_IDLE:
1123       // Wait for a trigger and start the debug printout sequence.
1124       if (gyro_cal->debug_print_trigger) {
1125         CAL_DEBUG_LOG(GYROCAL_REPORT_TAG, "");
1126         CAL_DEBUG_LOG(GYROCAL_REPORT_TAG, "Debug Version: %s",
1127                       GYROCAL_DEBUG_VERSION_STRING);
1128         gyro_cal->debug_print_trigger = false;  // Resets trigger.
1129         gyro_cal->debug_state = GYRO_PRINT_OFFSET;
1130       } else {
1131         gyro_cal->debug_state = GYRO_IDLE;
1132       }
1133       break;
1134 
1135     case GYRO_WAIT_STATE:
1136       // This helps throttle the print statements.
1137       if (timestamp_nanos >= GYROCAL_WAIT_TIME_NANOS + wait_timer_nanos) {
1138         gyro_cal->debug_state = next_state;
1139       }
1140       break;
1141 
1142     case GYRO_PRINT_OFFSET:
1143       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, OFFSET);
1144       wait_timer_nanos = timestamp_nanos;       // Starts the wait timer.
1145       next_state = GYRO_PRINT_STILLNESS_DATA;   // Sets the next state.
1146       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1147       break;
1148 
1149     case GYRO_PRINT_STILLNESS_DATA:
1150       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, STILLNESS_DATA);
1151       wait_timer_nanos = timestamp_nanos;       // Starts the wait timer.
1152       next_state = GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE;  // Sets next state.
1153       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1154       break;
1155 
1156     case GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE:
1157       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG,
1158                             SAMPLE_RATE_AND_TEMPERATURE);
1159       wait_timer_nanos = timestamp_nanos;       // Starts the wait timer.
1160       next_state = GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN;  // Sets next state.
1161       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1162       break;
1163 
1164     case GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN:
1165       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG,
1166                             GYRO_MINMAX_STILLNESS_MEAN);
1167       wait_timer_nanos = timestamp_nanos;       // Starts the wait timer.
1168       next_state = GYRO_PRINT_ACCEL_STATS;      // Sets the next state.
1169       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1170       break;
1171 
1172     case GYRO_PRINT_ACCEL_STATS:
1173       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, ACCEL_STATS);
1174       wait_timer_nanos = timestamp_nanos;       // Starts the wait timer.
1175       next_state = GYRO_PRINT_GYRO_STATS;       // Sets the next state.
1176       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1177       break;
1178 
1179     case GYRO_PRINT_GYRO_STATS:
1180       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, GYRO_STATS);
1181       wait_timer_nanos = timestamp_nanos;       // Starts the wait timer.
1182       next_state = GYRO_PRINT_MAG_STATS;        // Sets the next state.
1183       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1184       break;
1185 
1186     case GYRO_PRINT_MAG_STATS:
1187       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, MAG_STATS);
1188       wait_timer_nanos = timestamp_nanos;       // Starts the wait timer.
1189       next_state = GYRO_IDLE;                   // Sets the next state.
1190       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1191       break;
1192 
1193     default:
1194       // Sends this state machine to its idle state.
1195       wait_timer_nanos = timestamp_nanos;       // Starts the wait timer.
1196       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1197   }
1198 
1199 #ifdef GYRO_CAL_DBG_TUNE_ENABLED
1200   if (gyro_cal->debug_state == GYRO_IDLE) {
1201     // This check keeps the tuning printout from interleaving with the above
1202     // debug print data.
1203     gyroCalTuneDebugPrint(gyro_cal, timestamp_nanos);
1204   }
1205 #endif  // GYRO_CAL_DBG_TUNE_ENABLED
1206 }
1207 
1208 #ifdef GYRO_CAL_DBG_TUNE_ENABLED
gyroCalTuneDebugPrint(const struct GyroCal * gyro_cal,uint64_t timestamp_nanos)1209 void gyroCalTuneDebugPrint(const struct GyroCal* gyro_cal,
1210                            uint64_t timestamp_nanos) {
1211   static enum GyroCalDebugState debug_state = GYRO_IDLE;
1212   static enum GyroCalDebugState next_state = GYRO_IDLE;
1213   static uint64_t wait_timer_nanos = 0;
1214 
1215   // Output sensor variance levels to assist with tuning thresholds.
1216   //   i.  Within the first 300 seconds of boot: output interval = 5
1217   //       seconds.
1218   //   ii. Thereafter: output interval is 60 seconds.
1219   bool condition_i =
1220       ((timestamp_nanos <= 300000000000) &&
1221        (timestamp_nanos > 5000000000 + wait_timer_nanos));  // nsec
1222   bool condition_ii = (timestamp_nanos > 60000000000 + wait_timer_nanos);
1223 
1224   // This is a state machine that controls the reporting out of tuning data.
1225   switch (debug_state) {
1226     case GYRO_IDLE:
1227       // Wait for a trigger and start the data tuning printout sequence.
1228       if (condition_i || condition_ii) {
1229         CAL_DEBUG_LOG(GYROCAL_TUNE_TAG, "Temp [C]: %s%d.%03d",
1230                       CAL_ENCODE_FLOAT(gyro_cal->temperature_mean_celsius, 3));
1231         wait_timer_nanos = timestamp_nanos;   // Starts the wait timer.
1232         next_state = GYRO_PRINT_ACCEL_STATS;  // Sets the next state.
1233         debug_state = GYRO_WAIT_STATE;        // First, go to wait state.
1234       } else {
1235         debug_state = GYRO_IDLE;
1236       }
1237       break;
1238 
1239     case GYRO_WAIT_STATE:
1240       // This helps throttle the print statements.
1241       if (timestamp_nanos >= GYROCAL_WAIT_TIME_NANOS + wait_timer_nanos) {
1242         debug_state = next_state;
1243       }
1244       break;
1245 
1246     case GYRO_PRINT_ACCEL_STATS:
1247       gyroCalDebugPrintData(gyro_cal, GYROCAL_TUNE_TAG, ACCEL_STATS_TUNING);
1248       wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1249       next_state = GYRO_PRINT_GYRO_STATS;  // Sets the next state.
1250       debug_state = GYRO_WAIT_STATE;       // First, go to wait state.
1251       break;
1252 
1253     case GYRO_PRINT_GYRO_STATS:
1254       gyroCalDebugPrintData(gyro_cal, GYROCAL_TUNE_TAG, GYRO_STATS_TUNING);
1255       wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1256       next_state = GYRO_PRINT_MAG_STATS;   // Sets the next state.
1257       debug_state = GYRO_WAIT_STATE;       // First, go to wait state.
1258       break;
1259 
1260     case GYRO_PRINT_MAG_STATS:
1261       gyroCalDebugPrintData(gyro_cal, GYROCAL_TUNE_TAG, MAG_STATS_TUNING);
1262       wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1263       next_state = GYRO_IDLE;              // Sets the next state.
1264       debug_state = GYRO_WAIT_STATE;       // First, go to wait state.
1265       break;
1266 
1267     default:
1268       // Sends this state machine to its idle state.
1269       wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1270       debug_state = GYRO_IDLE;
1271   }
1272 }
1273 #endif  // GYRO_CAL_DBG_TUNE_ENABLED
1274 #endif  // GYRO_CAL_DBG_ENABLED
1275