PolledTimer.h
Go to the documentation of this file.
1 /****
2  * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
3  * Created 2015 by Skurydin Alexey
4  * http://github.com/SmingHub/Sming
5  * All files of the Sming Core are provided under the LGPL v3 license.
6  *
7  * PolledTimer.h - template class to assist with measurement of elapsed time periods
8  *
9  * @author mikee47 <mike@sillyhouse.net>
10  *
11  * Developed from the excellent esp8266 Arduino project's PolledTimer.h
12  * Copyright (c) 2018 Daniel Salazar. All rights reserved.
13  * https://github.com/esp8266/Arduino/blob/master/cores/esp8266/PolledTimeout.h
14  *
15  * Generally Sming uses timer callbacks but for some applications a polled timer
16  * is more appropriate, especially if timer intervals are less than few hundred
17  * microseconds, or even in nanoseconds.
18  *
19  * Here we have the `PolledTimer` template class. See `Platform/Timers.h` for implementations.
20  *
21  ****/
22 
23 #pragma once
24 
25 #include <cstdint>
26 #include <esp_attr.h>
27 #include <sming_attr.h>
28 #include <Platform/Clocks.h>
29 
41 #ifndef POLLED_TIMER_MARGIN_US
42 #define POLLED_TIMER_MARGIN_US 250000
43 #endif
44 
45 namespace PolledTimer
46 {
66 template <class Clock, NanoTime::Unit unit_, bool IsPeriodic, typename TimeType>
67 class Timer : public NanoTime::TimeSource<Clock, unit_, TimeType>
68 {
69 public:
70  static_assert(std::is_unsigned<TimeType>::value == true, "TimeType must be unsigned");
71 
72  using TickType = typename Clock::TickType;
73  using Clock::ticks;
75 
76  static constexpr NanoTime::Unit unit()
77  {
78  return unit_;
79  }
80 
81  static constexpr TickType maxInterval()
82  {
83  return Clock::maxTicks() - Margin::ticks();
84  }
85 
86  static constexpr Margin margin()
87  {
88  return Margin();
89  }
90 
95  IRAM_ATTR Timer(const TimeType& timeInterval = 0)
96  {
97  reset(timeInterval);
98  }
99 
103  __forceinline void IRAM_ATTR start()
104  {
105  startTicks = ticks();
106  if(!IsPeriodic) {
107  // One-shot timers require manual reset
108  hasExpired = false;
109  }
110  }
111 
116  template <uint64_t timeInterval> __forceinline void IRAM_ATTR reset()
117  {
118  auto ticks = checkTime<timeInterval>();
119  resetTicks(ticks);
120  }
121 
128  template <uint64_t timeInterval> constexpr uint32_t checkTime()
129  {
130  auto time = this->template timeConst<timeInterval>();
131  time.check();
132  constexpr auto ticks = time.ticks();
133  static_assert(ticks < maxInterval(), "Polled time interval too long");
134  return ticks;
135  }
136 
143  __forceinline bool IRAM_ATTR reset(const TimeType& timeInterval)
144  {
145  return resetTicks(this->template timeToTicks(timeInterval));
146  }
147 
155  __forceinline bool IRAM_ATTR resetTicks(const TimeType& interval)
156  {
157  start();
158  this->interval = interval;
159  neverExpires = (interval > maxInterval());
160  return !neverExpires;
161  }
162 
166  __forceinline void IRAM_ATTR cancel()
167  {
168  interval = 1; // Ensure canWait() returns true
169  neverExpires = true;
170  if(!IsPeriodic) {
171  hasExpired = true;
172  }
173  }
174 
179  {
180  return ticks() - startTicks;
181  }
182 
187  {
188  return this->template ticksToTime(elapsedTicks());
189  }
190 
192  {
193  return !neverExpires;
194  }
195 
196  __forceinline bool canWait() const
197  {
198  return interval != 0;
199  }
200 
206  {
207  return IsPeriodic ? expiredRetrigger() : expiredOneShot();
208  }
209 
210 private:
211  bool IRAM_ATTR checkExpired(const TickType& ticks) const
212  {
213  // canWait() is not checked here
214  // returns "can expire" and "time expired"
215  return !neverExpires && (TickType(ticks - startTicks) >= interval);
216  }
217 
218  bool IRAM_ATTR expiredRetrigger()
219  {
220  if(!canWait()) {
221  return true;
222  }
223 
224  bool result = false;
225  TickType current = ticks();
226  while(checkExpired(current)) {
227  result = true;
228  startTicks += interval;
229  }
230 
231  return result;
232  }
233 
234  bool IRAM_ATTR expiredOneShot()
235  {
236  // Remain triggered until manually reset or cancelled
237  if(!canWait() || hasExpired) {
238  return true;
239  }
240  hasExpired = checkExpired(ticks());
241  return hasExpired;
242  }
243 
244  TickType startTicks;
245  TickType interval;
246  bool neverExpires;
247  bool hasExpired;
248 };
249 
250 // Standard timer types
251 template <typename Clock, NanoTime::Unit unit> using OneShot = Timer<Clock, unit, false, uint32_t>;
252 template <typename Clock, NanoTime::Unit unit> using Periodic = Timer<Clock, unit, true, uint32_t>;
253 
254 } // namespace PolledTimer
255 
bool canExpire() const
Definition: PolledTimer.h:191
Unit
Identify units for a scalar quantity of time.
Definition: NanoTime.h:45
#define __forceinline
Definition: sming_attr.h:13
bool reset(const TimeType &timeInterval)
Start the timer with a new expiry interval.
Definition: PolledTimer.h:143
static constexpr uint64_t ticks()
Return the corresponding tick value for the time interval.
Definition: NanoTime.h:511
Template class to implement a polled timer.
Definition: PolledTimer.h:67
static constexpr Margin margin()
Definition: PolledTimer.h:86
void cancel()
Cancelling a timer means it will never expire.
Definition: PolledTimer.h:166
bool expired()
Determine if timer has expired.
Definition: PolledTimer.h:205
bool resetTicks(const TimeType &interval)
Start the timer with a new expiry interval.
Definition: PolledTimer.h:155
Class template to represent a fixed time value for a specific Clock.
Definition: NanoTime.h:120
NanoTime::Time< TimeType > elapsedTime() const
Get elapsed time since start() was last called.
Definition: PolledTimer.h:186
Class template for accessing a Clock in specific time units.
Definition: NanoTime.h:122
Time< T > time(Unit unit, T value)
Helper function to create a Time and deduce the type.
Definition: NanoTime.h:429
Timer(const TimeType &timeInterval=0)
Create a Timer with optional expiry time.
Definition: PolledTimer.h:95
Definition: PolledTimer.h:45
void start()
Start the timer.
Definition: PolledTimer.h:103
static constexpr uint64_t ticksToTime()
Get the time for a given number of clock ticks.
Definition: NanoTime.h:734
static constexpr TickType maxInterval()
Definition: PolledTimer.h:81
static constexpr uint64_t timeToTicks()
Get the number of ticks for a given time.
Definition: NanoTime.h:724
bool canWait() const
Definition: PolledTimer.h:196
TickType elapsedTicks() const
Get elapsed ticks since start() was last called.
Definition: PolledTimer.h:178
void reset()
Start the timer with a new expiry interval.
Definition: PolledTimer.h:116
constexpr uint32_t checkTime()
Check the given time interval is valid and return the corresponding tick count.
Definition: PolledTimer.h:128
static constexpr NanoTime::Unit unit()
Definition: PolledTimer.h:76
Class to handle a simple time value with associated unit.
Definition: NanoTime.h:123
typename NanoTime::Nanoseconds ::TickType TickType
Definition: PolledTimer.h:72
NanoTime::TimeConst< Clock, NanoTime::Microseconds, POLLED_TIMER_MARGIN_US > Margin
Definition: PolledTimer.h:74