ElecClock.h
Go to the documentation of this file.
1 /**
2  * \file ElecClock.h
3  *
4  * \ingroup DetectorClocks
5  *
6  * \brief Class def header for a class ElecClock
7  *
8  * @author Kazuhiro Terao (kterao@fnal.gov)
9  */
10 
11 /** \addtogroup DetectorClocks
12 
13  @{*/
14 #ifndef ElecClock_H
15 #define ElecClock_H
16 
17 #include "ClockConstants.h"
19 
20 namespace detinfo {
21  /**
22  * @brief Class representing the time measured by an electronics clock.
23  *
24  * This class represents the status of a running electronics clock.
25  * As such, it has:
26  *
27  * * _tick frequency_: how many times the clock ticks in one second
28  * * _frame period_: the duration of a single frame; clock time is organised
29  * into two levels:
30  * * the time is split into frames
31  * * each frame is split in samples; the first one of a each frame is
32  * sample number 0
33  * * _current time_ of the clock, with respect to the time (always "0") the
34  * clock was started at
35  *
36  * Note that this object is actually able to manage any (continuous) value of
37  * time, and the concepts of frame and sample are not used to store the clock
38  * state, which is instead defined by its current time.
39  *
40  * All these quantities are stored in real time units as opposed to clock tick
41  * counts. The nominal units for all times and frequencies are microseconds
42  * and megahertz, respectively, but `ElecClock` will give consistent results
43  * as long as the units of frame period and time are the same, and reciprocal
44  * to the frequency unit.
45  *
46  * The clock can update its time directly (`SetTime()`) or through operators.
47  *
48  * The clock started at time 0, with the sample 0 of the frame 0 (that is also
49  * tick 0). This implies that *all times and ticks returned by the clock
50  * implicitly have the same reference as the input time specified by the
51  * constructors or by the last call to `SetTime()`*.
52  *
53  * Some usage examples:
54  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
55  * // get a clock with a period of 500 ns (2 MHz) and a frame of 1.6 ms
56  * detinfo::ElecClock clock(0.0, 1600.0, 2.0);
57  *
58  * std::cout << "New clock:"
59  * << "\n current time: " << clock.Time() // 0.0 us
60  * << "\n samples per frame: " << clock.FrameTicks() // 3200
61  * << std::endl;
62  *
63  * clock.SetTime(1, 20); // sets the time to sample #20 of frame 1
64  * std::cout << "Time set to sample #20 of frame #1:"
65  * << "\n current time: " << clock.Time() // 1610.0 us
66  * << "\n current tick: " << clock.Tick() // 3220
67  * << std::endl;
68  *
69  * clock += 3.7; // add 3.7 us to the current time
70  * std::cout << "Added 3.7 microseconds:"
71  * << "\n current time: " << clock.Time() // 1613.7 us
72  * << "\n current tick: " << clock.Tick() // 3227
73  * << "\n discrete time: " << clock.Time(Time()) // 1613.5 us
74  * << std::endl;
75  *
76  * clock += 3; // add 3 more ticks (1.5 us) to the current time
77  * std::cout << "Added 3 ticks:"
78  * << "\n current time: " << clock.Time() // 1615.2 us
79  * << "\n current tick: " << clock.Tick() // 3230
80  * << "\n discrete time: " << clock.Time(Time()) // 1615.0 us
81  * << std::endl;
82  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
83  *
84  * @note Most methods and operators have different behaviour according to
85  * whether their argument is of type `double`, in which case it is
86  * interpreted as a time, or `int`, where it is interpreted as a clock
87  * tick. Be especially careful when utilizing data types which are
88  * neither `int` not `double`, because a conversion to one of them will
89  * occur, and you need to be in control of which one.
90  */
91  class ElecClock {
92  public:
93  /**
94  * @brief Constructor: sets all values.
95  * @param time starting time of the clock [&micro;s]
96  * @param frame_period period of the clock [&micro;s]
97  * @param frequency clock frequency [MHz]
98  *
99  */
100  ElecClock(double const time, double const frame_period, double const frequency)
101  : ElecClock{time, frame_period, frequency, std::nothrow}
102  {
103  if (fFrequency <= 0)
104  throw detinfo::DetectorClocksException("Only positive frequency allowed.");
105  }
106 
107  constexpr ElecClock
108  WithTime(double const time) const noexcept
109  {
110  return {time, fFramePeriod, fFrequency, std::nothrow};
111  }
112 
113  constexpr ElecClock
114  WithTick(int const tick, int const frame = 0) const noexcept
115  {
116  return {Time(tick, frame), fFramePeriod, fFrequency, std::nothrow};
117  }
118 
119  constexpr ElecClock
120  AdvanceTimeBy(double const time) const noexcept
121  {
122  return {fTime + time, fFramePeriod, fFrequency, std::nothrow};
123  }
124 
125  constexpr ElecClock
126  AdvanceTicksBy(int const ticks) const noexcept
127  {
128  return {fTime + Time(ticks), fFramePeriod, fFrequency, std::nothrow};
129  }
130 
131  /**
132  * @brief Current time (as stored) in microseconds.
133  *
134  * Note that this is different than `Time(Time())`, which is discretized.
135  */
136  constexpr double
137  Time() const noexcept
138  {
139  return fTime;
140  }
141 
142  /**
143  * @brief Returns the absolute time of the start of the specified sample.
144  * @param sample sample number within the specified frame
145  * @param frame number of the frame the specified sample is in
146  * @return time [us] corresponding to the start of the specified sample
147  *
148  * The sample number is not checked to be actually within the specified
149  * frame.
150  *
151  * The returned time is not related to the current time of the clock.
152  */
153  constexpr double
154  Time(int const sample, int const frame) const noexcept
155  {
156  return (sample / fFrequency + frame * fFramePeriod);
157  }
158 
159  /**
160  * @brief Returns the discretized value of the specified time.
161  * @param time a clock time [&micro;s]
162  * @return discretized time [&micro;s] (as a floating point number)
163  *
164  * The returned time is the start time of the sample `time` falls in.
165  *
166  * It is not related to the current time of the clock.
167  */
168  constexpr double
169  Time(double const time) const noexcept
170  {
171  return Time(Sample(time), Frame(time));
172  }
173 
174  /**
175  * @brief Returns the absolute start time of the specified tick.
176  * @param ticks a clock time [&micro;s]
177  * @return discretized time [&micro;s] (as a floating point number)
178  *
179  * The returned time is the start time of the tick which `time` falls in.
180  *
181  * It is not related to the current time of the clock.
182  */
183  constexpr double
184  Time(int const ticks) const noexcept
185  {
186  return ticks / fFrequency;
187  }
188 
189  /// Frequency in MHz.
190  constexpr double
191  Frequency() const
192  {
193  return fFrequency;
194  }
195 
196  /// A single frame period in microseconds.
197  constexpr double
198  FramePeriod() const noexcept
199  {
200  return fFramePeriod;
201  }
202 
203  /// Current clock tick (that is, the number of tick `Time()` falls in).
204  constexpr int
205  Ticks() const noexcept
206  {
207  return Ticks(fTime);
208  }
209 
210  /**
211  * @brief Returns the number of tick the specified time falls in.
212  * @param time time to be converted in ticks [&micro;s]
213  * @return the number of the tick containing the specified time
214  *
215  * The tick number 0 starts at time 0.0 &micro;s.
216  *
217  * @note The returned value (number of tick) can wrap if the real number of
218  * the tick is beyond the range of the returned data type (`int`).
219  */
220  constexpr int
221  Ticks(double const time) const noexcept
222  {
223  return static_cast<int>(time * fFrequency);
224  }
225 
226  /**
227  * @brief Returns the number of tick the specified sample falls in.
228  * @param sample number of sample in the specified frame
229  * @param frame number of frame the specified sample is in
230  * @return the number of the tick containing the specified sample
231  *
232  * The sample 0 of frame 0 is the tick number 0.
233  *
234  * @note The returned value (number of tick) can wrap if the real number of
235  * the tick is beyond the range of the returned data type (`int`).
236  */
237  constexpr int
238  Ticks(int const sample, int const frame) const noexcept
239  {
240  return sample + frame * FrameTicks();
241  }
242 
243  /**
244  * @brief Returns number of the sample containing the clock current time.
245  * @see `Sample(double)`
246  *
247  * The returned value is the number of the sample within a frame, which the
248  * current clock time falls in. The number of the frame is not returned.
249  * To univocally define the sample, the number of the frame must also be
250  * obtained, e.g. via `Frame()`.
251  */
252  constexpr int
253  Sample() const noexcept
254  {
255  return Sample(fTime);
256  }
257 
258  /**
259  * @brief Returns the number of the sample containing the specified time.
260  * @param time a clock time [&micro;s]
261  * @return number of the sample containing the specified time
262  * @see `Frame(double)`
263  *
264  * The returned value is the number of the sample within a frame, which the
265  * specified time falls in. The number of the frame is not returned.
266  * To univocally define the sample, the number of the frame must also be
267  * obtained, e.g. via `Frame(double)`.
268  *
269  * The result is not related to the current time of the clock.
270  */
271  constexpr int
272  Sample(double const time) const noexcept
273  {
274  return static_cast<int>((time - Frame(time) * fFramePeriod) * fFrequency);
275  }
276 
277  /**
278  * @brief Returns the number of the sample containing the specified tick.
279  * @param tick a clock tick number
280  * @return number of the sample containing the specified tick
281  * @see `Frame(int)`
282  *
283  * The returned value is the number of the sample within a frame, of the
284  * specified tick. The number of the frame is not returned.
285  * To univocally define the sample, the number of the frame must also be
286  * obtained, e.g. via `Frame(int)`.
287  *
288  * The result is not related to the current time of the clock.
289  */
290  constexpr int
291  Sample(int const tick) const noexcept
292  {
293  return (tick % static_cast<int>(FrameTicks()));
294  }
295 
296  /**
297  * @brief Returns the number of the frame containing the clock current time.
298  * @see `Frame(double)`
299  *
300  * The returned value is the number of the frame which the current clock
301  * time falls in.
302  */
303  constexpr int
304  Frame() const noexcept
305  {
306  return Frame(fTime);
307  }
308 
309  /**
310  * @brief Returns the number of the frame containing the specified time.
311  * @param time a clock time [&micro;s]
312  * @return number of the frame containing the specified time
313  * @see `Sample(double)`
314  *
315  * The returned value is the number of the frame which the specified time
316  * falls in.
317  *
318  * The result is not related to the current time of the clock.
319  */
320  constexpr int
321  Frame(double const time) const noexcept
322  {
323  return static_cast<int>(time / fFramePeriod);
324  }
325 
326  /**
327  * @brief Returns the number of the frame containing the specified tick.
328  * @param tick a clock tick number
329  * @return number of the frame containing the specified tick
330  * @see `Frame(int)`
331  *
332  * The returned value is the number of the frame the specified tick belongs
333  * to.
334  *
335  * The result is not related to the current time of the clock.
336  */
337  constexpr int
338  Frame(int const tick) const noexcept
339  {
340  return (tick / static_cast<int>(FrameTicks()));
341  }
342 
343  /// Number ticks in a frame.
344  constexpr unsigned int
345  FrameTicks() const noexcept
346  {
347  return static_cast<unsigned int>(fFramePeriod * fFrequency);
348  }
349 
350  /// A single tick period in microseconds.
351  constexpr double
352  TickPeriod() const noexcept
353  {
354  return 1. / fFrequency;
355  }
356 
357  //-- comparators --//
358 
359  constexpr bool
360  operator<(const ElecClock& rhs) const noexcept
361  {
362  return fTime < rhs.Time();
363  }
364  constexpr bool
365  operator>(const ElecClock& rhs) const noexcept
366  {
367  return fTime > rhs.Time();
368  }
369  constexpr bool
370  operator<=(const ElecClock& rhs) const noexcept
371  {
372  return fTime <= rhs.Time();
373  }
374  constexpr bool
375  operator>=(const ElecClock& rhs) const noexcept
376  {
377  return fTime >= rhs.Time();
378  }
379 
380  private:
381  constexpr ElecClock(double const time,
382  double const frame_period,
383  double const frequency,
384  std::nothrow_t) noexcept
385  : fTime(time), fFramePeriod(frame_period), fFrequency(frequency)
386  {}
387 
388  double fTime{}; ///< Time in microseconds.
389  double fFramePeriod{kTIME_MAX}; ///< Frame period in microseconds.
390  double fFrequency{1e9}; ///< Clock speed in MHz.
391 
392  }; // class ElecClock
393 
394 }
395 #endif
396 /** @} */ // end of doxygen group
constexpr ElecClock WithTime(double const time) const noexcept
Definition: ElecClock.h:108
constexpr int Frame(int const tick) const noexcept
Returns the number of the frame containing the specified tick.
Definition: ElecClock.h:338
constexpr unsigned int FrameTicks() const noexcept
Number ticks in a frame.
Definition: ElecClock.h:345
constexpr double kTIME_MAX
Maximum time in microseconds.
Definition: ClockConstants.h:9
constexpr int Ticks(double const time) const noexcept
Returns the number of tick the specified time falls in.
Definition: ElecClock.h:221
constexpr int Sample(double const time) const noexcept
Returns the number of the sample containing the specified time.
Definition: ElecClock.h:272
constexpr double FramePeriod() const noexcept
A single frame period in microseconds.
Definition: ElecClock.h:198
constexpr int Ticks(int const sample, int const frame) const noexcept
Returns the number of tick the specified sample falls in.
Definition: ElecClock.h:238
constexpr ElecClock WithTick(int const tick, int const frame=0) const noexcept
Definition: ElecClock.h:114
constexpr ElecClock AdvanceTimeBy(double const time) const noexcept
Definition: ElecClock.h:120
constexpr int Frame(double const time) const noexcept
Returns the number of the frame containing the specified time.
Definition: ElecClock.h:321
constexpr int Frame() const noexcept
Returns the number of the frame containing the clock current time.
Definition: ElecClock.h:304
tick ticks
Alias for common language habits.
Definition: electronics.h:78
constexpr int Ticks() const noexcept
Current clock tick (that is, the number of tick Time() falls in).
Definition: ElecClock.h:205
constexpr bool operator>(const ElecClock &rhs) const noexcept
Definition: ElecClock.h:365
double fFrequency
Clock speed in MHz.
Definition: ElecClock.h:390
constexpr double TickPeriod() const noexcept
A single tick period in microseconds.
Definition: ElecClock.h:352
constexpr int Sample(int const tick) const noexcept
Returns the number of the sample containing the specified tick.
Definition: ElecClock.h:291
constexpr double Time(double const time) const noexcept
Returns the discretized value of the specified time.
Definition: ElecClock.h:169
constexpr ElecClock AdvanceTicksBy(int const ticks) const noexcept
Definition: ElecClock.h:126
constexpr int Sample() const noexcept
Returns number of the sample containing the clock current time.
Definition: ElecClock.h:253
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
constexpr ElecClock(double const time, double const frame_period, double const frequency, std::nothrow_t) noexcept
Definition: ElecClock.h:381
constexpr double Time() const noexcept
Current time (as stored) in microseconds.
Definition: ElecClock.h:137
General LArSoft Utilities.
constexpr bool operator<=(const ElecClock &rhs) const noexcept
Definition: ElecClock.h:370
double fTime
Time in microseconds.
Definition: ElecClock.h:388
constexpr bool operator<(const ElecClock &rhs) const noexcept
Definition: ElecClock.h:360
ElecClock(double const time, double const frame_period, double const frequency)
Constructor: sets all values.
Definition: ElecClock.h:100
constexpr double Frequency() const
Frequency in MHz.
Definition: ElecClock.h:191
constexpr double Time(int const sample, int const frame) const noexcept
Returns the absolute time of the start of the specified sample.
Definition: ElecClock.h:154
constexpr bool operator>=(const ElecClock &rhs) const noexcept
Definition: ElecClock.h:375
Class representing the time measured by an electronics clock.
Definition: ElecClock.h:91
constexpr double Time(int const ticks) const noexcept
Returns the absolute start time of the specified tick.
Definition: ElecClock.h:184
double fFramePeriod
Frame period in microseconds.
Definition: ElecClock.h:389