Skip to content

Commit

Permalink
Merge pull request #7 from mairas/micros
Browse files Browse the repository at this point in the history
Internal microsecond time tracking
  • Loading branch information
mairas authored Dec 11, 2020
2 parents 9016acc + ea08b4f commit bec4654
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 97 deletions.
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BasedOnStyle: Google
IndentWidth: 2
47 changes: 44 additions & 3 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,48 @@
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:nodemcuv2]
platform = espressif8266
board = nodemcuv2
; [env:nodemcuv2]
; platform = espressif8266
; board = nodemcuv2
; framework = arduino

[platformio]
default_envs =
d1_mini

[env]
; Global data for all [env:***]
framework = arduino
lib_ldf_mode = deep
monitor_speed = 115200

[espressif8266_base]
;this section has config items common to all ESP8266 boards
platform = espressif8266
build_flags =
-Wl,-Teagle.flash.4m1m.ld
-Wall
-Wno-reorder

[env:d1_mini]
extends = espressif8266_base
board = d1_mini
build_flags =
${espressif8266_base.build_flags}
-D LED_BUILTIN=2
board_build.f_cpu = 160000000L
upload_resetmethod = nodemcu
upload_speed = 460800

[espressif32_base]
;this section has config items common to all ESP32 boards
platform = espressif32
build_unflags = -Werror=reorder
board_build.partitions = min_spiffs.csv
monitor_filters = esp32_exception_decoder

[env:esp32dev]
extends = espressif32_base
board = esp32dev
build_flags =
-D LED_BUILTIN=2
199 changes: 110 additions & 89 deletions src/ReactESP.cpp
Original file line number Diff line number Diff line change
@@ -1,155 +1,176 @@
#include "ReactESP.h"

#include <Arduino.h>
#include <string.h>
#include <FunctionalInterrupt.h>
#include <string.h>

#include "ReactESP.h"
/**
* @brief Return the current time since the device restart in microseconds
*
* Returns the time since the device restart. Even though the time
* is in microseconds, a 64-bit integer is all but guaranteed not to
* rewrap, ever.
*/
#ifdef ESP32
uint64_t ICACHE_RAM_ATTR micros64() { return esp_timer_get_time(); }
#endif

// Reaction classes define the behaviour of each particular
// Reaction

bool TimedReaction::operator<(const TimedReaction& other) {
return (this->last_trigger_time + this->interval) <
(other.last_trigger_time + other.interval);
return (this->last_trigger_time + this->interval) <
(other.last_trigger_time + other.interval);
}

void TimedReaction::add() {
ReactESP::app->timed_queue.push(this);
}
void TimedReaction::add() { ReactESP::app->timed_queue.push(this); }

void TimedReaction::remove() {
this->enabled = false;
// the object will be deleted when it's popped out of the
// timer queue
this->enabled = false;
// the object will be deleted when it's popped out of the
// timer queue
}

