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 
24 typedef std::function<void()> TimerDelegateStdFunction SMING_DEPRECATED;
25 
29 template <class TimerClass> class OsTimer64Api : public CallbackTimerApi<OsTimer64Api<TimerClass>>
30 {
31 public:
33  using TickType = uint64_t;
34  using TimeType = uint64_t;
35 
36  static constexpr const char* typeName()
37  {
38  return "OsTimer64Api";
39  }
40 
41  static constexpr TickType minTicks()
42  {
43  return 1;
44  }
45 
46  static constexpr TickType maxTicks()
47  {
48  return Clock::maxTicks() * 0xFFFF;
49  }
50 
52  {
53  osTimer.setCallback(
54  [](void* arg) {
55  auto self = static_cast<OsTimer64Api*>(arg);
56  self->longTick();
57  },
58  this);
59  }
60 
62  {
63  disarm();
64  }
65 
66  __forceinline bool IRAM_ATTR isArmed() const
67  {
68  return osTimer.isArmed();
69  }
70 
71  TickType ticks() const
72  {
73  TickType remain = osTimer.ticks();
74  if(longIntervalCounterLimit != 0) {
75  remain += TickType(longIntervalCounterLimit - longIntervalCounter) * osTimer.getInterval();
76  }
77  return remain;
78  }
79 
80  __forceinline void IRAM_ATTR setCallback(TimerCallback callback, void* arg)
81  {
82  this->callback.func = callback;
83  this->callback.arg = arg;
84  }
85 
86  __forceinline void setCallback(TimerDelegate delegateFunction)
87  {
88  delegate = delegateFunction;
89  this->callback.func = nullptr;
90  }
91 
92  void IRAM_ATTR setInterval(TickType interval);
93 
94  TickType IRAM_ATTR getInterval() const
95  {
96  TickType interval = osTimer.getInterval();
97  if(longIntervalCounterLimit != 0) {
98  interval *= longIntervalCounterLimit;
99  }
100  return interval;
101  }
102 
103  __forceinline void IRAM_ATTR arm(bool repeating)
104  {
105  this->repeating = repeating;
106  osTimer.arm(longIntervalCounterLimit || repeating);
107  }
108 
109  __forceinline void IRAM_ATTR disarm()
110  {
111  osTimer.disarm();
112  longIntervalCounter = 0;
113  }
114 
115 protected:
116  void longTick();
117 
118 private:
119  OsTimerApi osTimer;
120  struct {
121  TimerCallback func = nullptr;
122  void* arg = nullptr;
123  } callback;
124  TimerDelegate delegate;
125  bool repeating = false;
126  // Because of the limitation in Espressif SDK a workaround
127  // was added to allow for longer timer intervals.
128  uint16_t longIntervalCounter = 0;
129  uint16_t longIntervalCounterLimit = 0;
130 };
131 
132 template <class TimerClass> void OsTimer64Api<TimerClass>::setInterval(TickType interval)
133 {
134  constexpr auto maxTicks = osTimer.maxTicks();
135  if(interval > maxTicks) {
136  // interval too large, calculate a good divider
137  uint32_t div = (interval / (maxTicks + 1)) + 1; // integer division, intended
138 
139  // We will lose some precision here but its so small it won't matter.
140  // Error will be microseconds mod div which can at most be div-1.
141  // For small intervals (and thus small values of div) we are talking a few us.
142 
143  interval /= div;
144  longIntervalCounterLimit = div;
145  } else {
146  longIntervalCounterLimit = 0;
147  }
148  longIntervalCounter = 0;
149  osTimer.setInterval(interval);
150 }
151 
152 template <class TimerClass> void OsTimer64Api<TimerClass>::longTick()
153 {
154  if(longIntervalCounterLimit != 0) {
155  longIntervalCounter++;
156 
157  if(longIntervalCounter < longIntervalCounterLimit) {
158  return;
159  }
160 
161  // For long intervals os_timer is set to repeating.
162  // Stop timer if it was not a repeating timer.
163  if(repeating) {
164  longIntervalCounter = 0;
165  } else {
166  osTimer.disarm();
167  }
168  }
169 
170  if(callback.func != nullptr) {
171  callback.func(callback.arg);
172  } else if(delegate) {
173  delegate();
174  }
175 
176  static_cast<TimerClass*>(this)->expired();
177 }
178 
182 template <typename TimerApi> class DelegateCallbackTimer : public CallbackTimer<TimerApi>
183 {
184 public:
185  using typename TimerApi::TickType;
186  using typename TimerApi::TimeType;
190 
196  template <TimeType microseconds> DelegateCallbackTimer& IRAM_ATTR initializeUs(TimerDelegate delegateFunction)
197  {
198  setCallback(delegateFunction);
199  this->template setIntervalUs<microseconds>();
200  return *this;
201  }
202 
208  template <uint32_t milliseconds> DelegateCallbackTimer& IRAM_ATTR initializeMs(TimerDelegate delegateFunction)
209  {
210  setCallback(delegateFunction);
211  this->template setIntervalMs<milliseconds>();
212  return *this;
213  }
214 
220  DelegateCallbackTimer& initializeMs(uint32_t milliseconds, TimerDelegate delegateFunction)
221  {
222  setCallback(delegateFunction);
223  this->setIntervalMs(milliseconds);
224  return *this;
225  }
226 
232  DelegateCallbackTimer& initializeUs(uint32_t microseconds, TimerDelegate delegateFunction)
233  {
234  setCallback(delegateFunction);
235  this->setIntervalUs(microseconds);
236  return *this;
237  }
238 
243  void setCallback(TimerDelegate delegateFunction)
244  {
245  // Always disarm before setting the callback
246  this->stop();
247  TimerApi::setCallback(delegateFunction);
248  this->callbackSet = bool(delegateFunction);
249  }
250 };
251 
256 {
257 protected:
259 
260  void expired()
261  {
262  }
263 };
264 
268 class AutoDeleteTimer : public DelegateCallbackTimer<OsTimer64Api<AutoDeleteTimer>>
269 {
270 protected:
272 
273  // Ensures object may only be created on the heap
275  {
276  }
277 
278  void expired()
279  {
280  delete this;
281  }
282 };
283 
#define __forceinline
Definition: sming_attr.h:13
uint64_t TickType
Definition: Timer.h:33
static constexpr const char * typeName()
Definition: Timer.h:36
void disarm()
Definition: SimpleTimer.h:95
void expired()
Definition: Timer.h:260
static constexpr TickType minTicks()
Definition: Timer.h:41
uint64_t TimeType
Definition: Timer.h:34
void disarm()
Definition: Timer.h:109
void(* TimerCallback)(void *arg)
Interrupt-compatible C callback function pointer.
Definition: CallbackTimer.h:23
void setCallback(TimerDelegate delegateFunction)
Set timer trigger function using Delegate callback method.
Definition: Timer.h:243
void * arg
Definition: Timer.h:122
void setCallback(TimerCallback callback, void *arg)
Definition: SimpleTimer.h:75
Clock implementation for Hardware Timer 2.
Definition: Clocks.h:55
static constexpr MaxTicks maxTicks()
Definition: NanoTime.h:156
TickType ticks() const
Definition: SimpleTimer.h:60
void longTick()
Definition: Timer.h:152
Callback timer class template.
Definition: CallbackTimer.h:70
static constexpr TickType maxTicks()
Definition: Timer.h:46
DelegateCallbackTimer & initializeMs(TimerDelegate delegateFunction)
Initialise hardware timer in milliseconds, with static check.
Definition: Timer.h:208
TickType ticks() const
Definition: Timer.h:71
#define SMING_DEPRECATED
Definition: sming_attr.h:30
bool isArmed() const
Definition: Timer.h:66
TimerCallback func
Definition: Timer.h:121
void arm(bool repeating)
Definition: SimpleTimer.h:90
DelegateCallbackTimer & initializeMs(uint32_t milliseconds, TimerDelegate delegateFunction)
Initialise millisecond timer.
Definition: Timer.h:220
void arm(bool repeating)
Definition: Timer.h:103
Implements common system callback timer API.
Definition: SimpleTimer.h:32
void setInterval(TickType interval)
Definition: Timer.h:132
void setCallback(TimerDelegate delegateFunction)
Definition: Timer.h:86
Auto-delete callback timer class.
Definition: Timer.h:268
~AutoDeleteTimer()
Definition: Timer.h:274
TickType getInterval() const
Definition: SimpleTimer.h:85
bool isArmed() const
Definition: SimpleTimer.h:55
void expired()
Definition: Timer.h:278
TickType getInterval() const
Definition: Timer.h:94
Callback timer API class template.
Definition: CallbackTimer.h:30
Class template implementing an extended OS Timer with 64-bit microsecond times and delegate callback ...
Definition: Timer.h:29
DelegateCallbackTimer & initializeUs(uint32_t microseconds, TimerDelegate delegateFunction)
Initialise microsecond timer.
Definition: Timer.h:232
static constexpr TickType maxTicks()
Definition: SimpleTimer.h:50
std::function< void()> TimerDelegateStdFunction
Definition: Timer.h:24
DelegateCallbackTimer & initializeUs(TimerDelegate delegateFunction)
Initialise timer in microseconds, with static check.
Definition: Timer.h:196
void setCallback(TimerCallback callback, void *arg)
Definition: Timer.h:80
Callback timer class.
Definition: Timer.h:255
OsTimer64Api()
Definition: Timer.h:51
Timer2Clock Clock
Definition: SimpleTimer.h:35
void setInterval(TickType interval)
Definition: SimpleTimer.h:80
~OsTimer64Api()
Definition: Timer.h:61
Class template adding delegate callback method support to the basic CallbackTimer template...
Definition: Timer.h:182