Home | History | Annotate | Download | only in gyroscope
      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.
    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).
    200 void gyroCalDestroy(struct GyroCal* gyro_cal) { (void)gyro_cal; }
    201 
    202 // Get the most recent bias calibration value.
    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.
    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].
    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.
    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].
    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].
    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].
    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".
    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.
    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.
    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.
    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 
    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
    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 
    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 
   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