| /* Copyright 2020 The Chromium OS Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "gyro_cal.h" |
| #include "string.h" |
| #include <stdbool.h> |
| |
| /* |
| * Maximum gyro bias correction (should be set based on expected max bias |
| * of the given sensor). [rad/sec] |
| */ |
| #define MAX_GYRO_BIAS FLOAT_TO_FP(0.2f) |
| |
| static void device_stillness_check(struct gyro_cal *gyro_cal, |
| uint32_t sample_time_us); |
| |
| static void compute_gyro_cal(struct gyro_cal *gyro_cal, |
| uint32_t calibration_time_us); |
| |
| static void check_window(struct gyro_cal *gyro_cal, uint32_t sample_time_us); |
| |
| /** Data tracker command enumeration. */ |
| enum gyro_cal_tracker_command { |
| /** Resets the local data used for data tracking. */ |
| DO_RESET = 0, |
| /** Updates the local tracking data. */ |
| DO_UPDATE_DATA, |
| /** Stores intermediate results for later recall. */ |
| DO_STORE_DATA, |
| /** Computes and provides the results of the gate function. */ |
| DO_EVALUATE |
| }; |
| |
| /** |
| * Reset the gyro_cal's temperature statistics. |
| * |
| * @param gyro_cal Pointer to the gyro_cal data structure. |
| */ |
| static void gyro_temperature_stats_tracker_reset(struct gyro_cal *gyro_cal); |
| |
| /** |
| * Updates the temperature min/max and mean during the stillness period. |
| * |
| * @param gyro_cal Pointer to the gyro_cal data structure. |
| * @param temperature_kelvin New temperature sample to include. |
| */ |
| static void gyro_temperature_stats_tracker_update(struct gyro_cal *gyro_cal, |
| int temperature_kelvin); |
| |
| /** |
| * Store the tracker data to be used for calculation. |
| * |
| * @param gyro_cal Pointer to the gyro_cal data structure. |
| */ |
| static void gyro_temperature_stats_tracker_store(struct gyro_cal *gyro_cal); |
| |
| /** |
| * Compute whether or not the temperature values are in range. |
| * |
| * @param gyro_cal Pointer to the gyro_cal data structure. |
| * @return 'true' if the min and max temperature values exceed the |
| * range set by 'temperature_delta_limit_kelvin'. |
| */ |
| static bool gyro_temperature_stats_tracker_eval(struct gyro_cal *gyro_cal); |
| |
| /** |
| * Tracks the minimum and maximum gyroscope stillness window means. |
| * Returns |
| * |
| * @param gyro_cal Pointer to the gyro_cal data structure. |
| * @param do_this Command enumerator that controls function behavior. |
| */ |
| static void gyro_still_mean_tracker_reset(struct gyro_cal *gyro_cal); |
| |
| /** |
| * Compute the min/max window mean values according to 'window_mean_tracker'. |
| * |
| * @param gyro_cal Pointer to the gyro_cal data structure. |
| */ |
| static void gyro_still_mean_tracker_update(struct gyro_cal *gyro_cal); |
| |
| /** |
| * Store the most recent "stillness" mean data to the gyro_cal data structure. |
| * |
| * @param gyro_cal Pointer to the gyro_cal data structure. |
| */ |
| static void gyro_still_mean_tracker_store(struct gyro_cal *gyro_cal); |
| |
| /** |
| * Compute whether or not the gyroscope window range is within the valid range. |
| * |
| * @param gyro_cal Pointer to the gyro_cal data structure. |
| * @return 'true' when the difference between gyroscope min and max |
| * window means are outside the range set by |
| * 'stillness_mean_delta_limit'. |
| */ |
| static bool gyro_still_mean_tracker_eval(struct gyro_cal *gyro_cal); |
| |
| void init_gyro_cal(struct gyro_cal *gyro_cal) |
| { |
| gyro_still_mean_tracker_reset(gyro_cal); |
| gyro_temperature_stats_tracker_reset(gyro_cal); |
| } |
| |
| void gyro_cal_get_bias(struct gyro_cal *gyro_cal, fpv3_t bias, |
| int *temperature_kelvin, uint32_t *calibration_time_us) |
| { |
| bias[X] = gyro_cal->bias_x; |
| bias[Y] = gyro_cal->bias_y; |
| bias[Z] = gyro_cal->bias_z; |
| *calibration_time_us = gyro_cal->calibration_time_us; |
| *temperature_kelvin = gyro_cal->bias_temperature_kelvin; |
| } |
| |
| void gyro_cal_set_bias(struct gyro_cal *gyro_cal, fpv3_t bias, |
| int temperature_kelvin, uint32_t calibration_time_us) |
| { |
| gyro_cal->bias_x = bias[X]; |
| gyro_cal->bias_y = bias[Y]; |
| gyro_cal->bias_z = bias[Z]; |
| gyro_cal->calibration_time_us = calibration_time_us; |
| gyro_cal->bias_temperature_kelvin = temperature_kelvin; |
| } |
| |
| void gyro_cal_remove_bias(struct gyro_cal *gyro_cal, fpv3_t in, fpv3_t out) |
| { |
| if (gyro_cal->gyro_calibration_enable) { |
| out[X] = in[X] - gyro_cal->bias_x; |
| out[Y] = in[Y] - gyro_cal->bias_y; |
| out[Z] = in[Z] - gyro_cal->bias_z; |
| } |
| } |
| |
| bool gyro_cal_new_bias_available(struct gyro_cal *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; |
| } |
| |
| void gyro_cal_update_gyro(struct gyro_cal *gyro_cal, uint32_t sample_time_us, |
| fp_t x, fp_t y, fp_t z, int temperature_kelvin) |
| { |
| /* |
| * Make sure that a valid window end-time is set, and start the window |
| * timer. |
| */ |
| if (gyro_cal->stillness_win_endtime_us <= 0) { |
| gyro_cal->stillness_win_endtime_us = |
| sample_time_us + gyro_cal->window_time_duration_us; |
| |
| /* Start the window timer. */ |
| gyro_cal->gyro_window_start_us = sample_time_us; |
| } |
| |
| /* Update the temperature statistics. */ |
| gyro_temperature_stats_tracker_update(gyro_cal, temperature_kelvin); |
| |
| /* Pass gyro data to stillness detector */ |
| gyro_still_det_update(&gyro_cal->gyro_stillness_detect, |
| gyro_cal->stillness_win_endtime_us, |
| sample_time_us, x, y, z); |
| |
| /* |
| * Perform a device stillness check, set next window end-time, and |
| * possibly do a gyro bias calibration and stillness detector reset. |
| */ |
| device_stillness_check(gyro_cal, sample_time_us); |
| } |
| |
| void gyro_cal_update_mag(struct gyro_cal *gyro_cal, uint32_t sample_time_us, |
| fp_t x, fp_t y, fp_t z) |
| { |
| /* Pass magnetometer data to stillness detector. */ |
| gyro_still_det_update(&gyro_cal->mag_stillness_detect, |
| gyro_cal->stillness_win_endtime_us, |
| sample_time_us, 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. |
| */ |
| device_stillness_check(gyro_cal, sample_time_us); |
| } |
| |
| void gyro_cal_update_accel(struct gyro_cal *gyro_cal, uint32_t sample_time_us, |
| fp_t x, fp_t y, fp_t z) |
| { |
| /* Pass accelerometer data to stillnesss detector. */ |
| gyro_still_det_update(&gyro_cal->accel_stillness_detect, |
| gyro_cal->stillness_win_endtime_us, |
| sample_time_us, x, y, z); |
| |
| /* |
| * Perform a device stillness check, set next window end-time, and |
| * possibly do a gyro bias calibration and stillness detector reset. |
| */ |
| device_stillness_check(gyro_cal, sample_time_us); |
| } |
| |
| /** |
| * Handle the case where the device is found to be still. This function should |
| * be called from device_stillness_check. |
| * |
| * @param gyro_cal Pointer to the gyroscope calibration struct. |
| */ |
| static void handle_device_is_still(struct gyro_cal *gyro_cal) |
| { |
| /* |
| * 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. |
| */ |
| bool stillness_duration_exceeded = false; |
| |
| /* |
| * 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_us = |
| gyro_cal->gyro_stillness_detect.window_start_time; |
| } |
| |
| /* |
| * Check to see if current stillness period exceeds the desired limit. |
| */ |
| stillness_duration_exceeded = |
| gyro_cal->gyro_stillness_detect.last_sample_time >= |
| (gyro_cal->start_still_time_us + |
| gyro_cal->max_still_duration_us); |
| |
| /* Track the new stillness mean and temperature data. */ |
| gyro_still_mean_tracker_store(gyro_cal); |
| gyro_temperature_stats_tracker_store(gyro_cal); |
| |
| if (stillness_duration_exceeded) { |
| /* |
| * The current stillness has gone too long. Do a calibration |
| * with the current data and reset. |
| */ |
| |
| /* |
| * Updates the gyro bias estimate with the current window data |
| * and resets the stats. |
| */ |
| gyro_still_det_reset(&gyro_cal->accel_stillness_detect, |
| /*reset_stats=*/true); |
| gyro_still_det_reset(&gyro_cal->gyro_stillness_detect, |
| /*reset_stats=*/true); |
| gyro_still_det_reset(&gyro_cal->mag_stillness_detect, |
| /*reset_stats=*/true); |
| |
| /* |
| * Resets the local calculations because the stillness |
| * period is over. |
| */ |
| gyro_still_mean_tracker_reset(gyro_cal); |
| gyro_temperature_stats_tracker_reset(gyro_cal); |
| |
| /* Computes a new gyro offset estimate. */ |
| compute_gyro_cal( |
| 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. */ |
| |
| /* Extend the stillness period. */ |
| gyro_still_det_reset(&gyro_cal->accel_stillness_detect, |
| /*reset_stats=*/false); |
| gyro_still_det_reset(&gyro_cal->gyro_stillness_detect, |
| /*reset_stats=*/false); |
| gyro_still_det_reset(&gyro_cal->mag_stillness_detect, |
| /*reset_stats=*/false); |
| |
| /* Update the stillness flag. */ |
| gyro_cal->prev_still = true; |
| } |
| } |
| |
| static void handle_device_not_still(struct gyro_cal *gyro_cal) |
| { |
| /* 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. |
| */ |
| bool stillness_duration_too_short = |
| gyro_cal->gyro_stillness_detect.window_start_time < |
| (gyro_cal->start_still_time_us + |
| gyro_cal->min_still_duration_us); |
| |
| if (gyro_cal->prev_still && !stillness_duration_too_short) |
| compute_gyro_cal( |
| gyro_cal, |
| gyro_cal->gyro_stillness_detect.window_start_time); |
| |
| /* Reset the stillness detectors and the stats. */ |
| gyro_still_det_reset(&gyro_cal->accel_stillness_detect, |
| /*reset_stats=*/true); |
| gyro_still_det_reset(&gyro_cal->gyro_stillness_detect, |
| /*reset_stats=*/true); |
| gyro_still_det_reset(&gyro_cal->mag_stillness_detect, |
| /*reset_stats=*/true); |
| |
| /* Resets the temperature and sensor mean data. */ |
| gyro_temperature_stats_tracker_reset(gyro_cal); |
| gyro_still_mean_tracker_reset(gyro_cal); |
| |
| /* Update stillness flag. */ |
| gyro_cal->prev_still = false; |
| } |
| |
| void device_stillness_check(struct gyro_cal *gyro_cal, uint32_t sample_time_us) |
| { |
| bool min_max_temp_exceeded = false; |
| bool mean_not_stable = false; |
| bool device_is_still = false; |
| fp_t conf_not_rot = INT_TO_FP(0); |
| fp_t conf_not_accel = INT_TO_FP(0); |
| fp_t conf_still = INT_TO_FP(0); |
| |
| /* Check the window timer. */ |
| check_window(gyro_cal, sample_time_us); |
| |
| /* 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_us = |
| sample_time_us + gyro_cal->window_time_duration_us; |
| |
| /* Update the confidence scores for all sensors. */ |
| gyro_still_det_compute(&gyro_cal->accel_stillness_detect); |
| gyro_still_det_compute(&gyro_cal->gyro_stillness_detect); |
| if (gyro_cal->using_mag_sensor) { |
| gyro_still_det_compute(&gyro_cal->mag_stillness_detect); |
| } else { |
| /* |
| * Not using magnetometer, force stillness confidence to 100%. |
| */ |
| gyro_cal->mag_stillness_detect.stillness_confidence = |
| INT_TO_FP(1); |
| } |
| |
| /* Updates the mean tracker data. */ |
| gyro_still_mean_tracker_update(gyro_cal); |
| |
| /* |
| * Determine motion confidence scores (rotation, accelerating, and |
| * stillness). |
| */ |
| conf_not_rot = |
| fp_mul(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 = fp_mul(conf_not_rot, conf_not_accel); |
| |
| /* Evaluate the mean and temperature gate functions. */ |
| mean_not_stable = gyro_still_mean_tracker_eval(gyro_cal); |
| min_max_temp_exceeded = gyro_temperature_stats_tracker_eval(gyro_cal); |
| |
| /* Determines if the device is currently still. */ |
| device_is_still = (conf_still > gyro_cal->stillness_threshold) && |
| !mean_not_stable && !min_max_temp_exceeded; |
| |
| if (device_is_still) |
| handle_device_is_still(gyro_cal); |
| else |
| handle_device_not_still(gyro_cal); |
| |
| /* Reset the window timer after we have processed data. */ |
| gyro_cal->gyro_window_start_us = sample_time_us; |
| } |
| |
| void compute_gyro_cal(struct gyro_cal *gyro_cal, uint32_t calibration_time_us) |
| { |
| /* 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 the 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]; |
| |
| /* |
| * Store the calibration temperature (using the mean temperature over |
| * the "stillness" period). |
| */ |
| gyro_cal->bias_temperature_kelvin = gyro_cal->temperature_mean_kelvin; |
| |
| /* Store the calibration time stamp. */ |
| gyro_cal->calibration_time_us = calibration_time_us; |
| |
| /* Record the final stillness confidence. */ |
| gyro_cal->stillness_confidence = fp_mul( |
| gyro_cal->gyro_stillness_detect.prev_stillness_confidence, |
| gyro_cal->accel_stillness_detect.prev_stillness_confidence); |
| gyro_cal->stillness_confidence = fp_mul( |
| gyro_cal->stillness_confidence, |
| gyro_cal->mag_stillness_detect.prev_stillness_confidence); |
| |
| /* Set flag to indicate a new gyro calibration value is available. */ |
| gyro_cal->new_gyro_cal_available = true; |
| } |
| |
| void check_window(struct gyro_cal *gyro_cal, uint32_t sample_time_us) |
| { |
| bool window_timeout; |
| |
| /* Check for initialization of the window time (=0). */ |
| if (gyro_cal->gyro_window_start_us <= 0) |
| return; |
| |
| /* |
| * Checks for the following window timeout conditions: |
| * i. The current timestamp has exceeded the allowed window duration. |
| * ii. A timestamp was received that has jumped backwards by more than |
| * the allowed window duration (e.g., timestamp clock roll-over). |
| */ |
| window_timeout = |
| (sample_time_us > gyro_cal->gyro_window_timeout_duration_us + |
| gyro_cal->gyro_window_start_us) || |
| (sample_time_us + gyro_cal->gyro_window_timeout_duration_us < |
| gyro_cal->gyro_window_start_us); |
| |
| /* If a timeout occurred then reset to known good state. */ |
| if (window_timeout) { |
| /* Reset stillness detectors and restart data capture. */ |
| gyro_still_det_reset(&gyro_cal->accel_stillness_detect, |
| /*reset_stats=*/true); |
| gyro_still_det_reset(&gyro_cal->gyro_stillness_detect, |
| /*reset_stats=*/true); |
| gyro_still_det_reset(&gyro_cal->mag_stillness_detect, |
| /*reset_stats=*/true); |
| |
| /* Resets the temperature and sensor mean data. */ |
| gyro_temperature_stats_tracker_reset(gyro_cal); |
| gyro_still_mean_tracker_reset(gyro_cal); |
| |
| /* Resets the stillness window end-time. */ |
| gyro_cal->stillness_win_endtime_us = 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 window timeout flags. */ |
| gyro_cal->gyro_window_start_us = 0; |
| } |
| } |
| |
| void gyro_temperature_stats_tracker_reset(struct gyro_cal *gyro_cal) |
| { |
| /* Resets the mean accumulator. */ |
| gyro_cal->temperature_mean_tracker.num_points = 0; |
| gyro_cal->temperature_mean_tracker.mean_accumulator = INT_TO_FP(0); |
| |
| /* Initializes the min/max temperatures values. */ |
| gyro_cal->temperature_mean_tracker.temperature_min_kelvin = 0x7fff; |
| gyro_cal->temperature_mean_tracker.temperature_max_kelvin = 0xffff; |
| } |
| |
| void gyro_temperature_stats_tracker_update(struct gyro_cal *gyro_cal, |
| int temperature_kelvin) |
| { |
| /* Does the mean accumulation. */ |
| gyro_cal->temperature_mean_tracker.mean_accumulator += |
| temperature_kelvin; |
| gyro_cal->temperature_mean_tracker.num_points++; |
| |
| /* Tracks the min, max, and latest temperature values. */ |
| gyro_cal->temperature_mean_tracker.latest_temperature_kelvin = |
| temperature_kelvin; |
| if (gyro_cal->temperature_mean_tracker.temperature_min_kelvin > |
| temperature_kelvin) { |
| gyro_cal->temperature_mean_tracker.temperature_min_kelvin = |
| temperature_kelvin; |
| } |
| if (gyro_cal->temperature_mean_tracker.temperature_max_kelvin < |
| temperature_kelvin) { |
| gyro_cal->temperature_mean_tracker.temperature_max_kelvin = |
| temperature_kelvin; |
| } |
| } |
| |
| void gyro_temperature_stats_tracker_store(struct gyro_cal *gyro_cal) |
| { |
| /* |
| * Store the most recent temperature statistics data to the |
| * gyro_cal data structure. This functionality allows previous |
| * results to be recalled when the device suddenly becomes "not |
| * still". |
| */ |
| if (gyro_cal->temperature_mean_tracker.num_points > 0) |
| gyro_cal->temperature_mean_kelvin = |
| gyro_cal->temperature_mean_tracker.mean_accumulator / |
| gyro_cal->temperature_mean_tracker.num_points; |
| else |
| gyro_cal->temperature_mean_kelvin = |
| gyro_cal->temperature_mean_tracker |
| .latest_temperature_kelvin; |
| } |
| |
| bool gyro_temperature_stats_tracker_eval(struct gyro_cal *gyro_cal) |
| { |
| bool min_max_temp_exceeded = false; |
| |
| /* Determines if the min/max delta exceeded the set limit. */ |
| if (gyro_cal->temperature_mean_tracker.num_points > 0) { |
| min_max_temp_exceeded = |
| (gyro_cal->temperature_mean_tracker |
| .temperature_max_kelvin - |
| gyro_cal->temperature_mean_tracker |
| .temperature_min_kelvin) > |
| gyro_cal->temperature_delta_limit_kelvin; |
| } |
| |
| return min_max_temp_exceeded; |
| } |
| |
| void gyro_still_mean_tracker_reset(struct gyro_cal *gyro_cal) |
| { |
| size_t i; |
| |
| /* Resets the min/max window mean values to a default value. */ |
| for (i = 0; i < 3; i++) { |
| gyro_cal->window_mean_tracker.gyro_winmean_min[i] = FLT_MAX; |
| gyro_cal->window_mean_tracker.gyro_winmean_max[i] = -FLT_MAX; |
| } |
| } |
| |
| void gyro_still_mean_tracker_update(struct gyro_cal *gyro_cal) |
| { |
| int i; |
| |
| /* Computes the min/max window mean values. */ |
| for (i = 0; i < 3; ++i) { |
| if (gyro_cal->window_mean_tracker.gyro_winmean_min[i] > |
| gyro_cal->gyro_stillness_detect.win_mean[i]) { |
| gyro_cal->window_mean_tracker.gyro_winmean_min[i] = |
| gyro_cal->gyro_stillness_detect.win_mean[i]; |
| } |
| if (gyro_cal->window_mean_tracker.gyro_winmean_max[i] < |
| gyro_cal->gyro_stillness_detect.win_mean[i]) { |
| gyro_cal->window_mean_tracker.gyro_winmean_max[i] = |
| gyro_cal->gyro_stillness_detect.win_mean[i]; |
| } |
| } |
| } |
| |
| void gyro_still_mean_tracker_store(struct gyro_cal *gyro_cal) |
| { |
| /* |
| * Store the most recent "stillness" mean data to the gyro_cal |
| * data structure. This functionality allows previous results to |
| * be recalled when the device suddenly becomes "not still". |
| */ |
| memcpy(gyro_cal->gyro_winmean_min, |
| gyro_cal->window_mean_tracker.gyro_winmean_min, |
| sizeof(gyro_cal->window_mean_tracker.gyro_winmean_min)); |
| memcpy(gyro_cal->gyro_winmean_max, |
| gyro_cal->window_mean_tracker.gyro_winmean_max, |
| sizeof(gyro_cal->window_mean_tracker.gyro_winmean_max)); |
| } |
| |
| bool gyro_still_mean_tracker_eval(struct gyro_cal *gyro_cal) |
| { |
| bool mean_not_stable = false; |
| size_t i; |
| |
| /* |
| * Performs the stability check and returns the 'true' if the |
| * difference between min/max window mean value is outside the |
| * stable range. |
| */ |
| for (i = 0; i < 3 && !mean_not_stable; i++) { |
| mean_not_stable |= |
| (gyro_cal->window_mean_tracker.gyro_winmean_max[i] - |
| gyro_cal->window_mean_tracker.gyro_winmean_min[i]) > |
| gyro_cal->stillness_mean_delta_limit; |
| } |
| |
| return mean_not_stable; |
| } |