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