FastArduino  v1.7
C++ library to build fast but small Arduino/AVR projects
realtime_timer.h
Go to the documentation of this file.
1 // Copyright 2016-2021 Jean-Francois Poilpret
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
21 #ifndef RTT_HH
22 #define RTT_HH
23 
24 #include "boards/io.h"
25 #include <avr/interrupt.h>
26 #include "interrupts.h"
27 #include "timer.h"
28 #include "time.h"
29 #include "events.h"
30 
44 #define REGISTER_RTT_ISR(TIMER_NUM) \
45  ISR(CAT3(TIMER, TIMER_NUM, _COMPA_vect)) \
46  { \
47  timer::isr_handler_rtt::rtt<TIMER_NUM>(); \
48  }
49 
64 #define REGISTER_RTT_ISR_METHOD(TIMER_NUM, HANDLER, CALLBACK) \
65  ISR(CAT3(TIMER, TIMER_NUM, _COMPA_vect)) \
66  { \
67  timer::isr_handler_rtt::rtt_method<TIMER_NUM, HANDLER, CALLBACK>(); \
68  }
69 
82 #define REGISTER_RTT_ISR_FUNCTION(TIMER_NUM, CALLBACK) \
83  ISR(CAT3(TIMER, TIMER_NUM, _COMPA_vect)) \
84  { \
85  timer::isr_handler_rtt::rtt_function<TIMER_NUM, CALLBACK>(); \
86  }
87 
102 #define REGISTER_RTT_EVENT_ISR(TIMER_NUM, EVENT, PERIOD) \
103  ISR(CAT3(TIMER, TIMER_NUM, _COMPA_vect)) \
104  { \
105  timer::isr_handler_rtt::rtt_event<TIMER_NUM, EVENT, PERIOD>(); \
106  }
107 
114 #define DECL_RTT_ISR_HANDLERS_FRIEND \
115  friend struct timer::isr_handler_rtt; \
116  DECL_TIMER_COMP_FRIENDS
117 
118 namespace timer
119 {
135  template<typename T> class RTTRawTime
136  {
137  public:
138  RTTRawTime(const RTTRawTime<T>&) = default;
139  RTTRawTime<T>& operator=(const RTTRawTime<T>&) = default;
140 
150  RTTRawTime(uint32_t millis, T counter, T max_counter)
151  : millis_{millis}, counter_{counter}, max_counter_{max_counter}
152  {}
153 
158  static constexpr RTTRawTime<T> EMPTY_TIME{};
159 
166  {
167  return time::RTTTime{millis_, uint16_t(ONE_MILLI_32 * counter_ / (1UL + max_counter_))};
168  }
169 
170  private:
171  constexpr RTTRawTime() : buffer_{} {}
172 
173  // This union is an ugly hack to trick the compiler so that it understands
174  // the default constructor just needs 0 initialization for EMPTY_TIME constant,
175  // and thus can accept the fact EMPTY_TIME is a pure constexpr
176  union
177  {
178  struct
179  {
180  uint32_t millis_;
181  T counter_;
182  T max_counter_;
183  };
184  uint8_t buffer_[sizeof(uint32_t) + 2 * sizeof(T)];
185  };
186  };
187 
203  template<board::Timer NTIMER_> class RTT : private Timer<NTIMER_>
204  {
205  public:
207  static constexpr const board::Timer NTIMER = NTIMER_;
208 
209  private:
210  using TRAIT = typename Timer<NTIMER>::TRAIT;
211  using TYPE = typename Timer<NTIMER>::TYPE;
212  using PRESCALER = typename Timer<NTIMER>::PRESCALER;
213 
214  public:
215  RTT(const RTT<NTIMER_>&) = delete;
216  RTT<NTIMER_>& operator=(const RTT<NTIMER_>&) = delete;
217 
223 
231  RTT() : Timer<NTIMER>{TimerMode::CTC, MILLI_PRESCALER, TimerInterrupt::OUTPUT_COMPARE_A}
232  {
234  }
235 
252  uint32_t millis() const
253  {
254  synchronized return milliseconds_;
255  }
256 
273  uint32_t millis_() const
274  {
275  return milliseconds_;
276  }
277 
288  void delay(uint32_t ms) const
289  {
290  uint32_t end = millis() + ms + 1;
291  while (millis() < end) time::yield();
292  }
293 
312  uint16_t micros() const
313  {
314  synchronized return compute_micros();
315  }
316 
335  uint16_t micros_() const
336  {
337  return compute_micros();
338  }
339 
355  {
356  synchronized return time_();
357  }
358 
374  {
375  return time::RTTTime(milliseconds_, compute_micros());
376  }
377 
395  {
396  synchronized return raw_time_();
397  }
398 
416  {
417  return RAW_TIME{milliseconds_, (volatile TYPE&) TRAIT::TCNT, (volatile TYPE&) TRAIT::OCRA};
418  }
419 
425  void millis(uint32_t ms)
426  {
427  synchronized
428  {
429  milliseconds_ = ms;
430  // Reset timer counter
431  TRAIT::TCNT = 0;
432  }
433  }
434 
445  void begin()
446  {
447  synchronized begin_();
448  }
449 
460  void begin_()
461  {
462  milliseconds_ = 0;
463  Timer<NTIMER>::begin_(MILLI_COUNTER);
464  }
465 
475  void end()
476  {
478  }
479 
491  void end_()
492  {
494  }
495 
500  {
501  return *this;
502  }
503 
504  private:
505  volatile uint32_t milliseconds_ = 0UL;
506 
507  void on_timer()
508  {
509  ++milliseconds_;
510  }
511 
512  using CALC = Calculator<NTIMER>;
513  static constexpr const PRESCALER MILLI_PRESCALER = CALC::CTC_prescaler(ONE_MILLI_32);
514  static constexpr const TYPE MILLI_COUNTER = CALC::CTC_counter(MILLI_PRESCALER, ONE_MILLI_32);
515 
516  uint16_t compute_micros() const
517  {
518  return uint16_t(ONE_MILLI_32 * ((volatile TYPE&) TRAIT::TCNT) / (1UL + (volatile TYPE&) TRAIT::OCRA));
519  }
520 
521  friend struct isr_handler_rtt;
522  };
523 
535  template<typename EVENT, uint32_t PERIOD_MS = 1024> class RTTEventCallback
536  {
537  static_assert(events::Event_trait<EVENT>::IS_EVENT, "EVENT type must be an events::Event<T>");
538  static_assert((PERIOD_MS & (PERIOD_MS - 1)) == 0, "PERIOD_MS must be a power of 2");
539 
540  public:
543 
544  //FIXME we should allow Queue<EVENT, ?>
554  explicit RTTEventCallback(containers::Queue<EVENT>& event_queue) : event_queue_{event_queue} {}
555 
556  private:
557  void on_rtt_change(uint32_t millis)
558  {
559  if ((millis & (PERIOD_MS - 1)) == 0) event_queue_.push_(EVENT{events::Type::RTT_TIMER});
560  }
561 
562  containers::Queue<EVENT>& event_queue_;
563 
564  friend struct isr_handler_rtt;
565  };
566 
568 
569  // All RTT-related methods called by pre-defined ISR are defined here
570  //====================================================================
571 
572  struct isr_handler_rtt
573  {
574  template<uint8_t TIMER_NUM_> static void rtt()
575  {
576  static constexpr board::Timer NTIMER = isr_handler::check_timer<TIMER_NUM_>();
577  interrupt::HandlerHolder<RTT<NTIMER>>::handler()->on_timer();
578  }
579 
580  template<uint8_t TIMER_NUM_, typename HANDLER_, void (HANDLER_::*CALLBACK_)(uint32_t)> static void rtt_method()
581  {
582  static constexpr board::Timer NTIMER = isr_handler::check_timer<TIMER_NUM_>();
583  auto handler = interrupt::HandlerHolder<RTT<NTIMER>>::handler();
584  handler->on_timer();
585  interrupt::CallbackHandler<void (HANDLER_::*)(uint32_t), CALLBACK_>::call(handler->millis());
586  }
587 
588  template<uint8_t TIMER_NUM_, void (*CALLBACK_)(uint32_t)> static void rtt_function()
589  {
590  static constexpr board::Timer NTIMER = isr_handler::check_timer<TIMER_NUM_>();
591  auto handler = interrupt::HandlerHolder<RTT<NTIMER>>::handler();
592  handler->on_timer();
593  CALLBACK_(handler->millis());
594  }
595 
596  template<uint8_t TIMER_NUM_, typename EVENT_, uint32_t PERIOD_> static void rtt_event()
597  {
598  static constexpr board::Timer NTIMER = isr_handler::check_timer<TIMER_NUM_>();
599  auto handler = interrupt::HandlerHolder<RTT<NTIMER>>::handler();
600  handler->on_timer();
601  interrupt::HandlerHolder<RTTEventCallback<EVENT_, PERIOD_>>::handler()->on_rtt_change(handler->millis());
602  }
603  };
605 }
606 
607 #endif /* RTT_HH */
608 
timer::RTTEventCallback::RTTEventCallback
RTTEventCallback(containers::Queue< EVENT > &event_queue)
Create a RTTEventCallback that will push periodic events to event_queue.
Definition: realtime_timer.h:554
board::Timer
Timer
Defines all timers available for ATmega644.
Definition: atmega_xx4.h:316
timer::Calculator::CTC_counter
static constexpr TYPE CTC_counter(PRESCALER prescaler, uint32_t us)
Computes the value of counter to use for this timer, in TimerMode::CTC mode, with prescaler,...
Definition: timer.h:423
timer::RTT::end_
void end_()
Stop this real-time timer, hence time gets not counted anymore.
Definition: realtime_timer.h:491
containers::Queue< EVENT >
timer::RTT::timer
Timer< NTIMER > & timer()
Get a reference to the underlying Timer of this RTT.
Definition: realtime_timer.h:499
timer::RTT::raw_time
RAW_TIME raw_time() const
Elapsed time, in raw representation, since this timer has started.
Definition: realtime_timer.h:394
timer::RTT::delay
void delay(uint32_t ms) const
Delay program execution for the given amount of milliseconds.
Definition: realtime_timer.h:288
time::yield
void yield()
Utility method used by many FastArduino API in order to "yield" some processor time; concretely it ju...
Definition: time.cpp:22
timer
Defines all API to manipulate AVR Timers.
Definition: pulse_timer.h:116
events.h
Support for events management.
timer::RTT::raw_time_
RAW_TIME raw_time_() const
Elapsed time, in raw representation, since this timer has started.
Definition: realtime_timer.h:415
timer::RTT::begin_
void begin_()
Start this real-time timer, hence elapsed time starts getting counted from then.
Definition: realtime_timer.h:460
timer::RTTRawTime
Utility class to avoid costly instantiation of time::RTTTime from an interrupt routine.
Definition: realtime_timer.h:136
time::millis
MILLIS_PTR millis
Count number of milliseconds elapsed since some time base reference (generally since MCU startup).
Definition: time.cpp:20
timer.h
Timer API.
time.h
Simple time utilities.
timer::Timer::end_
void end_()
Completely stop this timer: timer interrupts are disabled and counter is stopped.
Definition: timer.h:1198
timer::Timer::end
void end()
Completely stop this timer: timer interrupts are disabled and counter is stopped.
Definition: timer.h:1183
timer::RTT::time_
time::RTTTime time_() const
Elapsed time, in milliseconds and microseconds, since this timer has started.
Definition: realtime_timer.h:373
timer::Timer
General API to handle an AVR timer.
Definition: timer.h:705
timer::RTT::RTT
RTT()
Construct a new real-time timer handler and initializes its current time to 0ms.
Definition: realtime_timer.h:231
timer::RTT::end
void end()
Stop this real-time timer, hence time gets not counted anymore.
Definition: realtime_timer.h:475
timer::RTT::millis_
uint32_t millis_() const
Elapsed time, in milliseconds, since this timer has started.
Definition: realtime_timer.h:273
timer::RTT::micros
uint16_t micros() const
Compute the microseconds part (from 0 to 999) of the time that has elapsed, since this timer has star...
Definition: realtime_timer.h:312
time::RTTTime
Structure used to hold a time value with microsecond precision.
Definition: time.h:50
containers::Queue::push_
bool push_(TREF item)
Push item to the end of this queue, provided there is still available space in its ring buffer.
timer::RTT::time
time::RTTTime time() const
Elapsed time, in milliseconds and microseconds, since this timer has started.
Definition: realtime_timer.h:354
timer::RTTEventCallback
Utility to generate events from an RTT instance at a given period.
Definition: realtime_timer.h:536
timer::RTT
API to handle a real-time timer.
Definition: realtime_timer.h:204
timer::RTTRawTime::as_real_time
time::RTTTime as_real_time() const
Convert this RTTRawTime instance to a fully usable time::RTTTime.
Definition: realtime_timer.h:165
timer::RTTRawTime::RTTRawTime
RTTRawTime(uint32_t millis, T counter, T max_counter)
Create a new RTTRawTime from millis milliseconds, and values from Timer counter value that will allow...
Definition: realtime_timer.h:150
timer::Timer::begin_
void begin_(TYPE max=0)
Start this timer in the currently selected mode, with the provided prescaler value and max value.
Definition: timer.h:964
interrupts.h
General API for handling AVR interrupt vectors.
timer::RTT::begin
void begin()
Start this real-time timer, hence elapsed time starts getting counted from then.
Definition: realtime_timer.h:445
interrupt::register_handler
void register_handler(Handler &handler)
Register a class instance containing methods that shall be called back by an ISR.
Definition: interrupts.h:157
timer::RTT::micros_
uint16_t micros_() const
Compute the microseconds part (from 0 to 999) of the time that has elapsed, since this timer has star...
Definition: realtime_timer.h:335
timer::RTT::NTIMER
static constexpr const board::Timer NTIMER
The AVR timer used by this RTT.
Definition: realtime_timer.h:207
timer::RTT::millis
uint32_t millis() const
Elapsed time, in milliseconds, since this timer has started.
Definition: realtime_timer.h:252
timer::RTTRawTime::EMPTY_TIME
static constexpr RTTRawTime< T > EMPTY_TIME
A constant to signify "no time".
Definition: realtime_timer.h:158
events::Type::RTT_TIMER
const uint8_t RTT_TIMER
Type of events generated by timer::RTTEventCallback whenever elapsed RTT::millis() reaches a multiple...
Definition: events.h:112
timer::Calculator::CTC_prescaler
static constexpr PRESCALER CTC_prescaler(uint32_t us)
Computes the ideal prescaler value to use for this timer, in TimerMode::CTC mode, in order to be able...
Definition: timer.h:390
timer::RTT::millis
void millis(uint32_t ms)
Reset the current milliseconds count of this RTT to the given value.
Definition: realtime_timer.h:425