7 #ifndef MULTI_TIMER_HPP__
8 #define MULTI_TIMER_HPP__
12 #include "freertos/semphr.h"
19 #define TICKER_MEMBER_CALL(NON_STATIC_MEMBER_FN) \
20 [](decltype(this) self){self->NON_STATIC_MEMBER_FN();}, this
21 #define TICKER_MEMBER_CALL_WITH_COUNT(NON_STATIC_MEMBER_FN) \
22 [](decltype(this) self, uint32_t i){self->NON_STATIC_MEMBER_FN(i);}, this
44 using type_identity_t =
typename type_identity<T>::type;
47 using callback_with_arg_and_count_t = void (*)(
void*, uint32_t);
55 _reentry_mutex = xSemaphoreCreateMutex();
56 assert(_reentry_mutex);
122 template <
typename TArg>
124 uint32_t total_repeat_count,
125 void (*callback)(type_identity_t<TArg>, uint32_t),
127 bool first_tick_nodelay=
false) {
128 static_assert(
sizeof(TArg) <=
sizeof(uint32_t),
129 "attach_ms() callback argument size must be <= 4 bytes");
130 _interval_ms = milliseconds;
131 _repeat_count_requested = total_repeat_count;
132 _callback =
reinterpret_cast<callback_t
>(callback);
133 _orig_arg = (uint32_t)arg;
134 _first_tick_nodelay = first_tick_nodelay;
135 _cb_lambda = [](
void *_this){
136 auto self =
static_cast<decltype(this)
>(_this);
138 auto repeat_count = ++
self->_repeat_count;
139 if (repeat_count < self->_repeat_count_requested) {
140 esp_timer_start_once(self->_timer, self->_interval_ms*1000ull);
142 self->_repeat_count = 0;
144 auto cb =
reinterpret_cast<callback_with_arg_and_count_t
>(
self->_callback);
145 auto arg = (TArg)(self->_orig_arg);
146 cb(arg, repeat_count);
149 return _attach_ms((uint32_t)
this);
152 template <
typename TArg>
154 uint32_t total_repeat_count,
155 void (*callback)(type_identity_t<TArg>),
157 bool first_tick_nodelay=
false) {
158 static_assert(
sizeof(TArg) <=
sizeof(uint32_t),
159 "attach_ms() callback argument size must be <= 4 bytes");
160 _interval_ms = milliseconds;
161 _repeat_count_requested = total_repeat_count;
162 _callback =
reinterpret_cast<callback_t
>(callback);
163 _orig_arg = (uint32_t)arg;
164 _first_tick_nodelay = first_tick_nodelay;
165 _cb_lambda = [](
void *_this){
166 auto self =
static_cast<decltype(this)
>(_this);
168 auto repeat_count = ++
self->_repeat_count;
169 if (repeat_count < self->_repeat_count_requested) {
170 esp_timer_start_once(self->_timer, self->_interval_ms*1000ull);
172 self->_repeat_count = 0;
174 auto cb =
reinterpret_cast<callback_with_arg_t
>(
self->_callback);
175 auto arg = (TArg)(self->_orig_arg);
179 return _attach_ms((uint32_t)
this);
183 uint32_t total_repeat_count,
185 bool first_tick_nodelay=
false) {
186 _interval_ms = milliseconds;
187 _repeat_count_requested = total_repeat_count;
188 _callback =
reinterpret_cast<callback_t
>(callback);
189 _first_tick_nodelay = first_tick_nodelay;
190 _cb_lambda = [](
void *_this){
191 auto self =
static_cast<decltype(this)
>(_this);
193 auto repeat_count = ++
self->_repeat_count;
194 if (repeat_count < self->_repeat_count_requested) {
195 esp_timer_start_once(self->_timer, self->_interval_ms*1000ull);
197 self->_repeat_count = 0;
202 return _attach_ms((uint32_t)
this);
209 if (_first_tick_nodelay && _cb_lambda) {
212 esp_timer_start_once(_timer, _interval_ms*1000ull);
215 void start(uint32_t interval_ms) {
216 _interval_ms = interval_ms;
217 if (_first_tick_nodelay && _cb_lambda) {
220 esp_timer_start_once(_timer, _interval_ms*1000ull);
225 esp_timer_stop(_timer);
228 esp_err_t stop_return_errors() {
229 auto errors = esp_timer_stop(_timer);
235 esp_timer_stop(_timer);
237 esp_err_t pause_return_errors() {
238 return esp_timer_stop(_timer);
242 esp_timer_start_once(_timer, _interval_ms*1000ull);
244 esp_err_t resume_return_errors() {
245 return esp_timer_start_once(_timer, _interval_ms*1000ull);
249 using Ticker::detach;
250 using Ticker::active;
253 using Ticker::_timer;
254 uint32_t _interval_ms;
255 uint32_t _repeat_count_requested{1};
256 uint32_t _repeat_count{0};
258 callback_t _callback;
259 uint32_t _orig_arg{0};
261 callback_with_arg_t _cb_lambda{
nullptr};
262 bool _first_tick_nodelay{
false};
263 SemaphoreHandle_t _reentry_mutex = NULL;
265 esp_err_t _attach_ms(uint32_t arg) {
266 esp_timer_create_args_t _timerConfig;
267 _timerConfig.callback = _cb_lambda;
268 _timerConfig.arg =
reinterpret_cast<void*
>(arg);
269 _timerConfig.dispatch_method = ESP_TIMER_TASK;
270 _timerConfig.name =
"MultiTimer";
272 esp_timer_stop(_timer);
273 esp_timer_delete(_timer);
275 return esp_timer_create(&_timerConfig, &_timer);
278 inline void _mutex_take() {
279 xSemaphoreTake(_reentry_mutex, portMAX_DELAY);
282 inline void _mutex_give() {
283 xSemaphoreGive(_reentry_mutex);
302 template<
typename TClass>
306 using mem_func_ptr_t = void (TClass::*)();
307 using mem_func_ptr_with_count_t = void (TClass::*)(uint32_t);
325 uint32_t total_repeat_count,
326 mem_func_ptr_t mem_func_ptr,
328 bool first_tick_nodelay=
false) {
329 _interval_ms = milliseconds;
330 _repeat_count_requested = total_repeat_count;
331 _mem_func_ptr = mem_func_ptr;
332 _orig_arg =
reinterpret_cast<uint32_t
>(inst);
333 _first_tick_nodelay = first_tick_nodelay;
334 _cb_lambda = [](
void *_this){
335 auto self =
static_cast<decltype(this)
>(_this);
337 auto repeat_count = ++
self->_repeat_count;
338 if (repeat_count < self->_repeat_count_requested) {
339 esp_timer_start_once(self->_timer, self->_interval_ms*1000ull);
341 self->_repeat_count = 0;
343 auto inst =
reinterpret_cast<TClass*
>(
self->_orig_arg);
345 auto mfp =
self->_mem_func_ptr;
349 return _attach_ms((uint32_t)
this);
353 uint32_t total_repeat_count,
354 mem_func_ptr_with_count_t mem_func_ptr,
356 bool first_tick_nodelay=
false) {
357 _interval_ms = milliseconds;
358 _repeat_count_requested = total_repeat_count;
359 _mem_func_ptr =
reinterpret_cast<mem_func_ptr_t
>(mem_func_ptr);
361 _orig_arg =
reinterpret_cast<uint32_t
>(inst);
362 _first_tick_nodelay = first_tick_nodelay;
363 _cb_lambda = [](
void *_this){
364 auto self =
static_cast<decltype(this)
>(_this);
366 auto repeat_count = ++
self->_repeat_count;
367 if (repeat_count < self->_repeat_count_requested) {
368 esp_timer_start_once(self->_timer, self->_interval_ms*1000ull);
370 self->_repeat_count = 0;
372 auto inst =
reinterpret_cast<TClass*
>(
self->_orig_arg);
374 auto mfp =
reinterpret_cast<mem_func_ptr_with_count_t
>(
self->_mem_func_ptr);
376 (inst->*mfp)(repeat_count);
379 return _attach_ms((uint32_t)
this);
383 mem_func_ptr_t _mem_func_ptr;
Ticker timer derivative allowing for a fixed number of repeated calls.
Definition: multi_timer.hpp:35
void start()
Definition: multi_timer.hpp:208
esp_err_t attach_static_ms(uint32_t milliseconds, uint32_t total_repeat_count, void(*callback)(type_identity_t< TArg >, uint32_t), TArg arg, bool first_tick_nodelay=false)
Attach a free function, static member function or a non-capturing lambda function to the timer.
Definition: multi_timer.hpp:123
Same as MultiTimer but allows a pointer to a non-static member function as a callback.
Definition: multi_timer.hpp:304
esp_err_t attach_mem_func_ptr_ms(uint32_t milliseconds, uint32_t total_repeat_count, mem_func_ptr_t mem_func_ptr, TClass *inst, bool first_tick_nodelay=false)
Same as attach_static_ms() but taking a pointer to a non-static member function as a callback,...
Definition: multi_timer.hpp:324
Definition: multi_timer.hpp:42