blob: 53f6f4da0ca3592d7cdab5d161f4c17594a152d5 [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#include "aos/util/phased_loop.h"
brians343bc112013-02-10 01:53:46 +00002
Austin Schuhf257f3c2019-10-27 21:00:43 -07003#include "glog/logging.h"
4
brians343bc112013-02-10 01:53:46 +00005namespace aos {
6namespace time {
7
Austin Schuhf257f3c2019-10-27 21:00:43 -07008PhasedLoop::PhasedLoop(const monotonic_clock::duration interval,
9 const monotonic_clock::time_point monotonic_now,
10 const monotonic_clock::duration offset)
11 : interval_(interval), offset_(offset), last_time_(offset) {
12 CHECK(offset >= monotonic_clock::duration(0));
13 CHECK(interval > monotonic_clock::duration(0));
14 CHECK(offset < interval);
15 Reset(monotonic_now);
16}
17
18void PhasedLoop::set_interval_and_offset(
19 const monotonic_clock::duration interval,
20 const monotonic_clock::duration offset) {
Milind Upadhyay42589bb2021-05-19 20:05:16 -070021 // Update last_time_ to the new offset so that we have an even interval
22 last_time_ += offset - offset_;
23
Austin Schuhf257f3c2019-10-27 21:00:43 -070024 interval_ = interval;
25 offset_ = offset;
26 CHECK(offset_ >= monotonic_clock::duration(0));
27 CHECK(interval_ > monotonic_clock::duration(0));
28 CHECK(offset_ < interval_);
29}
30
31monotonic_clock::duration PhasedLoop::OffsetFromIntervalAndTime(
32 const monotonic_clock::duration interval,
33 const monotonic_clock::time_point monotonic_trigger) {
34 CHECK(interval > monotonic_clock::duration(0));
35 return monotonic_trigger.time_since_epoch() -
36 (monotonic_trigger.time_since_epoch() / interval) * interval +
37 ((monotonic_trigger.time_since_epoch() >= monotonic_clock::zero())
38 ? monotonic_clock::zero()
39 : interval);
40}
41
Austin Schuh8aec1ed2016-05-01 13:29:20 -070042int PhasedLoop::Iterate(const monotonic_clock::time_point now) {
Brian Silverman8babd8f2020-06-23 16:38:50 -070043 auto next_time = monotonic_clock::epoch();
44 // Round up to the next whole interval, ignoring offset_.
45 {
46 const auto offset_now = (now - offset_).time_since_epoch();
47 monotonic_clock::duration prerounding;
48 if (now.time_since_epoch() >= offset_) {
49 // We're above 0, so rounding up means away from 0.
50 prerounding = offset_now + interval_;
51 } else {
52 // We're below 0, so rounding up means towards 0.
53 prerounding = offset_now + monotonic_clock::duration(1);
54 }
55 next_time += (prerounding / interval_) * interval_;
56 }
57 // Add offset_ back in.
58 next_time += offset_;
Brian Silvermandcaa3f72015-11-29 05:32:08 +000059
Austin Schuh8aec1ed2016-05-01 13:29:20 -070060 const monotonic_clock::duration difference = next_time - last_time_;
Milind Upadhyay42589bb2021-05-19 20:05:16 -070061
Austin Schuh8aec1ed2016-05-01 13:29:20 -070062 const int result = difference / interval_;
Austin Schuh8aec1ed2016-05-01 13:29:20 -070063 CHECK_EQ(
64 0, (next_time - offset_).time_since_epoch().count() % interval_.count());
Brian Silverman8babd8f2020-06-23 16:38:50 -070065 CHECK(next_time > now);
Austin Schuhf257f3c2019-10-27 21:00:43 -070066 CHECK(next_time - now <= interval_);
Brian Silvermandcaa3f72015-11-29 05:32:08 +000067 last_time_ = next_time;
68 return result;
69}
70
Milind Upadhyay42589bb2021-05-19 20:05:16 -070071} // namespace time
brians343bc112013-02-10 01:53:46 +000072} // namespace aos