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 <inttypes.h>
21 #include <math.h>
22 #include <string.h>
23 
24 #include "calibration/util/cal_log.h"
25 #include "common/math/macros.h"
26 
27 /////// DEFINITIONS AND MACROS ///////////////////////////////////////
28 
29 // Maximum gyro bias correction (should be set based on expected max bias
30 // of the given sensor).
31 #define MAX_GYRO_BIAS (0.2f)  // [rad/sec]
32 
33 // Watchdog timeout value (5 seconds). Monitors dropouts in sensor data and
34 // resets when exceeded.
35 #define GYRO_WATCHDOG_TIMEOUT_NANOS (SEC_TO_NANOS(5))
36 
37 #ifdef GYRO_CAL_DBG_ENABLED
38 // The time value used to throttle debug messaging.
39 #define GYROCAL_WAIT_TIME_NANOS (MSEC_TO_NANOS(100))
40 
41 // A debug version label to help with tracking results.
42 #define GYROCAL_DEBUG_VERSION_STRING "[July 05, 2017]"
43 
44 // Parameters used for sample rate estimation.
45 #define GYROCAL_DEBUG_SAMPLE_RATE_NUM_INTERVALS (100)
46 #define GYROCAL_DEBUG_SAMPLE_RATE_GAP_SEC (1.0f)
47 
48 // Debug log tag string used to identify debug report output data.
49 #define GYROCAL_REPORT_TAG "[GYRO_CAL:REPORT]"
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 // Updates the information used for debug printouts.
112 static void gyroCalUpdateDebug(struct GyroCal* gyro_cal);
113 
114 // Helper function for printing out common debug data.
115 static void gyroCalDebugPrintData(const struct GyroCal* gyro_cal,
116                                   char* debug_tag,
117                                   enum DebugPrintData print_data);
118 #endif  // GYRO_CAL_DBG_ENABLED
119 
120 /////// FUNCTION DEFINITIONS /////////////////////////////////////////
121 
122 // Initialize the gyro calibration data structure.
gyroCalInit(struct GyroCal * gyro_cal,const struct GyroCalParameters * parameters)123 void gyroCalInit(struct GyroCal* gyro_cal,
124                  const struct GyroCalParameters* parameters) {
125   // Clear gyro_cal structure memory.
126   memset(gyro_cal, 0, sizeof(struct GyroCal));
127 
128   // Initialize the stillness detectors.
129   // Gyro parameter input units are [rad/sec].
130   // Accel parameter input units are [m/sec^2].
131   // Magnetometer parameter input units are [uT].
132   gyroStillDetInit(&gyro_cal->gyro_stillness_detect,
133                    parameters->gyro_var_threshold,
134                    parameters->gyro_confidence_delta);
135   gyroStillDetInit(&gyro_cal->accel_stillness_detect,
136                    parameters->accel_var_threshold,
137                    parameters->accel_confidence_delta);
138   gyroStillDetInit(&gyro_cal->mag_stillness_detect,
139                    parameters->mag_var_threshold,
140                    parameters->mag_confidence_delta);
141 
142   // Reset stillness flag and start timestamp.
143   gyro_cal->prev_still = false;
144   gyro_cal->start_still_time_nanos = 0;
145 
146   // Set the min and max window stillness duration.
147   gyro_cal->min_still_duration_nanos = parameters->min_still_duration_nanos;
148   gyro_cal->max_still_duration_nanos = parameters->max_still_duration_nanos;
149 
150   // Sets the duration of the stillness processing windows.
151   gyro_cal->window_time_duration_nanos = parameters->window_time_duration_nanos;
152 
153   // Set the watchdog timeout duration.
154   gyro_cal->gyro_watchdog_timeout_duration_nanos = GYRO_WATCHDOG_TIMEOUT_NANOS;
155 
156   // Load the last valid cal from system memory.
157   gyro_cal->bias_x = parameters->bias_x;  // [rad/sec]
158   gyro_cal->bias_y = parameters->bias_y;  // [rad/sec]
159   gyro_cal->bias_z = parameters->bias_z;  // [rad/sec]
160   gyro_cal->calibration_time_nanos = parameters->calibration_time_nanos;
161 
162   // Set the stillness threshold required for gyro bias calibration.
163   gyro_cal->stillness_threshold = parameters->stillness_threshold;
164 
165   // Current window end-time used to assist in keeping sensor data collection in
166   // sync. Setting this to zero signals that sensor data will be dropped until a
167   // valid end-time is set from the first gyro timestamp received.
168   gyro_cal->stillness_win_endtime_nanos = 0;
169 
170   // Gyro calibrations will be applied (see, gyroCalRemoveBias()).
171   gyro_cal->gyro_calibration_enable = (parameters->gyro_calibration_enable > 0);
172 
173   // Sets the stability limit for the stillness window mean acceptable delta.
174   gyro_cal->stillness_mean_delta_limit = parameters->stillness_mean_delta_limit;
175 
176   // Sets the min/max temperature delta limit for the stillness period.
177   gyro_cal->temperature_delta_limit_celsius =
178       parameters->temperature_delta_limit_celsius;
179 
180   // Ensures that the data tracking functionality is reset.
181   gyroStillMeanTracker(gyro_cal, DO_RESET);
182   gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
183 
184 #ifdef GYRO_CAL_DBG_ENABLED
185   if (gyro_cal->gyro_calibration_enable) {
186     CAL_DEBUG_LOG("[GYRO_CAL:INIT]", "Online gyroscope calibration ENABLED.");
187   } else {
188     CAL_DEBUG_LOG("[GYRO_CAL:INIT]", "Online gyroscope calibration DISABLED.");
189   }
190 
191   // Initializes the gyro sampling rate estimator.
192   sampleRateEstimatorInit(&gyro_cal->debug_gyro_cal.sample_rate_estimator,
193                           GYROCAL_DEBUG_SAMPLE_RATE_NUM_INTERVALS,
194                           GYROCAL_DEBUG_SAMPLE_RATE_GAP_SEC);
195 #endif  // GYRO_CAL_DBG_ENABLED
196 }
197 
198 // Void pointer in the gyro calibration data structure (doesn't do anything
199 // except prevent compiler warnings).
gyroCalDestroy(struct GyroCal * gyro_cal)200 void gyroCalDestroy(struct GyroCal* gyro_cal) { (void)gyro_cal; }
201 
202 // Get the most recent bias calibration value.
gyroCalGetBias(struct GyroCal * gyro_cal,float * bias_x,float * bias_y,float * bias_z,float * temperature_celsius,uint64_t * calibration_time_nanos)203 void gyroCalGetBias(struct GyroCal* gyro_cal, float* bias_x, float* bias_y,
204                     float* bias_z, float* temperature_celsius,
205                     uint64_t* calibration_time_nanos) {
206   *bias_x = gyro_cal->bias_x;
207   *bias_y = gyro_cal->bias_y;
208   *bias_z = gyro_cal->bias_z;
209   *calibration_time_nanos = gyro_cal->calibration_time_nanos;
210   *temperature_celsius = gyro_cal->bias_temperature_celsius;
211 }
212 
213 // Set an initial bias calibration value.
gyroCalSetBias(struct GyroCal * gyro_cal,float bias_x,float bias_y,float bias_z,float temperature_celsius,uint64_t calibration_time_nanos)214 void gyroCalSetBias(struct GyroCal* gyro_cal, float bias_x, float bias_y,
215                     float bias_z, float temperature_celsius,
216                     uint64_t calibration_time_nanos) {
217   gyro_cal->bias_x = bias_x;
218   gyro_cal->bias_y = bias_y;
219   gyro_cal->bias_z = bias_z;
220   gyro_cal->calibration_time_nanos = calibration_time_nanos;
221   gyro_cal->bias_temperature_celsius = temperature_celsius;
222 
223 #ifdef GYRO_CAL_DBG_ENABLED
224   CAL_DEBUG_LOG("[GYRO_CAL:SET BIAS]",
225                 "Offset|Temp|Time [mDPS|C|nsec]: " CAL_FORMAT_3DIGITS_TRIPLET
226                 ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
227                 CAL_ENCODE_FLOAT(bias_x * RAD_TO_MDEG, 3),
228                 CAL_ENCODE_FLOAT(bias_y * RAD_TO_MDEG, 3),
229                 CAL_ENCODE_FLOAT(bias_z * RAD_TO_MDEG, 3),
230                 CAL_ENCODE_FLOAT(temperature_celsius, 3),
231                 calibration_time_nanos);
232 #endif  // GYRO_CAL_DBG_ENABLED
233 }
234 
235 // 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)236 void gyroCalRemoveBias(struct GyroCal* gyro_cal, float xi, float yi, float zi,
237                        float* xo, float* yo, float* zo) {
238   if (gyro_cal->gyro_calibration_enable) {
239     *xo = xi - gyro_cal->bias_x;
240     *yo = yi - gyro_cal->bias_y;
241     *zo = zi - gyro_cal->bias_z;
242   }
243 }
244 
245 // Returns true when a new gyro calibration is available.
gyroCalNewBiasAvailable(struct GyroCal * gyro_cal)246 bool gyroCalNewBiasAvailable(struct GyroCal* gyro_cal) {
247   bool new_gyro_cal_available =
248       (gyro_cal->gyro_calibration_enable && gyro_cal->new_gyro_cal_available);
249 
250   // Clear the flag.
251   gyro_cal->new_gyro_cal_available = false;
252 
253   return new_gyro_cal_available;
254 }
255 
256 // 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)257 void gyroCalUpdateGyro(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
258                        float x, float y, float z, float temperature_celsius) {
259   // Make sure that a valid window end-time is set, and start the watchdog
260   // timer.
261   if (gyro_cal->stillness_win_endtime_nanos <= 0) {
262     gyro_cal->stillness_win_endtime_nanos =
263         sample_time_nanos + gyro_cal->window_time_duration_nanos;
264 
265     // Start the watchdog timer.
266     gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
267   }
268 
269   // Update the temperature statistics.
270   gyroTemperatureStatsTracker(gyro_cal, temperature_celsius, DO_UPDATE_DATA);
271 
272 #ifdef GYRO_CAL_DBG_ENABLED
273   // Update the gyro sampling rate estimate.
274   sampleRateEstimatorUpdate(&gyro_cal->debug_gyro_cal.sample_rate_estimator,
275                             sample_time_nanos);
276 #endif  // GYRO_CAL_DBG_ENABLED
277 
278   // Pass gyro data to stillness detector
279   gyroStillDetUpdate(&gyro_cal->gyro_stillness_detect,
280                      gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
281                      x, y, z);
282 
283   // Perform a device stillness check, set next window end-time, and
284   // possibly do a gyro bias calibration and stillness detector reset.
285   deviceStillnessCheck(gyro_cal, sample_time_nanos);
286 }
287 
288 // 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)289 void gyroCalUpdateMag(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
290                       float x, float y, float z) {
291   // Pass magnetometer data to stillness detector.
292   gyroStillDetUpdate(&gyro_cal->mag_stillness_detect,
293                      gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
294                      x, y, z);
295 
296   // Received a magnetometer sample; incorporate it into detection.
297   gyro_cal->using_mag_sensor = true;
298 
299   // Perform a device stillness check, set next window end-time, and
300   // possibly do a gyro bias calibration and stillness detector reset.
301   deviceStillnessCheck(gyro_cal, sample_time_nanos);
302 }
303 
304 // 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)305 void gyroCalUpdateAccel(struct GyroCal* gyro_cal, uint64_t sample_time_nanos,
306                         float x, float y, float z) {
307   // Pass accelerometer data to stillnesss detector.
308   gyroStillDetUpdate(&gyro_cal->accel_stillness_detect,
309                      gyro_cal->stillness_win_endtime_nanos, sample_time_nanos,
310                      x, y, z);
311 
312   // Perform a device stillness check, set next window end-time, and
313   // possibly do a gyro bias calibration and stillness detector reset.
314   deviceStillnessCheck(gyro_cal, sample_time_nanos);
315 }
316 
317 // TODO: Consider breaking this function up to improve readability.
318 // Checks the state of all stillness detectors to determine
319 // whether the device is "still".
deviceStillnessCheck(struct GyroCal * gyro_cal,uint64_t sample_time_nanos)320 void deviceStillnessCheck(struct GyroCal* gyro_cal,
321                           uint64_t sample_time_nanos) {
322   bool stillness_duration_exceeded = false;
323   bool stillness_duration_too_short = false;
324   bool min_max_temp_exceeded = false;
325   bool mean_not_stable = false;
326   bool device_is_still = false;
327   float conf_not_rot = 0;
328   float conf_not_accel = 0;
329   float conf_still = 0;
330 
331   // Check the watchdog timer.
332   checkWatchdog(gyro_cal, sample_time_nanos);
333 
334   // Is there enough data to do a stillness calculation?
335   if ((!gyro_cal->mag_stillness_detect.stillness_window_ready &&
336        gyro_cal->using_mag_sensor) ||
337       !gyro_cal->accel_stillness_detect.stillness_window_ready ||
338       !gyro_cal->gyro_stillness_detect.stillness_window_ready) {
339     return;  // Not yet, wait for more data.
340   }
341 
342   // Set the next window end-time for the stillness detectors.
343   gyro_cal->stillness_win_endtime_nanos =
344       sample_time_nanos + gyro_cal->window_time_duration_nanos;
345 
346   // Update the confidence scores for all sensors.
347   gyroStillDetCompute(&gyro_cal->accel_stillness_detect);
348   gyroStillDetCompute(&gyro_cal->gyro_stillness_detect);
349   if (gyro_cal->using_mag_sensor) {
350     gyroStillDetCompute(&gyro_cal->mag_stillness_detect);
351   } else {
352     // Not using magnetometer, force stillness confidence to 100%.
353     gyro_cal->mag_stillness_detect.stillness_confidence = 1.0f;
354   }
355 
356   // Updates the mean tracker data.
357   gyroStillMeanTracker(gyro_cal, DO_UPDATE_DATA);
358 
359   // Determine motion confidence scores (rotation, accelerating, and stillness).
360   conf_not_rot = gyro_cal->gyro_stillness_detect.stillness_confidence *
361                  gyro_cal->mag_stillness_detect.stillness_confidence;
362   conf_not_accel = gyro_cal->accel_stillness_detect.stillness_confidence;
363   conf_still = conf_not_rot * conf_not_accel;
364 
365   // Evaluate the mean and temperature gate functions.
366   mean_not_stable = gyroStillMeanTracker(gyro_cal, DO_EVALUATE);
367   min_max_temp_exceeded =
368       gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_EVALUATE);
369 
370   // Determines if the device is currently still.
371   device_is_still = (conf_still > gyro_cal->stillness_threshold) &&
372                     !mean_not_stable && !min_max_temp_exceeded;
373 
374   if (device_is_still) {
375     // Device is "still" logic:
376     // If not previously still, then record the start time.
377     // If stillness period is too long, then do a calibration.
378     // Otherwise, continue collecting stillness data.
379 
380     // If device was not previously still, set new start timestamp.
381     if (!gyro_cal->prev_still) {
382       // Record the starting timestamp of the current stillness window.
383       // This enables the calculation of total duration of the stillness period.
384       gyro_cal->start_still_time_nanos =
385           gyro_cal->gyro_stillness_detect.window_start_time;
386     }
387 
388     // Check to see if current stillness period exceeds the desired limit.
389     stillness_duration_exceeded =
390         (gyro_cal->gyro_stillness_detect.last_sample_time >=
391          gyro_cal->start_still_time_nanos + gyro_cal->max_still_duration_nanos);
392 
393     // Track the new stillness mean and temperature data.
394     gyroStillMeanTracker(gyro_cal, DO_STORE_DATA);
395     gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_STORE_DATA);
396 
397     if (stillness_duration_exceeded) {
398       // The current stillness has gone too long. Do a calibration with the
399       // current data and reset.
400 
401       // Updates the gyro bias estimate with the current window data and
402       // resets the stats.
403       gyroStillDetReset(&gyro_cal->accel_stillness_detect,
404                         /*reset_stats=*/true);
405       gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
406       gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
407 
408       // Resets the local calculations because the stillness period is over.
409       gyroStillMeanTracker(gyro_cal, DO_RESET);
410       gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
411 
412       // Computes a new gyro offset estimate.
413       computeGyroCal(gyro_cal,
414                      gyro_cal->gyro_stillness_detect.last_sample_time);
415 
416       // Update stillness flag. Force the start of a new stillness period.
417       gyro_cal->prev_still = false;
418     } else {
419       // Continue collecting stillness data.
420 
421       // Extend the stillness period.
422       gyroStillDetReset(&gyro_cal->accel_stillness_detect,
423                         /*reset_stats=*/false);
424       gyroStillDetReset(&gyro_cal->gyro_stillness_detect,
425                         /*reset_stats=*/false);
426       gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/false);
427 
428       // Update the stillness flag.
429       gyro_cal->prev_still = true;
430     }
431   } else {
432     // Device is NOT still; motion detected.
433 
434     // If device was previously still and the total stillness duration is not
435     // "too short", then do a calibration with the data accumulated thus far.
436     stillness_duration_too_short =
437         (gyro_cal->gyro_stillness_detect.window_start_time <
438          gyro_cal->start_still_time_nanos + gyro_cal->min_still_duration_nanos);
439 
440     if (gyro_cal->prev_still && !stillness_duration_too_short) {
441       computeGyroCal(gyro_cal,
442                      gyro_cal->gyro_stillness_detect.window_start_time);
443     }
444 
445     // Reset the stillness detectors and the stats.
446     gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
447     gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
448     gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
449 
450     // Resets the temperature and sensor mean data.
451     gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
452     gyroStillMeanTracker(gyro_cal, DO_RESET);
453 
454     // Update stillness flag.
455     gyro_cal->prev_still = false;
456   }
457 
458   // Reset the watchdog timer after we have processed data.
459   gyro_cal->gyro_watchdog_start_nanos = sample_time_nanos;
460 }
461 
462 // Calculates a new gyro bias offset calibration value.
computeGyroCal(struct GyroCal * gyro_cal,uint64_t calibration_time_nanos)463 void computeGyroCal(struct GyroCal* gyro_cal, uint64_t calibration_time_nanos) {
464   // Check to see if new calibration values is within acceptable range.
465   if (!(gyro_cal->gyro_stillness_detect.prev_mean_x < MAX_GYRO_BIAS &&
466         gyro_cal->gyro_stillness_detect.prev_mean_x > -MAX_GYRO_BIAS &&
467         gyro_cal->gyro_stillness_detect.prev_mean_y < MAX_GYRO_BIAS &&
468         gyro_cal->gyro_stillness_detect.prev_mean_y > -MAX_GYRO_BIAS &&
469         gyro_cal->gyro_stillness_detect.prev_mean_z < MAX_GYRO_BIAS &&
470         gyro_cal->gyro_stillness_detect.prev_mean_z > -MAX_GYRO_BIAS)) {
471 #ifdef GYRO_CAL_DBG_ENABLED
472     CAL_DEBUG_LOG(
473         "[GYRO_CAL:REJECT]",
474         "Offset|Temp|Time [mDPS|C|nsec]: " CAL_FORMAT_3DIGITS_TRIPLET
475         ", " CAL_FORMAT_3DIGITS ", %" PRIu64,
476         CAL_ENCODE_FLOAT(
477             gyro_cal->gyro_stillness_detect.prev_mean_x * RAD_TO_MDEG, 3),
478         CAL_ENCODE_FLOAT(
479             gyro_cal->gyro_stillness_detect.prev_mean_y * RAD_TO_MDEG, 3),
480         CAL_ENCODE_FLOAT(
481             gyro_cal->gyro_stillness_detect.prev_mean_z * RAD_TO_MDEG, 3),
482         CAL_ENCODE_FLOAT(gyro_cal->temperature_mean_celsius, 3),
483         calibration_time_nanos);
484 #endif  // GYRO_CAL_DBG_ENABLED
485 
486     // Outside of range. Ignore, reset, and continue.
487     return;
488   }
489 
490   // Record the new gyro bias offset calibration.
491   gyro_cal->bias_x = gyro_cal->gyro_stillness_detect.prev_mean_x;
492   gyro_cal->bias_y = gyro_cal->gyro_stillness_detect.prev_mean_y;
493   gyro_cal->bias_z = gyro_cal->gyro_stillness_detect.prev_mean_z;
494 
495   // Store the calibration temperature (using the mean temperature over the
496   // "stillness" period).
497   gyro_cal->bias_temperature_celsius = gyro_cal->temperature_mean_celsius;
498 
499   // Store the calibration time stamp.
500   gyro_cal->calibration_time_nanos = calibration_time_nanos;
501 
502   // Record the final stillness confidence.
503   gyro_cal->stillness_confidence =
504       gyro_cal->gyro_stillness_detect.prev_stillness_confidence *
505       gyro_cal->accel_stillness_detect.prev_stillness_confidence *
506       gyro_cal->mag_stillness_detect.prev_stillness_confidence;
507 
508   // Set flag to indicate a new gyro calibration value is available.
509   gyro_cal->new_gyro_cal_available = true;
510 
511 #ifdef GYRO_CAL_DBG_ENABLED
512   // Increment the total count of calibration updates.
513   gyro_cal->debug_calibration_count++;
514 
515   // Update the calibration debug information and trigger a printout.
516   gyroCalUpdateDebug(gyro_cal);
517 #endif
518 }
519 
520 // Check for a watchdog timeout condition.
checkWatchdog(struct GyroCal * gyro_cal,uint64_t sample_time_nanos)521 void checkWatchdog(struct GyroCal* gyro_cal, uint64_t sample_time_nanos) {
522   bool watchdog_timeout;
523 
524   // Check for initialization of the watchdog time (=0).
525   if (gyro_cal->gyro_watchdog_start_nanos <= 0) {
526     return;
527   }
528 
529   // Checks for the following watchdog timeout conditions:
530   //    i.  The current timestamp has exceeded the allowed watchdog duration.
531   //    ii. A timestamp was received that has jumped backwards by more than the
532   //        allowed watchdog duration (e.g., timestamp clock roll-over).
533   watchdog_timeout =
534       (sample_time_nanos > gyro_cal->gyro_watchdog_timeout_duration_nanos +
535                                gyro_cal->gyro_watchdog_start_nanos) ||
536       (sample_time_nanos + gyro_cal->gyro_watchdog_timeout_duration_nanos <
537        gyro_cal->gyro_watchdog_start_nanos);
538 
539   // If a timeout occurred then reset to known good state.
540   if (watchdog_timeout) {
541 #ifdef GYRO_CAL_DBG_ENABLED
542     gyro_cal->debug_watchdog_count++;
543     if (sample_time_nanos < gyro_cal->gyro_watchdog_start_nanos) {
544       CAL_DEBUG_LOG("[GYRO_CAL:WATCHDOG]",
545                     "Total#, Timestamp | Delta [nsec]: %zu, %" PRIu64
546                     ", -%" PRIu64,
547                     gyro_cal->debug_watchdog_count, sample_time_nanos,
548                     gyro_cal->gyro_watchdog_start_nanos - sample_time_nanos);
549     } else {
550       CAL_DEBUG_LOG("[GYRO_CAL:WATCHDOG]",
551                     "Total#, Timestamp | Delta  [nsec]: %zu, %" PRIu64
552                     ", %" PRIu64,
553                     gyro_cal->debug_watchdog_count, sample_time_nanos,
554                     sample_time_nanos - gyro_cal->gyro_watchdog_start_nanos);
555     }
556 #endif  // GYRO_CAL_DBG_ENABLED
557 
558     // Reset stillness detectors and restart data capture.
559     gyroStillDetReset(&gyro_cal->accel_stillness_detect, /*reset_stats=*/true);
560     gyroStillDetReset(&gyro_cal->gyro_stillness_detect, /*reset_stats=*/true);
561     gyroStillDetReset(&gyro_cal->mag_stillness_detect, /*reset_stats=*/true);
562 
563     // Resets the temperature and sensor mean data.
564     gyroTemperatureStatsTracker(gyro_cal, 0.0f, DO_RESET);
565     gyroStillMeanTracker(gyro_cal, DO_RESET);
566 
567     // Resets the stillness window end-time.
568     gyro_cal->stillness_win_endtime_nanos = 0;
569 
570     // Force stillness confidence to zero.
571     gyro_cal->accel_stillness_detect.prev_stillness_confidence = 0;
572     gyro_cal->gyro_stillness_detect.prev_stillness_confidence = 0;
573     gyro_cal->mag_stillness_detect.prev_stillness_confidence = 0;
574     gyro_cal->stillness_confidence = 0;
575     gyro_cal->prev_still = false;
576 
577     // If there are no magnetometer samples being received then
578     // operate the calibration algorithm without this sensor.
579     if (!gyro_cal->mag_stillness_detect.stillness_window_ready &&
580         gyro_cal->using_mag_sensor) {
581       gyro_cal->using_mag_sensor = false;
582     }
583 
584     // Assert watchdog timeout flags.
585     gyro_cal->gyro_watchdog_start_nanos = 0;
586   }
587 }
588 
589 // TODO -- Combine the following two functions into one or consider
590 // implementing a separate helper module for tracking the temperature and mean
591 // statistics.
gyroTemperatureStatsTracker(struct GyroCal * gyro_cal,float temperature_celsius,enum GyroCalTrackerCommand do_this)592 bool gyroTemperatureStatsTracker(struct GyroCal* gyro_cal,
593                                  float temperature_celsius,
594                                  enum GyroCalTrackerCommand do_this) {
595   bool min_max_temp_exceeded = false;
596 
597   switch (do_this) {
598     case DO_RESET:
599       // Resets the mean accumulator.
600       gyro_cal->temperature_mean_tracker.num_points = 0;
601       gyro_cal->temperature_mean_tracker.mean_accumulator = 0.0f;
602 
603       // Initializes the min/max temperatures values.
604       gyro_cal->temperature_mean_tracker.temperature_min_celsius = FLT_MAX;
605       gyro_cal->temperature_mean_tracker.temperature_max_celsius = -FLT_MAX;
606       break;
607 
608     case DO_UPDATE_DATA:
609       // Does the mean accumulation.
610       gyro_cal->temperature_mean_tracker.mean_accumulator +=
611           temperature_celsius;
612       gyro_cal->temperature_mean_tracker.num_points++;
613 
614       // Tracks the min, max, and latest temperature values.
615       gyro_cal->temperature_mean_tracker.latest_temperature_celsius =
616           temperature_celsius;
617       if (gyro_cal->temperature_mean_tracker.temperature_min_celsius >
618           temperature_celsius) {
619         gyro_cal->temperature_mean_tracker.temperature_min_celsius =
620             temperature_celsius;
621       }
622       if (gyro_cal->temperature_mean_tracker.temperature_max_celsius <
623           temperature_celsius) {
624         gyro_cal->temperature_mean_tracker.temperature_max_celsius =
625             temperature_celsius;
626       }
627       break;
628 
629     case DO_STORE_DATA:
630       // Store the most recent temperature statistics data to the GyroCal data
631       // structure. This functionality allows previous results to be recalled
632       // when the device suddenly becomes "not still".
633       if (gyro_cal->temperature_mean_tracker.num_points > 0) {
634         gyro_cal->temperature_mean_celsius =
635             gyro_cal->temperature_mean_tracker.mean_accumulator /
636             gyro_cal->temperature_mean_tracker.num_points;
637       } else {
638         gyro_cal->temperature_mean_celsius =
639             gyro_cal->temperature_mean_tracker.latest_temperature_celsius;
640 #ifdef GYRO_CAL_DBG_ENABLED
641         CAL_DEBUG_LOG("[GYRO_CAL:TEMP_GATE]",
642                       "Insufficient statistics (num_points = 0), using latest "
643                       "measured temperature as the mean value.");
644 #endif  // GYRO_CAL_DBG_ENABLED
645       }
646 #ifdef GYRO_CAL_DBG_ENABLED
647       // Records the min/max and mean temperature values for debug purposes.
648       gyro_cal->debug_gyro_cal.temperature_mean_celsius =
649           gyro_cal->temperature_mean_celsius;
650       gyro_cal->debug_gyro_cal.temperature_min_celsius =
651           gyro_cal->temperature_mean_tracker.temperature_min_celsius;
652       gyro_cal->debug_gyro_cal.temperature_max_celsius =
653           gyro_cal->temperature_mean_tracker.temperature_max_celsius;
654 #endif
655       break;
656 
657     case DO_EVALUATE:
658       // Determines if the min/max delta exceeded the set limit.
659       if (gyro_cal->temperature_mean_tracker.num_points > 0) {
660         min_max_temp_exceeded =
661             (gyro_cal->temperature_mean_tracker.temperature_max_celsius -
662              gyro_cal->temperature_mean_tracker.temperature_min_celsius) >
663             gyro_cal->temperature_delta_limit_celsius;
664 
665 #ifdef GYRO_CAL_DBG_ENABLED
666         if (min_max_temp_exceeded) {
667           CAL_DEBUG_LOG(
668               "[GYRO_CAL:TEMP_GATE]",
669               "Exceeded the max temperature variation during stillness.");
670         }
671 #endif  // GYRO_CAL_DBG_ENABLED
672       }
673       break;
674 
675     default:
676       break;
677   }
678 
679   return min_max_temp_exceeded;
680 }
681 
gyroStillMeanTracker(struct GyroCal * gyro_cal,enum GyroCalTrackerCommand do_this)682 bool gyroStillMeanTracker(struct GyroCal* gyro_cal,
683                           enum GyroCalTrackerCommand do_this) {
684   bool mean_not_stable = false;
685 
686   switch (do_this) {
687     case DO_RESET:
688       // Resets the min/max window mean values to a default value.
689       for (size_t i = 0; i < 3; i++) {
690         gyro_cal->window_mean_tracker.gyro_winmean_min[i] = FLT_MAX;
691         gyro_cal->window_mean_tracker.gyro_winmean_max[i] = -FLT_MAX;
692       }
693       break;
694 
695     case DO_UPDATE_DATA:
696       // Computes the min/max window mean values.
697       if (gyro_cal->window_mean_tracker.gyro_winmean_min[0] >
698           gyro_cal->gyro_stillness_detect.win_mean_x) {
699         gyro_cal->window_mean_tracker.gyro_winmean_min[0] =
700             gyro_cal->gyro_stillness_detect.win_mean_x;
701       }
702       if (gyro_cal->window_mean_tracker.gyro_winmean_max[0] <
703           gyro_cal->gyro_stillness_detect.win_mean_x) {
704         gyro_cal->window_mean_tracker.gyro_winmean_max[0] =
705             gyro_cal->gyro_stillness_detect.win_mean_x;
706       }
707 
708       if (gyro_cal->window_mean_tracker.gyro_winmean_min[1] >
709           gyro_cal->gyro_stillness_detect.win_mean_y) {
710         gyro_cal->window_mean_tracker.gyro_winmean_min[1] =
711             gyro_cal->gyro_stillness_detect.win_mean_y;
712       }
713       if (gyro_cal->window_mean_tracker.gyro_winmean_max[1] <
714           gyro_cal->gyro_stillness_detect.win_mean_y) {
715         gyro_cal->window_mean_tracker.gyro_winmean_max[1] =
716             gyro_cal->gyro_stillness_detect.win_mean_y;
717       }
718 
719       if (gyro_cal->window_mean_tracker.gyro_winmean_min[2] >
720           gyro_cal->gyro_stillness_detect.win_mean_z) {
721         gyro_cal->window_mean_tracker.gyro_winmean_min[2] =
722             gyro_cal->gyro_stillness_detect.win_mean_z;
723       }
724       if (gyro_cal->window_mean_tracker.gyro_winmean_max[2] <
725           gyro_cal->gyro_stillness_detect.win_mean_z) {
726         gyro_cal->window_mean_tracker.gyro_winmean_max[2] =
727             gyro_cal->gyro_stillness_detect.win_mean_z;
728       }
729       break;
730 
731     case DO_STORE_DATA:
732       // Store the most recent "stillness" mean data to the GyroCal data
733       // structure. This functionality allows previous results to be recalled
734       // when the device suddenly becomes "not still".
735       memcpy(gyro_cal->gyro_winmean_min,
736              gyro_cal->window_mean_tracker.gyro_winmean_min,
737              sizeof(gyro_cal->window_mean_tracker.gyro_winmean_min));
738       memcpy(gyro_cal->gyro_winmean_max,
739              gyro_cal->window_mean_tracker.gyro_winmean_max,
740              sizeof(gyro_cal->window_mean_tracker.gyro_winmean_max));
741       break;
742 
743     case DO_EVALUATE:
744       // Performs the stability check and returns the 'true' if the difference
745       // between min/max window mean value is outside the stable range.
746       for (size_t i = 0; i < 3; i++) {
747         mean_not_stable |= (gyro_cal->window_mean_tracker.gyro_winmean_max[i] -
748                             gyro_cal->window_mean_tracker.gyro_winmean_min[i]) >
749                            gyro_cal->stillness_mean_delta_limit;
750       }
751 #ifdef GYRO_CAL_DBG_ENABLED
752       if (mean_not_stable) {
753         CAL_DEBUG_LOG(
754             "[GYRO_CAL:MEAN_STABILITY_GATE]",
755             "Variation Limit|Delta [mDPS]: " CAL_FORMAT_3DIGITS
756             " | " CAL_FORMAT_3DIGITS_TRIPLET,
757             CAL_ENCODE_FLOAT(gyro_cal->stillness_mean_delta_limit * RAD_TO_MDEG,
758                              3),
759             CAL_ENCODE_FLOAT(
760                 (gyro_cal->window_mean_tracker.gyro_winmean_max[0] -
761                  gyro_cal->window_mean_tracker.gyro_winmean_min[0]) *
762                     RAD_TO_MDEG,
763                 3),
764             CAL_ENCODE_FLOAT(
765                 (gyro_cal->window_mean_tracker.gyro_winmean_max[1] -
766                  gyro_cal->window_mean_tracker.gyro_winmean_min[1]) *
767                     RAD_TO_MDEG,
768                 3),
769             CAL_ENCODE_FLOAT(
770                 (gyro_cal->window_mean_tracker.gyro_winmean_max[2] -
771                  gyro_cal->window_mean_tracker.gyro_winmean_min[2]) *
772                     RAD_TO_MDEG,
773                 3));
774       }
775 #endif  // GYRO_CAL_DBG_ENABLED
776       break;
777 
778     default:
779       break;
780   }
781 
782   return mean_not_stable;
783 }
784 
785 #ifdef GYRO_CAL_DBG_ENABLED
gyroCalUpdateDebug(struct GyroCal * gyro_cal)786 void gyroCalUpdateDebug(struct GyroCal* gyro_cal) {
787   // Only update this data if debug printing is not currently in progress
788   // (i.e., don't want to risk overwriting debug information that is actively
789   // being reported).
790   if (gyro_cal->debug_state != GYRO_IDLE) {
791     return;
792   }
793 
794   // Probability of stillness (acc, rot, still), duration, timestamp.
795   gyro_cal->debug_gyro_cal.accel_stillness_conf =
796       gyro_cal->accel_stillness_detect.prev_stillness_confidence;
797   gyro_cal->debug_gyro_cal.gyro_stillness_conf =
798       gyro_cal->gyro_stillness_detect.prev_stillness_confidence;
799   gyro_cal->debug_gyro_cal.mag_stillness_conf =
800       gyro_cal->mag_stillness_detect.prev_stillness_confidence;
801 
802   // Magnetometer usage.
803   gyro_cal->debug_gyro_cal.using_mag_sensor = gyro_cal->using_mag_sensor;
804 
805   // Stillness start, stop, and duration times.
806   gyro_cal->debug_gyro_cal.start_still_time_nanos =
807       gyro_cal->start_still_time_nanos;
808   gyro_cal->debug_gyro_cal.end_still_time_nanos =
809       gyro_cal->calibration_time_nanos;
810   gyro_cal->debug_gyro_cal.stillness_duration_nanos =
811       gyro_cal->calibration_time_nanos - gyro_cal->start_still_time_nanos;
812 
813   // Records the current calibration values.
814   gyro_cal->debug_gyro_cal.calibration[0] = gyro_cal->bias_x;
815   gyro_cal->debug_gyro_cal.calibration[1] = gyro_cal->bias_y;
816   gyro_cal->debug_gyro_cal.calibration[2] = gyro_cal->bias_z;
817 
818   // Records the min/max gyroscope window stillness mean values.
819   memcpy(gyro_cal->debug_gyro_cal.gyro_winmean_min, gyro_cal->gyro_winmean_min,
820          sizeof(gyro_cal->gyro_winmean_min));
821   memcpy(gyro_cal->debug_gyro_cal.gyro_winmean_max, gyro_cal->gyro_winmean_max,
822          sizeof(gyro_cal->gyro_winmean_max));
823 
824   // Records the previous stillness window means.
825   gyro_cal->debug_gyro_cal.accel_mean[0] =
826       gyro_cal->accel_stillness_detect.prev_mean_x;
827   gyro_cal->debug_gyro_cal.accel_mean[1] =
828       gyro_cal->accel_stillness_detect.prev_mean_y;
829   gyro_cal->debug_gyro_cal.accel_mean[2] =
830       gyro_cal->accel_stillness_detect.prev_mean_z;
831 
832   gyro_cal->debug_gyro_cal.gyro_mean[0] =
833       gyro_cal->gyro_stillness_detect.prev_mean_x;
834   gyro_cal->debug_gyro_cal.gyro_mean[1] =
835       gyro_cal->gyro_stillness_detect.prev_mean_y;
836   gyro_cal->debug_gyro_cal.gyro_mean[2] =
837       gyro_cal->gyro_stillness_detect.prev_mean_z;
838 
839   gyro_cal->debug_gyro_cal.mag_mean[0] =
840       gyro_cal->mag_stillness_detect.prev_mean_x;
841   gyro_cal->debug_gyro_cal.mag_mean[1] =
842       gyro_cal->mag_stillness_detect.prev_mean_y;
843   gyro_cal->debug_gyro_cal.mag_mean[2] =
844       gyro_cal->mag_stillness_detect.prev_mean_z;
845 
846   // Records the variance data.
847   // NOTE: These statistics include the final captured window, which may be
848   // outside of the "stillness" period. Therefore, these values may exceed the
849   // stillness thresholds.
850   gyro_cal->debug_gyro_cal.accel_var[0] =
851       gyro_cal->accel_stillness_detect.win_var_x;
852   gyro_cal->debug_gyro_cal.accel_var[1] =
853       gyro_cal->accel_stillness_detect.win_var_y;
854   gyro_cal->debug_gyro_cal.accel_var[2] =
855       gyro_cal->accel_stillness_detect.win_var_z;
856 
857   gyro_cal->debug_gyro_cal.gyro_var[0] =
858       gyro_cal->gyro_stillness_detect.win_var_x;
859   gyro_cal->debug_gyro_cal.gyro_var[1] =
860       gyro_cal->gyro_stillness_detect.win_var_y;
861   gyro_cal->debug_gyro_cal.gyro_var[2] =
862       gyro_cal->gyro_stillness_detect.win_var_z;
863 
864   gyro_cal->debug_gyro_cal.mag_var[0] =
865       gyro_cal->mag_stillness_detect.win_var_x;
866   gyro_cal->debug_gyro_cal.mag_var[1] =
867       gyro_cal->mag_stillness_detect.win_var_y;
868   gyro_cal->debug_gyro_cal.mag_var[2] =
869       gyro_cal->mag_stillness_detect.win_var_z;
870 
871   // Trigger a printout of the debug information.
872   gyro_cal->debug_print_trigger = true;
873 }
874 
gyroCalDebugPrintData(const struct GyroCal * gyro_cal,char * debug_tag,enum DebugPrintData print_data)875 void gyroCalDebugPrintData(const struct GyroCal* gyro_cal, char* debug_tag,
876                            enum DebugPrintData print_data) {
877   // Prints out the desired debug data.
878   float mag_data;
879   switch (print_data) {
880     case OFFSET:
881       CAL_DEBUG_LOG(
882           debug_tag,
883           "Cal#|Offset|Temp|Time [mDPS|C|nsec]: "
884           "%zu, " CAL_FORMAT_3DIGITS_TRIPLET ", " CAL_FORMAT_3DIGITS
885           ", %" PRIu64,
886           gyro_cal->debug_calibration_count,
887           CAL_ENCODE_FLOAT(
888               gyro_cal->debug_gyro_cal.calibration[0] * RAD_TO_MDEG, 3),
889           CAL_ENCODE_FLOAT(
890               gyro_cal->debug_gyro_cal.calibration[1] * RAD_TO_MDEG, 3),
891           CAL_ENCODE_FLOAT(
892               gyro_cal->debug_gyro_cal.calibration[2] * RAD_TO_MDEG, 3),
893           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_mean_celsius,
894                            3),
895           gyro_cal->debug_gyro_cal.end_still_time_nanos);
896       break;
897 
898     case STILLNESS_DATA:
899       mag_data = (gyro_cal->debug_gyro_cal.using_mag_sensor)
900                      ? gyro_cal->debug_gyro_cal.mag_stillness_conf
901                      : -1.0f;  // Signals that magnetometer was not used.
902       CAL_DEBUG_LOG(
903           debug_tag,
904           "Cal#|Stillness|Confidence [nsec]: %zu, "
905           "%" PRIu64 ", " CAL_FORMAT_3DIGITS_TRIPLET,
906           gyro_cal->debug_calibration_count,
907           gyro_cal->debug_gyro_cal.end_still_time_nanos -
908               gyro_cal->debug_gyro_cal.start_still_time_nanos,
909           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_stillness_conf, 3),
910           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_stillness_conf, 3),
911           CAL_ENCODE_FLOAT(mag_data, 3));
912       break;
913 
914     case SAMPLE_RATE_AND_TEMPERATURE:
915       CAL_DEBUG_LOG(
916           debug_tag,
917           "Cal#|Mean|Min|Max|Delta|Sample Rate [C|Hz]: "
918           "%zu, " CAL_FORMAT_3DIGITS_TRIPLET ", " CAL_FORMAT_3DIGITS
919           ", " CAL_FORMAT_3DIGITS,
920           gyro_cal->debug_calibration_count,
921           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_mean_celsius,
922                            3),
923           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_min_celsius, 3),
924           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_max_celsius, 3),
925           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.temperature_max_celsius -
926                                gyro_cal->debug_gyro_cal.temperature_min_celsius,
927                            3),
928           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.sample_rate_estimator
929                                .mean_sampling_rate_estimate_hz,
930                            3));
931       break;
932 
933     case GYRO_MINMAX_STILLNESS_MEAN:
934       CAL_DEBUG_LOG(
935           debug_tag,
936           "Cal#|Gyro Peak Stillness Variation [mDPS]: "
937           "%zu, " CAL_FORMAT_3DIGITS_TRIPLET,
938           gyro_cal->debug_calibration_count,
939           CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[0] -
940                             gyro_cal->debug_gyro_cal.gyro_winmean_min[0]) *
941                                RAD_TO_MDEG,
942                            3),
943           CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[1] -
944                             gyro_cal->debug_gyro_cal.gyro_winmean_min[1]) *
945                                RAD_TO_MDEG,
946                            3),
947           CAL_ENCODE_FLOAT((gyro_cal->debug_gyro_cal.gyro_winmean_max[2] -
948                             gyro_cal->debug_gyro_cal.gyro_winmean_min[2]) *
949                                RAD_TO_MDEG,
950                            3));
951       break;
952 
953     case ACCEL_STATS:
954       CAL_DEBUG_LOG(debug_tag,
955                     "Cal#|Accel Mean|Var [m/sec^2|(m/sec^2)^2]: "
956                     "%zu, " CAL_FORMAT_3DIGITS_TRIPLET
957                     ", " CAL_FORMAT_6DIGITS_TRIPLET,
958                     gyro_cal->debug_calibration_count,
959                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[0], 3),
960                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[1], 3),
961                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_mean[2], 3),
962                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[0], 6),
963                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[1], 6),
964                     CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.accel_var[2], 6));
965       break;
966 
967     case GYRO_STATS:
968       CAL_DEBUG_LOG(
969           debug_tag,
970           "Cal#|Gyro Mean|Var [mDPS|mDPS^2]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET
971           ", " CAL_FORMAT_3DIGITS_TRIPLET,
972           gyro_cal->debug_calibration_count,
973           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_mean[0] * RAD_TO_MDEG,
974                            3),
975           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_mean[1] * RAD_TO_MDEG,
976                            3),
977           CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.gyro_mean[2] * RAD_TO_MDEG,
978                            3),
979           CAL_ENCODE_FLOAT(
980               gyro_cal->debug_gyro_cal.gyro_var[0] * RAD_TO_MDEG * RAD_TO_MDEG,
981               3),
982           CAL_ENCODE_FLOAT(
983               gyro_cal->debug_gyro_cal.gyro_var[1] * RAD_TO_MDEG * RAD_TO_MDEG,
984               3),
985           CAL_ENCODE_FLOAT(
986               gyro_cal->debug_gyro_cal.gyro_var[2] * RAD_TO_MDEG * RAD_TO_MDEG,
987               3));
988       break;
989 
990     case MAG_STATS:
991       if (gyro_cal->debug_gyro_cal.using_mag_sensor) {
992         CAL_DEBUG_LOG(
993             debug_tag,
994             "Cal#|Mag Mean|Var [uT|uT^2]: %zu, " CAL_FORMAT_3DIGITS_TRIPLET
995             ", " CAL_FORMAT_6DIGITS_TRIPLET,
996             gyro_cal->debug_calibration_count,
997             CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[0], 3),
998             CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[1], 3),
999             CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_mean[2], 3),
1000             CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[0], 6),
1001             CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[1], 6),
1002             CAL_ENCODE_FLOAT(gyro_cal->debug_gyro_cal.mag_var[2], 6));
1003       } else {
1004         CAL_DEBUG_LOG(debug_tag,
1005                       "Cal#|Mag Mean|Var [uT|uT^2]: %zu, 0, 0, 0, -1.0, -1.0, "
1006                       "-1.0",
1007                       gyro_cal->debug_calibration_count);
1008       }
1009       break;
1010 
1011     default:
1012       break;
1013   }
1014 }
1015 
gyroCalDebugPrint(struct GyroCal * gyro_cal,uint64_t timestamp_nanos)1016 void gyroCalDebugPrint(struct GyroCal* gyro_cal, uint64_t timestamp_nanos) {
1017   // This is a state machine that controls the reporting out of debug data.
1018   switch (gyro_cal->debug_state) {
1019     case GYRO_IDLE:
1020       // Wait for a trigger and start the debug printout sequence.
1021       if (gyro_cal->debug_print_trigger) {
1022         CAL_DEBUG_LOG(GYROCAL_REPORT_TAG, "");
1023         CAL_DEBUG_LOG(GYROCAL_REPORT_TAG, "Debug Version: %s",
1024                       GYROCAL_DEBUG_VERSION_STRING);
1025         gyro_cal->debug_print_trigger = false;  // Resets trigger.
1026         gyro_cal->debug_state = GYRO_PRINT_OFFSET;
1027       } else {
1028         gyro_cal->debug_state = GYRO_IDLE;
1029       }
1030       break;
1031 
1032     case GYRO_WAIT_STATE:
1033       // This helps throttle the print statements.
1034       if (NANO_TIMER_CHECK_T1_GEQUAL_T2_PLUS_DELTA(timestamp_nanos,
1035                                                    gyro_cal->wait_timer_nanos,
1036                                                    GYROCAL_WAIT_TIME_NANOS)) {
1037         gyro_cal->debug_state = gyro_cal->next_state;
1038       }
1039       break;
1040 
1041     case GYRO_PRINT_OFFSET:
1042       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, OFFSET);
1043       gyro_cal->wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1044       gyro_cal->next_state = GYRO_PRINT_STILLNESS_DATA;  // Sets the next state.
1045       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1046       break;
1047 
1048     case GYRO_PRINT_STILLNESS_DATA:
1049       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, STILLNESS_DATA);
1050       gyro_cal->wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1051       gyro_cal->next_state =
1052           GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE;  // Sets next state.
1053       gyro_cal->debug_state = GYRO_WAIT_STATE;     // First, go to wait state.
1054       break;
1055 
1056     case GYRO_PRINT_SAMPLE_RATE_AND_TEMPERATURE:
1057       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG,
1058                             SAMPLE_RATE_AND_TEMPERATURE);
1059       gyro_cal->wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1060       gyro_cal->next_state =
1061           GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN;  // Sets next state.
1062       gyro_cal->debug_state = GYRO_WAIT_STATE;    // First, go to wait state.
1063       break;
1064 
1065     case GYRO_PRINT_GYRO_MINMAX_STILLNESS_MEAN:
1066       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG,
1067                             GYRO_MINMAX_STILLNESS_MEAN);
1068       gyro_cal->wait_timer_nanos = timestamp_nanos;   // Starts the wait timer.
1069       gyro_cal->next_state = GYRO_PRINT_ACCEL_STATS;  // Sets the next state.
1070       gyro_cal->debug_state = GYRO_WAIT_STATE;  // First, go to wait state.
1071       break;
1072 
1073     case GYRO_PRINT_ACCEL_STATS:
1074       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, ACCEL_STATS);
1075       gyro_cal->wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1076       gyro_cal->next_state = GYRO_PRINT_GYRO_STATS;  // Sets the next state.
1077       gyro_cal->debug_state = GYRO_WAIT_STATE;       // First, go to wait state.
1078       break;
1079 
1080     case GYRO_PRINT_GYRO_STATS:
1081       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, GYRO_STATS);
1082       gyro_cal->wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1083       gyro_cal->next_state = GYRO_PRINT_MAG_STATS;   // Sets the next state.
1084       gyro_cal->debug_state = GYRO_WAIT_STATE;       // First, go to wait state.
1085       break;
1086 
1087     case GYRO_PRINT_MAG_STATS:
1088       gyroCalDebugPrintData(gyro_cal, GYROCAL_REPORT_TAG, MAG_STATS);
1089       gyro_cal->wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1090       gyro_cal->next_state = GYRO_IDLE;              // Sets the next state.
1091       gyro_cal->debug_state = GYRO_WAIT_STATE;       // First, go to wait state.
1092       break;
1093 
1094     default:
1095       // Sends this state machine to its idle state.
1096       gyro_cal->wait_timer_nanos = timestamp_nanos;  // Starts the wait timer.
1097       gyro_cal->debug_state = GYRO_IDLE;             // Go to idle state.
1098   }
1099 }
1100 #endif  // GYRO_CAL_DBG_ENABLED
1101