ReactESP 1.0.0
Asynchronous programming for the ESP microcontrollers
ReactESP.cpp
Go to the documentation of this file.
1#include "ReactESP.h"
2
3#include <Arduino.h>
4#include <FunctionalInterrupt.h>
5#include <string.h>
6
14#ifdef ESP32
15uint64_t ICACHE_RAM_ATTR micros64() { return esp_timer_get_time(); }
16#endif
17
18// Reaction classes define the behaviour of each particular
19// Reaction
20
22 return (this->last_trigger_time + this->interval) <
23 (other.last_trigger_time + other.interval);
24}
25
26void TimedReaction::add() { ReactESP::app->timed_queue.push(this); }
27
29 this->enabled = false;
30 // the object will be deleted when it's popped out of the
31 // timer queue
32}
33
34DelayReaction::DelayReaction(uint32_t interval, const react_callback callback)
35 : TimedReaction(interval, callback) {
36 this->last_trigger_time = micros64();
37}
38
39DelayReaction::DelayReaction(uint64_t interval, const react_callback callback)
40 : TimedReaction(interval, callback) {
41 this->last_trigger_time = micros64();
42}
43
45 this->last_trigger_time = micros64();
46 this->callback();
47 delete this;
48}
49
51 auto now = micros64();
52 this->last_trigger_time = this->last_trigger_time + this->interval;
53 if (this->last_trigger_time + this->interval < now) {
54 // we're lagging more than one full interval; reset the time
55 this->last_trigger_time = now;
56 }
57 this->callback();
58 ReactESP::app->timed_queue.push(this);
59}
60
61void UntimedReaction::add() { ReactESP::app->untimed_list.push_front(this); }
62
64 ReactESP::app->untimed_list.remove(this);
65 delete this;
66}
67
69 if (stream.available()) {
70 this->callback();
71 }
72}
73
74void TickReaction::tick() { this->callback(); }
75
76#ifdef ESP32
77bool ISRReaction::isr_service_installed = false;
78
79void ISRReaction::isr(void* this_ptr) {
80 auto* this_ = (ISRReaction*)this_ptr;
81 this_->callback();
82}
83#endif
84
86#ifdef ESP32
87 gpio_isr_handler_add((gpio_num_t)pin_number, ISRReaction::isr, (void*)this);
88#elif defined(ESP8266)
89 attachInterrupt(digitalPinToInterrupt(pin_number), callback, mode);
90#endif
91 ReactESP::app->isr_reaction_list.push_front(this);
92}
93
95 ReactESP::app->isr_reaction_list.remove(this);
96#ifdef ESP32
97 gpio_isr_handler_remove((gpio_num_t)pin_number);
98#elif defined(ESP8266)
99 detachInterrupt(digitalPinToInterrupt(this->pin_number));
100#endif
101 delete this;
102}
103
104// Need to define the static variable outside of the class
105ReactESP* ReactESP::app = NULL;
106
107void setup(void) { ReactESP::app->setup(); }
108
109void loop(void) {
111 yield();
112}
113
114void ReactESP::tickTimed() {
115 uint64_t now = micros64();
116 uint64_t trigger_t;
117 TimedReaction* top;
118
119 while (true) {
120 if (timed_queue.empty()) {
121 break;
122 }
123 top = timed_queue.top();
124 if (!top->isEnabled()) {
125 timed_queue.pop();
126 delete top;
127 continue;
128 }
129 trigger_t = top->getTriggerTimeMicros();
130 if (now >= trigger_t) {
131 timed_queue.pop();
132 top->tick();
133 } else {
134 break;
135 }
136 }
137}
138
139void ReactESP::tickUntimed() {
140 for (UntimedReaction* re : this->untimed_list) {
141 re->tick();
142 }
143}
144
146 tickUntimed();
147 tickTimed();
148}
149
150DelayReaction* ReactESP::onDelay(const uint32_t t, const react_callback cb) {
151 DelayReaction* dre = new DelayReaction(t, cb);
152 dre->add();
153 return dre;
154}
155
157 const react_callback cb) {
158 DelayReaction* dre = new DelayReaction(t, cb);
159 dre->add();
160 return dre;
161}
162
164 RepeatReaction* rre = new RepeatReaction(t, cb);
165 rre->add();
166 return rre;
167}
168
170 const react_callback cb) {
171 RepeatReaction* rre = new RepeatReaction(t, cb);
172 rre->add();
173 return rre;
174}
175
177 StreamReaction* sre = new StreamReaction(stream, cb);
178 sre->add();
179 return sre;
180}
181
182ISRReaction* ReactESP::onInterrupt(const uint8_t pin_number, int mode,
183 const react_callback cb) {
184 ISRReaction* isrre = new ISRReaction(pin_number, mode, cb);
185 isrre->add();
186 return isrre;
187}
188
190 TickReaction* tre = new TickReaction(cb);
191 tre->add();
192 return tre;
193}
void loop(void)
Definition: ReactESP.cpp:109
void setup(void)
Definition: ReactESP.cpp:107
std::function< void()> react_callback
Definition: ReactESP.h:10
Reaction that is triggered after a certain time delay.
Definition: ReactESP.h:92
DelayReaction(const uint32_t delay, const react_callback callback)
Construct a new Delay Reaction object.
Definition: ReactESP.cpp:34
void tick()
Definition: ReactESP.cpp:44
Reaction that is triggered on an input pin change.
Definition: ReactESP.h:185
void remove()
Definition: ReactESP.cpp:94
void add()
Definition: ReactESP.cpp:85
Main class of a ReactESP program.
Definition: ReactESP.h:245
ISRReaction * onInterrupt(const uint8_t pin_number, int mode, const react_callback cb)
Create a new ISRReaction (interrupt reaction)
Definition: ReactESP.cpp:182
static ReactESP * app
Static singleton reference to the instantiated ReactESP object.
Definition: ReactESP.h:265
RepeatReaction * onRepeatMicros(const uint64_t t, const react_callback cb)
Create a new RepeatReaction.
Definition: ReactESP.cpp:169
friend class RepeatReaction
Definition: ReactESP.h:248
friend class ISRReaction
Definition: ReactESP.h:250
TickReaction * onTick(const react_callback cb)
Create a new TickReaction.
Definition: ReactESP.cpp:189
StreamReaction * onAvailable(Stream &stream, const react_callback cb)
Create a new StreamReaction.
Definition: ReactESP.cpp:176
void setup(void)
Definition: ReactESP.h:261
DelayReaction * onDelay(const uint32_t t, const react_callback cb)
Create a new DelayReaction.
Definition: ReactESP.cpp:150
DelayReaction * onDelayMicros(const uint64_t t, const react_callback cb)
Create a new DelayReaction.
Definition: ReactESP.cpp:156
RepeatReaction * onRepeat(const uint32_t t, const react_callback cb)
Create a new RepeatReaction.
Definition: ReactESP.cpp:163
void tick(void)
Definition: ReactESP.cpp:145
const react_callback callback
Definition: ReactESP.h:27
Reaction that is triggered repeatedly.
Definition: ReactESP.h:115
Reaction that is triggered when there is input available at the given Arduino Stream.
Definition: ReactESP.h:152
Reaction that is triggered unconditionally at each execution loop.
Definition: ReactESP.h:171
void tick()
Definition: ReactESP.cpp:74
TimedReactions are called based on elapsing of time.
Definition: ReactESP.h:45
void add()
Definition: ReactESP.cpp:26
uint64_t last_trigger_time
Definition: ReactESP.h:48
bool operator<(const TimedReaction &other)
Return the current time since the device restart in microseconds.
Definition: ReactESP.cpp:21
uint64_t getTriggerTimeMicros()
Definition: ReactESP.h:80
virtual void tick()=0
void remove()
Definition: ReactESP.cpp:28
const uint64_t interval
Definition: ReactESP.h:47
bool enabled
Definition: ReactESP.h:49
bool isEnabled()
Definition: ReactESP.h:81
Reactions that are triggered based on something else than time.
Definition: ReactESP.h:139
virtual void remove()
Definition: ReactESP.cpp:63
virtual void add()
Definition: ReactESP.cpp:61
void ICACHE_RAM_ATTR isr()
Definition: main.cpp:18