SatCat5
timeref.cc
1 // Copyright 2021-2024 The Aerospace Corporation.
3 // This file is a part of SatCat5, licensed under CERN-OHL-W v2 or later.
5 
6 #include <satcat5/timeref.h>
7 #include <satcat5/utils.h>
8 
12 
13 // Fixed point scaling: (X * Y) / 2^32
14 static constexpr unsigned fp_floor(u32 t, u64 k)
15  { return unsigned((u64(t) * k) >> 32); }
16 static constexpr u32 fp_round(unsigned t, u64 k)
17  { return u32((u64(t) * k + (1u << 31)) >> 32); }
18 
19 unsigned TimeVal::elapsed_tick() const {
20  // Note: U32 arithmetic handles wraparound correctly,
21  // as long as elapsed time is less than UINT32_MAX ticks.
22  return unsigned(clk->raw() - tval);
23 }
24 
25 unsigned TimeVal::elapsed_usec() const {
26  return fp_floor(clk->raw() - tval, clk->m_usec_per_tick);
27 }
28 
29 unsigned TimeVal::elapsed_msec() const {
30  return fp_floor(clk->raw() - tval, clk->m_msec_per_tick);
31 }
32 
34  unsigned usec = elapsed_usec();
35  tval += fp_round(usec, clk->m_tick_per_usec);
36  return usec;
37 }
38 
40  unsigned msec = elapsed_msec();
41  tval += fp_round(msec, clk->m_tick_per_msec);
42  return msec;
43 }
44 
45 bool TimeVal::interval_tick(u32 ticks) {
46  u32 elapsed = clk->raw() - tval;
47  if (elapsed >= ticks) {
48  tval += ticks;
49  return true;
50  } else {
51  return false;
52  }
53 }
54 
55 bool TimeVal::interval_usec(unsigned usec) {
56  u32 ticks = fp_round(usec, clk->m_tick_per_usec);
57  return interval_tick(ticks);
58 }
59 
60 bool TimeVal::interval_msec(unsigned msec) {
61  u32 ticks = fp_round(msec, clk->m_tick_per_msec);
62  return interval_tick(ticks);
63 }
64 
66  return TimeVal {this, this->raw()};
67 }
68 
70  return TimeVal {this, raw() + fp_round(usec, m_tick_per_usec)};
71 }
72 
74  return TimeVal {this, raw() + fp_round(msec, m_tick_per_msec)};
75 }
76 
78  // Is the checkpoint enabled? Measure elapsed time.
79  if (!tval) return false; // Disabled
80  u32 elapsed = clk->raw() - tval;
81 
82  // Once now() exceeds tval, elapsed time will be a small positive number.
83  // Until then, it will be very large due to uint32_t wraparound.
84  static const u32 THRESHOLD = UINT32_MAX / 8;
85  if (elapsed < THRESHOLD) {
86  tval = 0; // Disable countdown (one-time use)
87  return true; // Interval elapsed
88  } else {
89  return false; // Still pending
90  }
91 }
92 
93 void TimeRef::busywait_usec(unsigned usec) {
94  // Note: If m_ticks_per_sec is small, interval may truncate to zero.
95  u32 tstart = raw();
96  u32 interval = fp_round(usec, m_tick_per_usec);
97  while (raw() - tstart < interval) {}
98 }
99 
101  return *m_reg;
102 }
The TimeRef API provides access to a monotonic time-counter.
Definition: timeref.h:142
TimeVal checkpoint_msec(unsigned msec)
Create an oven-timer, set N milliseconds from now.
Definition: timeref.cc:73
virtual u32 raw()=0
Read current time in arbitrary "ticks".
TimeVal now()
Create a TimeVal object using the tick-count from raw().
Definition: timeref.cc:65
TimeVal checkpoint_usec(unsigned usec)
Create an oven-timer, set N microseconds from now.
Definition: timeref.cc:69
void busywait_usec(unsigned usec)
If timer resolution allows, busywait for X microseconds.
Definition: timeref.cc:93
Implement TimeRef API using a memory-mapped performance counter.
Definition: timeref.h:209
u32 raw() override
Read current time in arbitrary "ticks".
Definition: timeref.cc:100
Timestamp for measuring elapsed time.
Definition: timeref.h:48
unsigned elapsed_usec() const
Elapsed time in microseconds.
Definition: timeref.cc:25
bool interval_usec(unsigned usec)
Test an interval measured in microseconds.
Definition: timeref.cc:55
TimeRef * clk
Pointer to the parent time reference.
Definition: timeref.h:49
bool checkpoint_elapsed()
Test if an oven-timer checkpoint has elapsed.
Definition: timeref.cc:77
u32 tval
The value of this timestamp, measured in ticks.
Definition: timeref.h:50
bool interval_tick(u32 ticks)
Test an interval measured in ticks.
Definition: timeref.cc:45
unsigned increment_msec()
Measure elapsed time in milliseconds, then increment by the returned quantized value.
Definition: timeref.cc:39
unsigned elapsed_msec() const
Elapsed time in milliseconds.
Definition: timeref.cc:29
bool interval_msec(unsigned msec)
Test an interval measured in milliseconds.
Definition: timeref.cc:60
unsigned increment_usec()
Measure elapsed time in microseconds, then increment by the returned quantized value.
Definition: timeref.cc:33
TimeRef and TimeVal define the API for monotonic timers.
Miscellaneous mathematical utility functions.