mirror of
https://github.com/google/pebble.git
synced 2026-02-16 02:16:49 -05:00
75 lines
3.1 KiB
C
75 lines
3.1 KiB
C
/*
|
|
* Copyright 2024 Google LLC
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
|
|
//! @file interval_timer.h
|
|
//!
|
|
//! Times the average number of milliseconds between samples. Taking a sample is ISR-safe. Uses
|
|
//! the RTC time domain which should be fairly accurate for real clock time. Note that because
|
|
//! we use the RTC we may occasionally have to discard intervals because the wall clock time was
|
|
//! changed. This is not ideal, but it's still a better source of time than our SysTick time source
|
|
//! as that is not necessarily synced to real time.
|
|
//!
|
|
//! The resolution of the recorded timer will be same as the configured resolution of our RTC
|
|
//! peripheral, which at the time of writing is 1/256 of a second.
|
|
//!
|
|
//! The average is calculated as an exponential moving average.
|
|
//! https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
|
|
//! The weighting factor (how responsive to recent changes) is configurable.
|
|
|
|
typedef struct {
|
|
uint64_t last_sample_timestamp_ms;
|
|
|
|
// The minimum and maximum values for an interval for it to be included into the average.
|
|
uint32_t min_expected_ms;
|
|
uint32_t max_expected_ms;
|
|
|
|
uint32_t weighting_factor_inverted;
|
|
|
|
//! The moving average we've calculated based on the samples we have so far.
|
|
uint32_t average_ms;
|
|
//! The number of samples we've taken.
|
|
uint32_t num_samples;
|
|
} IntervalTimer;
|
|
|
|
//! Initialize an interval timer.
|
|
//!
|
|
//! Allows the specification of an acceptable range of intervals. This is used to discard invalid
|
|
//! intervals.
|
|
//!
|
|
//! Intervals are averaged together in a moving average that includes the last n intervals. The
|
|
//! number of intervals to average over is configurable.
|
|
//!
|
|
//! @param min_expected_ms The minimum number of milliseconds between samples
|
|
//! @param min_expected_ms The maximum number of milliseconds between samples
|
|
//! @param weighting_factor_inverted
|
|
//! 1 / alpha. Specified as a inverted number to avoid dealing with floats. The higher the
|
|
//! number the less responsive to recent changes our average is.
|
|
void interval_timer_init(IntervalTimer *timer, uint32_t min_expected_ms, uint32_t max_expected_ms,
|
|
uint32_t weighting_factory_inverted);
|
|
|
|
//! Record a sample that marks the start/end of an interval.
|
|
//! Safe to call from an ISR.
|
|
void interval_timer_take_sample(IntervalTimer *timer);
|
|
|
|
//! @param[out] average_ms_out The average ms for the interval.
|
|
//! @return The number of valid intervals that are in our moving average. Note that this value
|
|
//! will never be larger than num_intervals_in_average.
|
|
uint32_t interval_timer_get(IntervalTimer *timer, uint32_t *average_ms_out);
|