Timer.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  * Timer.h
8  *
9  ****/
10 
11 #pragma once
12 
13 #include "Interrupts.h"
14 #include "SimpleTimer.h"
15 
26 template <class TimerClass> class OsTimer64Api : public CallbackTimerApi<OsTimer64Api<TimerClass>>
27 {
28 public:
30  using TickType = uint64_t;
31  using TimeType = uint64_t;
32 
33  static constexpr const char* typeName()
34  {
35  return "OsTimer64Api";
36  }
37 
38  static constexpr TickType minTicks()
39  {
40  return 1;
41  }
42 
43  static constexpr TickType maxTicks()
44  {
45  return Clock::maxTicks() * 0xFFFF;
46  }
47 
49  {
50 #ifndef ARCH_ESP32
51  initCallback();
52 #endif
53  }
54 
56  {
57  disarm();
58  }
59 
60  __forceinline bool IRAM_ATTR isArmed() const
61  {
62  return osTimer.isArmed();
63  }
64 
65  TickType ticks() const
66  {
67  TickType remain = osTimer.ticks();
68  if(longIntervalCounterLimit != 0) {
69  remain += TickType(longIntervalCounterLimit - longIntervalCounter) * osTimer.getInterval();
70  }
71  return remain;
72  }
73 
74  __forceinline void IRAM_ATTR setCallback(TimerCallback callback, void* arg)
75  {
76  this->callback.func = callback;
77  this->callback.arg = arg;
78  }
79 
80  __forceinline void setCallback(TimerDelegate delegateFunction)
81  {
82  delegate = delegateFunction;
83  this->callback.func = nullptr;
84  }
85 
86  void IRAM_ATTR setInterval(TickType interval);
87 
88  TickType IRAM_ATTR getInterval() const
89  {
90  TickType interval = osTimer.getInterval();
91  if(longIntervalCounterLimit != 0) {
92  interval *= longIntervalCounterLimit;
93  }
94  return interval;
95  }
96 
97  __forceinline void IRAM_ATTR arm(bool repeating)
98  {
99 #ifdef ARCH_ESP32
100  initCallback();
101 #endif
102  this->repeating = repeating;
103  osTimer.arm(longIntervalCounterLimit || repeating);
104  }
105 
106  __forceinline void IRAM_ATTR disarm()
107  {
108  osTimer.disarm();
109  longIntervalCounter = 0;
110  }
111 
112 protected:
113  void longTick();
114 
115 private:
116  OsTimerApi osTimer;
117  struct {
118  TimerCallback func = nullptr;
119  void* arg = nullptr;
120  } callback;
121  TimerDelegate delegate;
122  bool repeating = false;
123  // Because of the limitation in Espressif SDK a workaround
124  // was added to allow for longer timer intervals.
125  uint16_t longIntervalCounter = 0;
126  uint16_t longIntervalCounterLimit = 0;
127 
128  void initCallback()
129  {
130  osTimer.setCallback(
131  [](void* arg) {
132  auto self = static_cast<OsTimer64Api*>(arg);
133  self->longTick();
134  },
135  this);
136  }
137 };
138 
139 template <class TimerClass> void OsTimer64Api<TimerClass>::setInterval(TickType interval)
140 {
141  constexpr auto maxTicks = osTimer.maxTicks();
142  if(interval > maxTicks) {
143  // interval too large, calculate a good divider
144  uint32_t div = (interval / (maxTicks + 1)) + 1; // integer division, intended
145 
146  // We will lose some precision here but its so small it won't matter.
147  // Error will be microseconds mod div which can at most be div-1.
148  // For small intervals (and thus small values of div) we are talking a few us.
149 
150  interval /= div;
151  longIntervalCounterLimit = div;
152  } else {
153  longIntervalCounterLimit = 0;
154  }
155  longIntervalCounter = 0;
156  osTimer.setInterval(interval);
157 }
158 
159 template <class TimerClass> void OsTimer64Api<TimerClass>::longTick()
160 {
161  if(longIntervalCounterLimit != 0) {
162  longIntervalCounter++;
163 
164  if(longIntervalCounter < longIntervalCounterLimit) {
165  return;
166  }
167 
168  // For long intervals os_timer is set to repeating.
169  // Stop timer if it was not a repeating timer.
170  if(repeating) {
171  longIntervalCounter = 0;
172  } else {
173  osTimer.disarm();
174  }
175  }
176 
177  if(callback.func != nullptr) {
178  callback.func(callback.arg);
179  } else if(delegate) {
180  delegate();
181  }
182 
183  static_cast<TimerClass*>(this)->expired();
184 }
185 
189 template <typename TimerApi> class DelegateCallbackTimer : public CallbackTimer<TimerApi>
190 {
191 public:
192  using typename TimerApi::TickType;
193  using typename TimerApi::TimeType;
197 
203  template <TimeType microseconds> DelegateCallbackTimer& IRAM_ATTR initializeUs(TimerDelegate delegateFunction)
204  {
205  setCallback(delegateFunction);
206  this->template setIntervalUs<microseconds>();
207  return *this;
208  }
209 
215  template <uint32_t milliseconds> DelegateCallbackTimer& IRAM_ATTR initializeMs(TimerDelegate delegateFunction)
216  {
217  setCallback(delegateFunction);
218  this->template setIntervalMs<milliseconds>();
219  return *this;
220  }
221 
227  DelegateCallbackTimer& initializeMs(uint32_t milliseconds, TimerDelegate delegateFunction)
228  {
229  setCallback(delegateFunction);
230  this->setIntervalMs(milliseconds);
231  return *this;
232  }
233 
239  DelegateCallbackTimer& initializeUs(uint32_t microseconds, TimerDelegate delegateFunction)
240  {
241  setCallback(delegateFunction);
242  this->setIntervalUs(microseconds);
243  return *this;
244  }
245 
250  void setCallback(TimerDelegate delegateFunction)
251  {
252  // Always disarm before setting the callback
253  this->stop();
254  TimerApi::setCallback(delegateFunction);
255  this->callbackSet = bool(delegateFunction);
256  }
257 };
258 
263 {
264 protected:
266 
267  void expired()
268  {
269  }
270 };
271 
275 class AutoDeleteTimer : public DelegateCallbackTimer<OsTimer64Api<AutoDeleteTimer>>
276 {
277 protected:
279 
280  // Ensures object may only be created on the heap
282  {
283  }
284 
285  void expired()
286  {
287  delete this;
288  }
289 };
290 
Auto-delete callback timer class.
Definition: Timer.h:276
~AutoDeleteTimer()
Definition: Timer.h:281
void expired()
Definition: Timer.h:285
Callback timer class template.
Definition: CallbackTimer.h:76
void stop()
Stops timer.
Definition: CallbackTimer.h:239
bool callbackSet
User has provided callback function.
Definition: CallbackTimer.h:423
void setIntervalUs()
Set timer interval in microseconds (static check)
Definition: CallbackTimer.h:372
void setIntervalMs()
Set timer interval in milliseconds (static check)
Definition: CallbackTimer.h:384
Class template adding delegate callback method support to the basic CallbackTimer template.
Definition: Timer.h:190
DelegateCallbackTimer & initializeMs(uint32_t milliseconds, TimerDelegate delegateFunction)
Initialise millisecond timer.
Definition: Timer.h:227
DelegateCallbackTimer & initializeUs(uint32_t microseconds, TimerDelegate delegateFunction)
Initialise microsecond timer.
Definition: Timer.h:239
DelegateCallbackTimer & initializeMs(TimerDelegate delegateFunction)
Initialise hardware timer in milliseconds, with static check.
Definition: Timer.h:215
void setCallback(TimerDelegate delegateFunction)
Set timer trigger function using Delegate callback method.
Definition: Timer.h:250
DelegateCallbackTimer & initializeUs(TimerDelegate delegateFunction)
Initialise timer in microseconds, with static check.
Definition: Timer.h:203
Class template implementing an extended OS Timer with 64-bit microsecond times and delegate callback ...
Definition: Timer.h:27
static constexpr const char * typeName()
Definition: Timer.h:33
~OsTimer64Api()
Definition: Timer.h:55
void * arg
Definition: Timer.h:119
OsTimer64Api()
Definition: Timer.h:48
void setCallback(TimerDelegate delegateFunction)
Definition: Timer.h:80
TimerCallback func
Definition: Timer.h:118
uint64_t TimeType
Definition: Timer.h:31
void setCallback(TimerCallback callback, void *arg)
Definition: Timer.h:74
TickType ticks() const
Definition: Timer.h:65
static constexpr TickType minTicks()
Definition: Timer.h:38
void arm(bool repeating)
Definition: Timer.h:97
TickType getInterval() const
Definition: Timer.h:88
uint64_t TickType
Definition: Timer.h:30
OsTimerApi::Clock Clock
Definition: Timer.h:29
static constexpr TickType maxTicks()
Definition: Timer.h:43
bool isArmed() const
Definition: Timer.h:60
void disarm()
Definition: Timer.h:106
Implements common system callback timer API.
Definition: SimpleTimer.h:33
void setCallback(TimerCallback callback, void *arg)
Definition: SimpleTimer.h:77
TickType getInterval() const
Definition: SimpleTimer.h:87
void arm(bool repeating)
Definition: SimpleTimer.h:92
TickType ticks() const
Definition: SimpleTimer.h:60
bool isArmed() const
Definition: SimpleTimer.h:55
void disarm()
Definition: SimpleTimer.h:97
OsTimerClock Clock
Definition: SimpleTimer.h:35
Callback timer class.
Definition: Timer.h:263
void expired()
Definition: Timer.h:267
void(*)(void *arg) TimerCallback
Interrupt-compatible C callback function pointer.
Definition: CallbackTimer.h:23
void setInterval(TickType interval)
Definition: Timer.h:139
void longTick()
Definition: Timer.h:159
void setCallback(Callback callback)
Set a callback function that is invoked on each change of the current allocation.
Callback timer API class template.
Definition: CallbackTimer.h:30