/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <algos/gyro_cal.h> /////// DEFINITIONS AND MACROS /////////////////////////////////////// // Maximum gyro bias correction (should be set based on // expected max bias of the given sensor). #define MAX_GYRO_BIAS 0.096f // [rad/sec] // Helper constants for converting units. #define RAD_TO_MDEG (float)(1e3*180.0/M_PI) #define GRAVITY_TO_G (float)(1.0/9.80665) /////// FORWARD DECLARATIONS ///////////////////////////////////////// static void deviceStillnessCheck(struct gyroCal_t* gyro_cal, uint64_t sample_time); static void computeGyroCal(struct gyroCal_t* gyro_cal, uint64_t calibration_time); static void checkWatchdog(struct gyroCal_t* gyro_cal, uint64_t sample_time); #ifdef GYRO_CAL_DBG_ENABLED static void gyroCalUpdateDebug(struct gyroCal_t* gyro_cal, struct debugGyroCal_t* debug_gyro_cal); static void gyroCalTuneDebugPrint(struct gyroCal_t* gyro_cal, uint64_t sample_time); static void gyroCalDebugPrintData(int count, struct debugGyroCal_t *debug_data); // Information print macro. #define GYRO_INFO_PRINT(fmt, ...) do { \ osLog(LOG_INFO, "%s " fmt, "[GYRO CAL]", ##__VA_ARGS__); \ } while (0); // Macro used to print out floating point numbers. #define GYRO_ENCODE_FLOAT(x, num_digits) ((x < 0) ? "-" : ""), \ (int)floorf(fabsf(x)), \ (int)((fabsf(x) - floorf(fabsf(x))) * powf(10,num_digits)) #endif /////// FUNCTION DEFINITIONS ///////////////////////////////////////// // Initialize the gyro calibration data structure. void gyroCalInit(struct gyroCal_t* gyro_cal, uint64_t min_still_duration, uint64_t max_still_duration, float bias_x, float bias_y, float bias_z, uint64_t calibration_time, uint64_t window_time_duration, float gyro_var_threshold, float gyro_confidence_delta, float accel_var_threshold, float accel_confidence_delta, float mag_var_threshold, float mag_confidence_delta, float stillness_threshold, int remove_bias_enable) { // Clear gyro_cal structure memory. memset(gyro_cal, 0, sizeof(struct gyroCal_t)); // Initialize the stillness detectors. // Gyro parameter input units are [rad/sec] // Accel parameter input units are [m/sec^2] // Magnetometer parameter input units are [uT] gyroStillDetInit(&gyro_cal->gyro_stillness_detect, gyro_var_threshold, gyro_confidence_delta); gyroStillDetInit(&gyro_cal->accel_stillness_detect, accel_var_threshold, accel_confidence_delta); gyroStillDetInit(&gyro_cal->mag_stillness_detect, mag_var_threshold, mag_confidence_delta); // Reset stillness flag and start timestamp. gyro_cal->prev_still = false; gyro_cal->start_still_time = 0; // Set the min and max window stillness duration. gyro_cal->min_still_duration = min_still_duration; gyro_cal->max_still_duration = max_still_duration; // Sets the duration of the stillness processing windows. gyro_cal->window_time_duration = window_time_duration; // Set the watchdog timeout duration. gyro_cal->gyro_watchdog_timeout_duration = 2 * window_time_duration; // Load the last valid cal from system memory. gyro_cal->bias_x = bias_x; // [rad/sec] gyro_cal->bias_y = bias_y; // [rad/sec] gyro_cal->bias_z = bias_z; // [rad/sec] gyro_cal->calibration_time = calibration_time; // Set the stillness threshold required for gyro bias calibration. gyro_cal->stillness_threshold = stillness_threshold; // Current window end time used to assist in keeping sensor data // collection in sync. Setting this to zero signals that sensor data // will be dropped until a valid end time is set from the first gyro // timestamp received. gyro_cal->stillness_win_endtime = 0; // Gyro calibrations will be applied (see, gyroCalRemoveBias()). gyro_cal->gyro_calibration_enable = (remove_bias_enable > 0); #ifdef GYRO_CAL_DBG_ENABLED GYRO_INFO_PRINT("Gyro Cal: Initialized."); #endif } // Void all pointers in the gyro calibration data structure // (prevents compiler warnings). void gyroCalDestroy(struct gyroCal_t* gyro_cal) { (void)gyro_cal; } // Get the most recent bias calibration value. void gyroCalGetBias(struct gyroCal_t* gyro_cal, float* bias_x, float* bias_y, float* bias_z) { if (gyro_cal->gyro_calibration_enable) { *bias_x = gyro_cal->bias_x; *bias_y = gyro_cal->bias_y; *bias_z = gyro_cal->bias_z; } } // Set an initial bias calibration value. void gyroCalSetBias(struct gyroCal_t* gyro_cal, float bias_x, float bias_y, float bias_z, uint64_t calibration_time) { gyro_cal->bias_x = bias_x; gyro_cal->bias_y = bias_y; gyro_cal->bias_z = bias_z; gyro_cal->calibration_time = calibration_time; } // Remove bias from a gyro measurement [rad/sec]. void gyroCalRemoveBias(struct gyroCal_t* gyro_cal, float xi, float yi, float zi, float* xo, float* yo, float* zo) { if (gyro_cal->gyro_calibration_enable) { *xo = xi - gyro_cal->bias_x; *yo = yi - gyro_cal->bias_y; *zo = zi - gyro_cal->bias_z; } } // Returns true when a new gyro calibration is available. bool gyroCalNewBiasAvailable(struct gyroCal_t* gyro_cal) { bool new_gyro_cal_available = (gyro_cal->gyro_calibration_enable && gyro_cal->new_gyro_cal_available); // Clear the flag. gyro_cal->new_gyro_cal_available = false; return new_gyro_cal_available; } // Update the gyro calibration with gyro data [rad/sec]. void gyroCalUpdateGyro(struct gyroCal_t* gyro_cal, uint64_t sample_time, float x, float y, float z, float temperature) { // Make sure that a valid window end time is set, // and start the watchdog timer. if (gyro_cal->stillness_win_endtime <= 0) { gyro_cal->stillness_win_endtime = sample_time + gyro_cal->window_time_duration; // Start the watchdog timer. gyro_cal->gyro_watchdog_start = sample_time; } // Record the latest temperture sample. gyro_cal->latest_temperature_celcius = temperature; // Pass gyro data to stillness detector gyroStillDetUpdate(&gyro_cal->gyro_stillness_detect, gyro_cal->stillness_win_endtime, sample_time, x, y, z); // Perform a device stillness check, set next window end time, and // possibly do a gyro bias calibration and stillness detector reset. deviceStillnessCheck(gyro_cal, sample_time); } // Update the gyro calibration with mag data [micro Tesla]. void gyroCalUpdateMag(struct gyroCal_t* gyro_cal, uint64_t sample_time, float x, float y, float z) { // Pass magnetometer data to stillness detector. gyroStillDetUpdate(&gyro_cal->mag_stillness_detect, gyro_cal->stillness_win_endtime, sample_time, x, y, z); // Received a magnetometer sample; incorporate it into detection. gyro_cal->using_mag_sensor = true; // Perform a device stillness check, set next window end time, and // possibly do a gyro bias calibration and stillness detector reset. deviceStillnessCheck(gyro_cal, sample_time); } // Update the gyro calibration with accel data [m/sec^2]. void gyroCalUpdateAccel(struct gyroCal_t* gyro_cal, uint64_t sample_time, float x, float y, float z) { // Pass accelerometer data to stillnesss detector. gyroStillDetUpdate(&gyro_cal->accel_stillness_detect, gyro_cal->stillness_win_endtime, sample_time, x, y, z); // Perform a device stillness check, set next window end time, and // possibly do a gyro bias calibration and stillness detector reset. deviceStillnessCheck(gyro_cal, sample_time); } // Checks the state of all stillness detectors to determine // whether the device is "still". void deviceStillnessCheck(struct gyroCal_t* gyro_cal, uint64_t sample_time) { bool stillness_duration_exceeded = false; bool stillness_duration_too_short = false; bool device_is_still = false; float conf_not_rot = 0; float conf_not_accel = 0; float conf_still = 0; // Check the watchdog timer. checkWatchdog(gyro_cal, sample_time); // Is there enough data to do a stillness calculation? if ((!gyro_cal->mag_stillness_detect.stillness_window_ready && gyro_cal->using_mag_sensor) || !gyro_cal->accel_stillness_detect.stillness_window_ready || !gyro_cal->gyro_stillness_detect.stillness_window_ready) { return; // Not yet, wait for more data. } // Set the next window end time for the stillness detectors. gyro_cal->stillness_win_endtime = sample_time + gyro_cal->window_time_duration; // Update the confidence scores for all sensors. gyroStillDetCompute(&gyro_cal->accel_stillness_detect); gyroStillDetCompute(&gyro_cal->gyro_stillness_detect); if (gyro_cal->using_mag_sensor) { gyroStillDetCompute(&gyro_cal->mag_stillness_detect); } else { // Not using magnetometer, force stillness confidence to 100%. gyro_cal->mag_stillness_detect.stillness_confidence = 1.0f; } // Determine motion confidence scores (rotation, accelerating, and stillness). conf_not_rot = gyro_cal->gyro_stillness_detect.stillness_confidence * gyro_cal->mag_stillness_detect.stillness_confidence; conf_not_accel = gyro_cal->accel_stillness_detect.stillness_confidence; conf_still = conf_not_rot * conf_not_accel; // determine if the device is currently still. device_is_still = (conf_still > gyro_cal->stillness_threshold); if (device_is_still) { // Device is still logic: // If not previously still, then record the start time. // If stillness period is too long, then do a calibration. // Otherwise, continue collecting stillness data. // If device was not previously still, set new start timestamp. if (!gyro_cal->prev_still) { // Record the starting timestamp of the current stillness window. // This enables the calculation of total duration of the stillness period. gyro_cal->start_still_time = gyro_cal->gyro_stillness_detect.window_start_time; } // Check to see if current stillness period exceeds the desired limit // to avoid corrupting the . stillness_duration_exceeded = ((gyro_cal->gyro_stillness_detect.last_sample_time - gyro_cal->start_still_time) > gyro_cal->max_still_duration); if (stillness_duration_exceeded) { // The current stillness has gone too long. Do a calibration with the // current data and reset. // Update the gyro bias estimate with the current window data and // reset the stats. gyroStillDetReset(&gyro_cal->accel_stillness_detect, true); gyroStillDetReset(&gyro_cal->gyro_stillness_detect, true); gyroStillDetReset(&gyro_cal->mag_stillness_detect, true); // Perform calibration. computeGyroCal(gyro_cal, gyro_cal->gyro_stillness_detect.last_sample_time); // Update stillness flag. Force the start of a new stillness period. gyro_cal->prev_still = false; } else { // Continue collecting stillness data. // Reset stillness detectors, and extend stillness period. gyroStillDetReset(&gyro_cal->accel_stillness_detect, false); gyroStillDetReset(&gyro_cal->gyro_stillness_detect, false); gyroStillDetReset(&gyro_cal->mag_stillness_detect, false); // Update stillness flag. gyro_cal->prev_still = true; } } else { // Device is NOT still; motion detected. // If device was previously still and the total stillness duration is not // "too short", then do a calibration with the data accumulated thus far. stillness_duration_too_short = ((gyro_cal->gyro_stillness_detect.window_start_time - gyro_cal->start_still_time) < gyro_cal->min_still_duration); if (gyro_cal->prev_still && !stillness_duration_too_short) { computeGyroCal(gyro_cal, gyro_cal->gyro_stillness_detect.window_start_time); } // Reset stillness detectors and the stats. gyroStillDetReset(&gyro_cal->accel_stillness_detect, true); gyroStillDetReset(&gyro_cal->gyro_stillness_detect, true); gyroStillDetReset(&gyro_cal->mag_stillness_detect, true); // Update stillness flag. gyro_cal->prev_still = false; } // Reset the watchdog timer after we have processed data. gyro_cal->gyro_watchdog_start = sample_time; #ifdef GYRO_CAL_DBG_ENABLED // Debug information available. gyro_cal->debug_processed_data_available = true; gyro_cal->debug_processed_data_time = sample_time; #endif } // Calculates a new gyro bias offset calibration value. void computeGyroCal(struct gyroCal_t* gyro_cal, uint64_t calibration_time) { // Current calibration duration. uint64_t cur_cal_dur = calibration_time - gyro_cal->start_still_time; // Check to see if new calibration values is within acceptable range. if (!(gyro_cal->gyro_stillness_detect.prev_mean_x < MAX_GYRO_BIAS && gyro_cal->gyro_stillness_detect.prev_mean_x >-MAX_GYRO_BIAS && gyro_cal->gyro_stillness_detect.prev_mean_y < MAX_GYRO_BIAS && gyro_cal->gyro_stillness_detect.prev_mean_y >-MAX_GYRO_BIAS && gyro_cal->gyro_stillness_detect.prev_mean_z < MAX_GYRO_BIAS && gyro_cal->gyro_stillness_detect.prev_mean_z >-MAX_GYRO_BIAS)) { // Outside of range. Ignore, reset, and continue. return; } // Record new gyro bias offset calibration. gyro_cal->bias_x = gyro_cal->gyro_stillness_detect.prev_mean_x; gyro_cal->bias_y = gyro_cal->gyro_stillness_detect.prev_mean_y; gyro_cal->bias_z = gyro_cal->gyro_stillness_detect.prev_mean_z; // Record final stillness confidence. gyro_cal->stillness_confidence = gyro_cal->gyro_stillness_detect.prev_stillness_confidence * gyro_cal->accel_stillness_detect.prev_stillness_confidence * gyro_cal->mag_stillness_detect.prev_stillness_confidence; // Store calibration stillness duration. gyro_cal->calibration_time_duration = cur_cal_dur; // Store calibration time stamp. gyro_cal->calibration_time = calibration_time; // Set flag to indicate a new gyro calibration value is available. gyro_cal->new_gyro_cal_available = true; #ifdef GYRO_CAL_DBG_ENABLED // Increment the total count of calibration updates. gyro_cal->debug_calibration_count++; // Store the last 'DEBUG_GYRO_SHORTTERM_NUM_CAL' calibration debug data // in a circular buffer, 'debug_cal_data[]'. 'debug_head' is the index // of the last valid calibration. gyro_cal->debug_head++; if (gyro_cal->debug_head >= DEBUG_GYRO_SHORTTERM_NUM_CAL) { gyro_cal->debug_head = 0; } if (gyro_cal->debug_num_cals < DEBUG_GYRO_SHORTTERM_NUM_CAL) { gyro_cal->debug_num_cals++; } // Update the calibration debug information. gyroCalUpdateDebug(gyro_cal, &gyro_cal->debug_cal_data[gyro_cal->debug_head]); // Improve the collection of historic calibrations. Limit frequency to // every N hours. if ((gyro_cal->debug_num_cals_hist <= 0) || (calibration_time - gyro_cal-> debug_cal_data_hist[gyro_cal->debug_head_hist].calibration_time) >= DEBUG_GYRO_CAL_LIMIT) { gyro_cal->debug_head_hist++; if (gyro_cal->debug_head_hist >= DEBUG_GYRO_LONGTERM_NUM_CAL) { gyro_cal->debug_head_hist = 0; } if (gyro_cal->debug_num_cals_hist < DEBUG_GYRO_LONGTERM_NUM_CAL) { gyro_cal->debug_num_cals_hist++; } // Update the calibration debug information. gyroCalUpdateDebug(gyro_cal, &gyro_cal-> debug_cal_data_hist[gyro_cal->debug_head_hist]); } #endif } // Check for a watchdog timeout condition. void checkWatchdog(struct gyroCal_t* gyro_cal, uint64_t sample_time) { bool watchdog_timeout; // Check for initialization of the watchdog time (=0). if (gyro_cal->gyro_watchdog_start <= 0) { return; } // Check for timeout condition of watchdog. watchdog_timeout = ((sample_time - gyro_cal->gyro_watchdog_start) > gyro_cal->gyro_watchdog_timeout_duration); // If a timeout occurred then reset to known good state. if (watchdog_timeout) { // Reset stillness detectors and restart data capture. gyroStillDetReset(&gyro_cal->accel_stillness_detect, true); gyroStillDetReset(&gyro_cal->gyro_stillness_detect, true); gyroStillDetReset(&gyro_cal->mag_stillness_detect, true); gyro_cal->mag_stillness_detect.stillness_confidence = 0; gyro_cal->stillness_win_endtime = 0; // Force stillness confidence to zero. gyro_cal->accel_stillness_detect.prev_stillness_confidence = 0; gyro_cal->gyro_stillness_detect.prev_stillness_confidence = 0; gyro_cal->mag_stillness_detect.prev_stillness_confidence = 0; gyro_cal->stillness_confidence = 0; gyro_cal->prev_still = false; // If there are no magnetometer samples being received then // operate the calibration algorithm without this sensor. if (!gyro_cal->mag_stillness_detect.stillness_window_ready && gyro_cal->using_mag_sensor) { gyro_cal->using_mag_sensor = false; } // Assert watchdog timeout flags. gyro_cal->gyro_watchdog_timeout |= watchdog_timeout; gyro_cal->gyro_watchdog_start = 0; #ifdef GYRO_CAL_DBG_ENABLED gyro_cal->debug_watchdog_count++; #endif } } #ifdef GYRO_CAL_DBG_ENABLED // Update the calibration debug information. void gyroCalUpdateDebug(struct gyroCal_t* gyro_cal, struct debugGyroCal_t* debug_gyro_cal) { // Probability of stillness (acc, rot, still), duration, timestamp. debug_gyro_cal->accel_stillness_conf = gyro_cal->accel_stillness_detect.prev_stillness_confidence; debug_gyro_cal->gyro_stillness_conf = gyro_cal->gyro_stillness_detect.prev_stillness_confidence; debug_gyro_cal->mag_stillness_conf = gyro_cal->mag_stillness_detect.prev_stillness_confidence; // Magnetometer usage. debug_gyro_cal->used_mag_sensor = gyro_cal->using_mag_sensor; // Temperature at calibration time. debug_gyro_cal->temperature_celcius = gyro_cal->latest_temperature_celcius; // Calibration time and stillness duration. debug_gyro_cal->calibration_time_duration = gyro_cal->calibration_time_duration; debug_gyro_cal->calibration_time = gyro_cal->calibration_time; // Record the current calibration values debug_gyro_cal->calibration[0] = gyro_cal->bias_x; debug_gyro_cal->calibration[1] = gyro_cal->bias_y; debug_gyro_cal->calibration[2] = gyro_cal->bias_z; // Record the previous window means debug_gyro_cal->accel_mean[0] = gyro_cal->accel_stillness_detect.prev_mean_x; debug_gyro_cal->accel_mean[1] = gyro_cal->accel_stillness_detect.prev_mean_y; debug_gyro_cal->accel_mean[2] = gyro_cal->accel_stillness_detect.prev_mean_z; debug_gyro_cal->gyro_mean[0] = gyro_cal->gyro_stillness_detect.prev_mean_x; debug_gyro_cal->gyro_mean[1] = gyro_cal->gyro_stillness_detect.prev_mean_y; debug_gyro_cal->gyro_mean[2] = gyro_cal->gyro_stillness_detect.prev_mean_z; debug_gyro_cal->mag_mean[0] = gyro_cal->mag_stillness_detect.prev_mean_x; debug_gyro_cal->mag_mean[1] = gyro_cal->mag_stillness_detect.prev_mean_y; debug_gyro_cal->mag_mean[2] = gyro_cal->mag_stillness_detect.prev_mean_z; // Record the variance data. debug_gyro_cal->accel_var[0] = gyro_cal->accel_stillness_detect.win_var_x; debug_gyro_cal->accel_var[1] = gyro_cal->accel_stillness_detect.win_var_y; debug_gyro_cal->accel_var[2] = gyro_cal->accel_stillness_detect.win_var_z; debug_gyro_cal->gyro_var[0] = gyro_cal->gyro_stillness_detect.win_var_x; debug_gyro_cal->gyro_var[1] = gyro_cal->gyro_stillness_detect.win_var_y; debug_gyro_cal->gyro_var[2] = gyro_cal->gyro_stillness_detect.win_var_z; debug_gyro_cal->mag_var[0] = gyro_cal->mag_stillness_detect.win_var_x; debug_gyro_cal->mag_var[1] = gyro_cal->mag_stillness_detect.win_var_y; debug_gyro_cal->mag_var[2] = gyro_cal->mag_stillness_detect.win_var_z; } // Helper function to print debug statements. void gyroCalDebugPrintData(int count, struct debugGyroCal_t *debug_data) { GYRO_INFO_PRINT( "#%d Gyro Bias Calibration = {%s%d.%06d, %s%d.%06d, %s%d.%06d} [mdps]\n", count, GYRO_ENCODE_FLOAT(debug_data->calibration[0] * RAD_TO_MDEG, 6), GYRO_ENCODE_FLOAT(debug_data->calibration[1] * RAD_TO_MDEG, 6), GYRO_ENCODE_FLOAT(debug_data->calibration[2] * RAD_TO_MDEG, 6) ); if (debug_data->used_mag_sensor) { GYRO_INFO_PRINT(" Using Magnetometer.\n"); } else { GYRO_INFO_PRINT(" Not Using Magnetometer.\n"); } GYRO_INFO_PRINT(" Temperature = %s%d.%06d [C]\n", GYRO_ENCODE_FLOAT(debug_data->temperature_celcius, 6)); GYRO_INFO_PRINT(" Calibration Timestamp = %llu [nsec]\n", debug_data->calibration_time); GYRO_INFO_PRINT(" Stillness Duration = %llu [nsec]\n", debug_data->calibration_time_duration); GYRO_INFO_PRINT(" Accel Mean = {%s%d.%06d, %s%d.%06d, %s%d.%06d} [g]\n", GYRO_ENCODE_FLOAT(debug_data->accel_mean[0] * GRAVITY_TO_G, 6), GYRO_ENCODE_FLOAT(debug_data->accel_mean[1] * GRAVITY_TO_G, 6), GYRO_ENCODE_FLOAT(debug_data->accel_mean[2] * GRAVITY_TO_G, 6)); GYRO_INFO_PRINT(" Mag Mean = {%s%d.%06d, %s%d.%06d, %s%d.%06d} [uT]\n", GYRO_ENCODE_FLOAT(debug_data->mag_mean[0], 6), GYRO_ENCODE_FLOAT(debug_data->mag_mean[1], 6), GYRO_ENCODE_FLOAT(debug_data->mag_mean[2], 6) ); } // Print Debug data useful for tuning the stillness detectors. void gyroCalTuneDebugPrint(struct gyroCal_t* gyro_cal, uint64_t sample_time) { static uint64_t counter = 0; // Output sensor variance levels to assist with tuning thresholds // every N seconds. if ((sample_time - counter) > 10000000000) { //nsec GYRO_INFO_PRINT(""); GYRO_INFO_PRINT( " Gyro Variance = {%s%d.%08d, %s%d.%08d, %s%d.%08d} [rad/sec]^2\n", GYRO_ENCODE_FLOAT( gyro_cal->gyro_stillness_detect.win_var_x, 8), GYRO_ENCODE_FLOAT( gyro_cal->gyro_stillness_detect.win_var_y, 8), GYRO_ENCODE_FLOAT( gyro_cal->gyro_stillness_detect.win_var_z, 8)); GYRO_INFO_PRINT( " Accel Variance = {%s%d.%08d, %s%d.%08d, %s%d.%08d} [m/sec^2]^2\n", GYRO_ENCODE_FLOAT( gyro_cal->accel_stillness_detect.win_var_x, 8), GYRO_ENCODE_FLOAT( gyro_cal->accel_stillness_detect.win_var_y, 8), GYRO_ENCODE_FLOAT( gyro_cal->accel_stillness_detect.win_var_z, 8)); GYRO_INFO_PRINT( " Mag Variance = {%s%d.%06d, %s%d.%06d, %s%d.%06d} [uT]^2\n", GYRO_ENCODE_FLOAT( gyro_cal->mag_stillness_detect.win_var_x, 6), GYRO_ENCODE_FLOAT( gyro_cal->mag_stillness_detect.win_var_y, 6), GYRO_ENCODE_FLOAT( gyro_cal->mag_stillness_detect.win_var_z, 6)); GYRO_INFO_PRINT( " Stillness = {G%s%d.%06d, A%s%d.%06d, M%s%d.%06d}\n", GYRO_ENCODE_FLOAT( gyro_cal-> gyro_stillness_detect.stillness_confidence, 6), GYRO_ENCODE_FLOAT( gyro_cal-> accel_stillness_detect.stillness_confidence, 6), GYRO_ENCODE_FLOAT( gyro_cal-> mag_stillness_detect.stillness_confidence, 6)); GYRO_INFO_PRINT( " Temperature = %s%d.%06d [C]\n", GYRO_ENCODE_FLOAT( gyro_cal->latest_temperature_celcius, 6)); GYRO_INFO_PRINT("Total Gyro Calibrations: %lu\n", gyro_cal->debug_calibration_count); counter = sample_time; //reset } } // Print Debug data report. void gyroCalDebugPrint(struct gyroCal_t* gyro_cal, int* state, uint64_t sample_time) { static int head_index; static int i, j; if (gyro_cal->debug_num_cals == 0) { *state = -1; // idle state. } // State machine to control reporting out debug print data. switch (*state) { case 0: // STATE 0 : Print out header GYRO_INFO_PRINT(""); GYRO_INFO_PRINT( "---DEBUG REPORT-------------------------------------\n"); GYRO_INFO_PRINT("Gyro Calibrations To Report (newest to oldest): %d\n", gyro_cal->debug_num_cals); head_index = gyro_cal->debug_head; i = 1; // initialize report count *state = 1; // set next state. break; case 1: // STATE 1: Print out past N recent calibrations. if (i <= gyro_cal->debug_num_cals) { // Print the data. gyroCalDebugPrintData(i, &gyro_cal->debug_cal_data[head_index]); // Move to the previous calibration data set. head_index--; if (head_index < 0) { head_index = DEBUG_GYRO_SHORTTERM_NUM_CAL-1; } // Increment the report count. i++; // Go to wait state. j = 0; *state = 2; } else { // Print out the footer data. *state = 3; } break; case 2: // STATE 2 : Wait state. // Wait for N cycles of gyro samples before printing out more data. // This helps throttle the print statements. if (j <= 50) { j++; } else { *state = 1; } break; case 3: // STATE 3 : Print the end of the debug report. GYRO_INFO_PRINT("Total Gyro Calibrations: %lu\n", gyro_cal->debug_calibration_count); GYRO_INFO_PRINT("Total Watchdog Timeouts: %lu\n", gyro_cal->debug_watchdog_count); GYRO_INFO_PRINT( "---END DEBUG REPORT---------------------------------\n"); *state = 4; break; case 4: // STATE 4 : Print out header (historic data) GYRO_INFO_PRINT(""); GYRO_INFO_PRINT( "---DEBUG REPORT (HISTORY)---------------------------\n"); GYRO_INFO_PRINT("Gyro Calibrations To Report (newest to oldest): %d\n", gyro_cal->debug_num_cals_hist); head_index = gyro_cal->debug_head_hist; i = 1; // initialize report count *state = 5; // set next state. break; case 5: // STATE 5: Print out past N historic calibrations. if (i <= gyro_cal->debug_num_cals_hist) { // Print the data. gyroCalDebugPrintData(i, &gyro_cal->debug_cal_data_hist[head_index]); // Move to the previous calibration data set. head_index--; if (head_index < 0) { head_index = DEBUG_GYRO_LONGTERM_NUM_CAL-1; } // Increment the report count. i++; // Go to wait state. j = 0; *state = 6; } else { // Print out the footer data. *state = 7; } break; case 6: // STATE 6 : Wait state. // Wait for N cycles of gyro samples before printing out more data. // This helps throttle the print statements. if (j <= 50) { j++; } else { *state = 5; } break; case 7: // STATE 3 : Print the end of the debug report. GYRO_INFO_PRINT("Total Gyro Calibrations: %lu\n", gyro_cal->debug_calibration_count); GYRO_INFO_PRINT("Total Watchdog Timeouts: %lu\n", gyro_cal->debug_watchdog_count); GYRO_INFO_PRINT( "---END DEBUG REPORT---------------------------------\n"); *state = -1; break; default : // Idle state. *state = -1; // Report periodic data useful for tuning the stillness detectors. //gyroCalTuneDebugPrint(gyro_cal, sample_time); } } #endif