|
23 | 23 | #include "eagle_soc.h"
|
24 | 24 | #include "osapi.h"
|
25 | 25 |
|
| 26 | +#include <Arduino.h> |
26 | 27 | #include "Ticker.h"
|
27 | 28 |
|
28 |
| -Ticker::Ticker() |
29 |
| - : _timer(nullptr) {} |
| 29 | +// ETSTimer is part of the instance, and we don't have any state besides |
| 30 | +// the things required for the callback. Allow copies and moves, but |
| 31 | +// disable any member copies and default-init + detach() instead. |
30 | 32 |
|
31 | 33 | Ticker::~Ticker()
|
32 | 34 | {
|
33 | 35 | detach();
|
34 | 36 | }
|
35 | 37 |
|
36 |
| -void Ticker::_attach_ms(uint32_t milliseconds, bool repeat, callback_with_arg_t callback, void* arg) |
| 38 | +Ticker::Ticker(const Ticker&) |
37 | 39 | {
|
38 |
| - if (_timer) |
39 |
| - { |
| 40 | +} |
| 41 | + |
| 42 | +Ticker& Ticker::operator=(const Ticker&) |
| 43 | +{ |
| 44 | + detach(); |
| 45 | + return *this; |
| 46 | +} |
| 47 | + |
| 48 | +Ticker::Ticker(Ticker&& other) noexcept |
| 49 | +{ |
| 50 | + other.detach(); |
| 51 | +} |
| 52 | + |
| 53 | +Ticker& Ticker::operator=(Ticker&& other) noexcept |
| 54 | +{ |
| 55 | + other.detach(); |
| 56 | + detach(); |
| 57 | + return *this; |
| 58 | +} |
| 59 | + |
| 60 | +void Ticker::_attach(Ticker::Milliseconds milliseconds, bool repeat) |
| 61 | +{ |
| 62 | + if (_timer) { |
40 | 63 | os_timer_disarm(_timer);
|
| 64 | + } else { |
| 65 | + _timer = &_timer_internal; |
41 | 66 | }
|
42 |
| - else |
43 |
| - { |
44 |
| - _timer = &_etsTimer; |
| 67 | + |
| 68 | + os_timer_setfn(_timer, |
| 69 | + [](void* ptr) { |
| 70 | + reinterpret_cast<Ticker*>(ptr)->_static_callback(); |
| 71 | + }, this); |
| 72 | + |
| 73 | + _repeat = repeat; |
| 74 | + |
| 75 | + // whenever duration excedes this limit, make timer repeatable N times |
| 76 | + // in case it is really repeatable, it will reset itself and continue as usual |
| 77 | + size_t total = 0; |
| 78 | + if (milliseconds > DurationMax) { |
| 79 | + total = 1; |
| 80 | + while (milliseconds > DurationMax) { |
| 81 | + total *= 2; |
| 82 | + milliseconds /= 2; |
| 83 | + } |
| 84 | + _tick.reset(new callback_tick_t{ |
| 85 | + .total = total, |
| 86 | + .count = 0, |
| 87 | + }); |
| 88 | + repeat = true; |
45 | 89 | }
|
46 | 90 |
|
47 |
| - os_timer_setfn(_timer, callback, arg); |
48 |
| - os_timer_arm(_timer, milliseconds, repeat); |
| 91 | + os_timer_arm(_timer, milliseconds.count(), repeat); |
49 | 92 | }
|
50 | 93 |
|
51 | 94 | void Ticker::detach()
|
52 | 95 | {
|
53 |
| - if (!_timer) |
54 |
| - return; |
55 |
| - |
56 |
| - os_timer_disarm(_timer); |
57 |
| - _timer = nullptr; |
58 |
| - _callback_function = nullptr; |
| 96 | + if (_timer) { |
| 97 | + os_timer_disarm(_timer); |
| 98 | + _timer = nullptr; |
| 99 | + _tick.reset(nullptr); |
| 100 | + _callback = std::monostate{}; |
| 101 | + } |
59 | 102 | }
|
60 | 103 |
|
61 | 104 | bool Ticker::active() const
|
62 | 105 | {
|
63 |
| - return _timer; |
| 106 | + return _timer != nullptr; |
64 | 107 | }
|
65 | 108 |
|
66 |
| -void Ticker::_static_callback(void* arg) |
| 109 | +void Ticker::_static_callback() |
67 | 110 | {
|
68 |
| - Ticker* _this = reinterpret_cast<Ticker*>(arg); |
69 |
| - if (_this && _this->_callback_function) |
70 |
| - _this->_callback_function(); |
| 111 | + if (_tick) { |
| 112 | + ++_tick->count; |
| 113 | + if (_tick->count < _tick->total) { |
| 114 | + return; |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + std::visit([](auto&& callback) { |
| 119 | + using T = std::decay_t<decltype(callback)>; |
| 120 | + if constexpr (std::is_same_v<T, callback_ptr_t>) { |
| 121 | + callback.func(callback.arg); |
| 122 | + } else if constexpr (std::is_same_v<T, callback_function_t>) { |
| 123 | + callback(); |
| 124 | + } |
| 125 | + }, _callback); |
| 126 | + |
| 127 | + if (_repeat) { |
| 128 | + if (_tick) { |
| 129 | + _tick->count = 0; |
| 130 | + } |
| 131 | + return; |
| 132 | + } |
| 133 | + |
| 134 | + detach(); |
71 | 135 | }
|
0 commit comments