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