DelayReaction::DelayReaction(uint32_t interval, const react_callback callback)
: TimedReaction(interval, callback) {
this->last_trigger_time = millis();
DelayReaction::DelayReaction(uint32_t interval, const react_callback callback)
: TimedReaction(interval, callback) {
this->last_trigger_time = micros64();
}

void DelayReaction::tick() {
this->last_trigger_time = millis();
this->callback();
delete this;
DelayReaction::DelayReaction(uint64_t interval, const react_callback callback)
: TimedReaction(interval, callback) {
this->last_trigger_time = micros64();
}

void DelayReaction::tick() {
this->last_trigger_time = micros64();
this->callback();
delete this;
}

void RepeatReaction::tick() {
this->last_trigger_time = millis();
this->callback();
ReactESP::app->timed_queue.push(this);
auto now = micros64();
this->last_trigger_time = this->last_trigger_time + this->interval;
if (this->last_trigger_time + this->interval < now) {
// we're lagging more than one full interval; reset the time
this->last_trigger_time = now;
}
this->callback();
ReactESP::app->timed_queue.push(this);
}


void UntimedReaction::add() {
ReactESP::app->untimed_list.push_front(this);
}
void UntimedReaction::add() { ReactESP::app->untimed_list.push_front(this); }

void UntimedReaction::remove() {
ReactESP::app->untimed_list.remove(this);
delete this;
ReactESP::app->untimed_list.remove(this);
delete this;
}


void StreamReaction::tick() {
if (stream.available()) {
this->callback();
}
}


void TickReaction::tick() {
if (stream.available()) {
this->callback();
}
}

void TickReaction::tick() { this->callback(); }

void ISRReaction::add() {
attachInterrupt(digitalPinToInterrupt(pin_number), callback, mode);
ReactESP::app->isr_reaction_list.push_front(this);
attachInterrupt(digitalPinToInterrupt(pin_number), callback, mode);
ReactESP::app->isr_reaction_list.push_front(this);
}

void ISRReaction::remove() {
ReactESP::app->isr_reaction_list.remove(this);
detachInterrupt(digitalPinToInterrupt(this->pin_number));
delete this;
ReactESP::app->isr_reaction_list.remove(this);
detachInterrupt(digitalPinToInterrupt(this->pin_number));
delete this;
}

// Need to define the static variable outside of the class
ReactESP* ReactESP::app = NULL;

void setup(void)
{
ReactESP::app->setup();
}
void setup(void) { ReactESP::app->setup(); }

void loop(void)
{
ReactESP::app->tick();
yield();
void loop(void) {
ReactESP::app->tick();
yield();
}

void ReactESP::tickTimed() {
uint32_t now = millis();
uint32_t trigger_t;
TimedReaction* top;

while (true) {
if (timed_queue.empty()) {
break;
}
top = timed_queue.top();
if (!top->isEnabled()) {
timed_queue.pop();
delete top;
continue;
}
trigger_t = top->getTriggerTime();
if (now>=trigger_t) {
timed_queue.pop();
top->tick();
} else {
break;
}
uint64_t now = micros64();
uint64_t trigger_t;
TimedReaction* top;

while (true) {
if (timed_queue.empty()) {
break;
}
top = timed_queue.top();
if (!top->isEnabled()) {
timed_queue.pop();
delete top;
continue;
}
trigger_t = top->getTriggerTimeMicros();
if (now >= trigger_t) {
timed_queue.pop();
top->tick();
} else {
break;
}
}
}

void ReactESP::tickUntimed() {
for (UntimedReaction* re : this->untimed_list) {
re->tick();
}
for (UntimedReaction* re : this->untimed_list) {
re->tick();
}
}

void ReactESP::tick() {
tickUntimed();
tickTimed();
tickUntimed();
tickTimed();
}

DelayReaction* ReactESP::onDelay(const uint32_t t, const react_callback cb) {
DelayReaction* dre = new DelayReaction(t, cb);
dre->add();
return dre;
DelayReaction* dre = new DelayReaction(t, cb);
dre->add();
return dre;
}

DelayReaction* ReactESP::onDelayMicros(const uint64_t t,
const react_callback cb) {
DelayReaction* dre = new DelayReaction(t, cb);
dre->add();
return dre;
}

RepeatReaction* ReactESP::onRepeat(const uint32_t t, const react_callback cb) {
RepeatReaction* rre = new RepeatReaction(t, cb);
rre->add();
return rre;
RepeatReaction* rre = new RepeatReaction(t, cb);
rre->add();
return rre;
}

RepeatReaction* ReactESP::onRepeatMicros(const uint64_t t,
const react_callback cb) {
RepeatReaction* rre = new RepeatReaction(t, cb);
rre->add();
return rre;
}

StreamReaction* ReactESP::onAvailable(Stream& stream, const react_callback cb) {
StreamReaction *sre = new StreamReaction(stream, cb);
sre->add();
return sre;
StreamReaction* sre = new StreamReaction(stream, cb);
sre->add();
return sre;
}

ISRReaction* ReactESP::onInterrupt(const uint8_t pin_number, int mode, const react_callback cb) {
ISRReaction* isrre = new ISRReaction(pin_number, mode, cb);
isrre->add();
return isrre;
ISRReaction* ReactESP::onInterrupt(const uint8_t pin_number, int mode,
const react_callback cb) {
ISRReaction* isrre = new ISRReaction(pin_number, mode, cb);
isrre->add();
return isrre;
}

TickReaction* ReactESP::onTick(const react_callback cb) {
TickReaction* tre = new TickReaction(cb);
tre->add();
return tre;
TickReaction* tre = new TickReaction(cb);
tre->add();
return tre;
}
Loading

0 comments on commit bec4654

Please sign in to comment.