SensESP 3.1.1
Universal Signal K sensor toolkit ESP32
Loading...
Searching...
No Matches
led_blinker.h
Go to the documentation of this file.
1#ifndef SENSESP_SYSTEM_LED_BLINKER_H_
2#define SENSESP_SYSTEM_LED_BLINKER_H_
3
4#include <Arduino.h>
5#include <ReactESP.h>
6
7#include "crgb.h"
9
10namespace sensesp {
11
12#define max(a, b) ((a) > (b) ? (a) : (b))
13#define PATTERN_END (-1)
14
19 public:
20 BaseBlinker(int pin) : pin_{pin} {
21 pinMode(pin, OUTPUT);
22 event_loop()->onDelay(1, [this]() { this->tick(); });
23 }
24
27 void set_state(bool state) {
28 this->state_ = state;
29 digitalWrite(pin_, state);
31 }
32
36 void flip_state() { this->set_state(!this->state_); }
37
41 void blip(int duration = 20) {
42 // indicator for a blip being in progress
43 static bool blipping = false;
44
45 // only allow one blip at a time
46 if (blipping) {
47 return;
48 }
49 blipping = true;
50
51 bool const orig_state = this->state_;
52 this->set_state(false);
53 int const current_counter = this->update_counter_;
54 event_loop()->onDelay(
55 duration, [this, duration, orig_state, current_counter]() {
56 // only update if no-one has touched the LED in the meanwhile
57 if (this->update_counter_ == current_counter) {
58 this->set_state(true);
59 int const new_counter = this->update_counter_;
60 event_loop()->onDelay(duration, [this, orig_state, new_counter]() {
61 // again, only update if no-one has touched the LED
62 if (this->update_counter_ == new_counter) {
63 this->set_state(orig_state);
64 }
65 blipping = false;
66 });
67 } else {
68 blipping = false;
69 }
70 });
71 }
72
76 void set_enabled(bool state) {
77 bool const was_enabled = this->enabled_;
78 this->enabled_ = state;
79 if (this->enabled_) {
80 this->tick();
81 } else {
82 this->set_state(false);
83 if (was_enabled) {
84 event_->remove(event_loop());
85 }
86 }
87 }
88
92 virtual void tick() = 0;
93
94 protected:
95 int pin_;
96 bool enabled_ = true;
97 bool state_ = false;
99 reactesp::Event* event_ = NULL;
100};
101
102class LEDPattern;
103using FragmentCallback = std::function<void(uint32_t, CRGB&)>;
104
106 public:
107 LEDPatternFragment(uint32_t duration_ms, FragmentCallback callback)
108 : duration_ms_(duration_ms), callback_(callback) {}
109
110 // Copy constructor
113
114 // Assignment operator
117 callback_ = other.callback_;
118 return *this;
119 }
120
121 uint32_t duration_ms_;
123};
124
126 public:
128 LEDPattern(const std::vector<LEDPatternFragment>& fragments)
129 : fragments_(fragments) {}
130 LEDPattern(const std::initializer_list<LEDPatternFragment>& fragments)
131 : fragments_(fragments),
134
135 // Assignment operator
137 fragments_ = other.fragments_;
138 return *this;
139 }
140
141 bool apply(CRGB& crgb, bool oneshot = false) {
142 // Initialize fragment begin time if it's the first time
143 if (fragment_begin_ms_ == 0) {
144 fragment_begin_ms_ = millis();
145 }
146 unsigned long current_fragment_duration_ms =
147 fragments_[current_fragment_idx_].duration_ms_;
148 while (millis() - fragment_begin_ms_ >= current_fragment_duration_ms) {
150 if (current_fragment_idx_ >= fragments_.size()) {
152 if (oneshot) {
153 return false;
154 }
155 }
156 fragment_begin_ms_ += current_fragment_duration_ms;
157 current_fragment_duration_ms =
158 fragments_[current_fragment_idx_].duration_ms_;
159 }
160 // Call the callback function for the current fragment, passing the elapsed
161 // time and a reference to the CRGB object
163 crgb);
164 return true;
165 }
166
167 protected:
168 std::vector<LEDPatternFragment> fragments_;
170 unsigned long fragment_begin_ms_ = 0;
171};
172
190 public:
191 LEDBlinker(CRGB& crgb, LEDPattern pattern, std::function<void()> show_func)
192 : crgb_(crgb), pattern_(pattern), show_func_(show_func) {}
193 void tick() {
194 // Always start with the last color
196 pattern_.apply(crgb_);
198 std::list<LEDPattern>::iterator it = modifiers_.begin();
199 while (it != modifiers_.end()) {
200 LEDPattern* mod = &*it;
201 bool result = mod->apply(crgb_, true);
202 if (!result) {
203 it = modifiers_.erase(it);
204 } else {
205 it++;
206 }
207 }
208 show_func_();
209 }
210
211 void set_pattern(const LEDPattern& pattern) { pattern_ = pattern; }
212
213 void add_modifier(const LEDPattern& modifier) {
214 modifiers_.push_back(modifier);
215 }
216
217 protected:
218 CRGB& crgb_;
219 CRGB last_color_ = CRGB::Black; // Previous set color before modifiers
221 std::list<LEDPattern> modifiers_ = {};
222
223 std::function<void()> show_func_;
224};
225
226LEDPatternFragment frag_solid_color(uint32_t duration_ms, const CRGB& color);
227LEDPatternFragment frag_linear_fade(uint32_t duration_ms,
228 uint32_t fade_duration_ms,
229 const CRGB& target_color);
230LEDPatternFragment frag_linear_invert(uint32_t duration_ms,
231 bool reverse = false);
232LEDPatternFragment frag_blend(uint32_t duration_ms, const CRGB& target_color,
233 bool reverse = false);
234LEDPatternFragment frag_nop(uint32_t duration_ms);
235} // namespace sensesp
236
237#endif
void set_state(bool state)
Definition led_blinker.h:27
void set_enabled(bool state)
Definition led_blinker.h:76
void blip(int duration=20)
Definition led_blinker.h:41
virtual void tick()=0
reactesp::Event * event_
Definition led_blinker.h:99
std::function< void()> show_func_
void add_modifier(const LEDPattern &modifier)
void set_pattern(const LEDPattern &pattern)
std::list< LEDPattern > modifiers_
LEDBlinker(CRGB &crgb, LEDPattern pattern, std::function< void()> show_func)
LEDPatternFragment(const LEDPatternFragment &other)
LEDPatternFragment & operator=(const LEDPatternFragment &other)
FragmentCallback callback_
LEDPatternFragment(uint32_t duration_ms, FragmentCallback callback)
LEDPattern(const std::vector< LEDPatternFragment > &fragments)
unsigned long fragment_begin_ms_
bool apply(CRGB &crgb, bool oneshot=false)
uint32_t current_fragment_idx_
std::vector< LEDPatternFragment > fragments_
LEDPattern(const std::initializer_list< LEDPatternFragment > &fragments)
LEDPattern & operator=(const LEDPattern &other)
std::shared_ptr< reactesp::EventLoop > event_loop()
Definition sensesp.cpp:9
LEDPatternFragment frag_linear_fade(uint32_t duration_ms, uint32_t fade_duration_ms, const CRGB &target_color)
LEDPatternFragment frag_nop(uint32_t duration_ms)
LEDPatternFragment frag_blend(uint32_t duration_ms, const CRGB &target_color, bool reverse)
std::function< void(uint32_t, CRGB &)> FragmentCallback
LEDPatternFragment frag_linear_invert(uint32_t duration_ms, bool reverse)
LEDPatternFragment frag_solid_color(uint32_t duration_ms, const CRGB &color)