roo_blink
API Documentation for roo_blink
Loading...
Searching...
No Matches
blinker.cpp
Go to the documentation of this file.
2
3#include "roo_blink.h"
5#include "roo_logging.h"
6#include "roo_threads.h"
7
8using namespace roo_time;
9
10namespace roo_blink {
11
13
14Blinker::Blinker(Led& led, roo_scheduler::Scheduler& scheduler)
15 : led_(led),
16 stepper_(scheduler, [this]() { step(); }),
17 sequence_(),
18 pos_(0) {}
19
21 updateSequence(std::move(sequence), -1, 0);
22}
23
24void Blinker::repeat(BlinkSequence sequence, int repetitions,
25 uint16_t terminal_level) {
26 updateSequence(std::move(sequence), repetitions - 1, terminal_level);
27}
28
29void Blinker::execute(BlinkSequence sequence, uint16_t terminal_level) {
30 updateSequence(std::move(sequence), 0, terminal_level);
31}
32
33void Blinker::set(uint16_t intensity) { updateSequence({}, 0, intensity); }
34
35void Blinker::turnOn() { set(65535); }
36
37void Blinker::turnOff() { set(0); }
38
39void Blinker::updateSequence(BlinkSequence sequence, int repetitions,
40 uint16_t terminal_level) {
41 roo::lock_guard<roo::mutex> lock(mutex_);
42 sequence_ = std::move(sequence.sequence_);
43 terminal_level_ = terminal_level;
44 current_level_ = terminal_level_;
45 repetitions_ = repetitions;
46 fade_in_progress_ = false;
47 pos_ = 0;
48 if (!sequence_.empty() && !stepper_.is_scheduled()) {
49 stepper_.scheduleNow(roo_scheduler::PRIORITY_ELEVATED);
50 } else {
51 current_level_ = terminal_level_;
52 led_.setLevel(current_level_);
53 }
54}
55
56void Blinker::step() {
57 roo::lock_guard<roo::mutex> lock(mutex_);
58 if (fade_in_progress_) {
59 roo_time::Uptime now = roo_time::Uptime::Now();
60 if (now >= fade_end_time_) {
61 fade_in_progress_ = false;
62 current_level_ = fade_target_level_;
63 led_.setLevel(current_level_);
64 } else {
65 float progress = (now - fade_start_time_).inMillisFloat() /
66 (fade_end_time_ - fade_start_time_).inMillisFloat();
67 current_level_ = fade_start_level_ +
68 (fade_target_level_ - fade_start_level_) * progress;
69 led_.setLevel(current_level_);
70 stepper_.scheduleAfter(roo_time::Millis(20),
71 roo_scheduler::PRIORITY_ELEVATED);
72 return;
73 }
74 }
75 uint16_t next_delay = 0;
76 do {
77 if (pos_ >= sequence_.size()) {
78 sequence_.clear();
79 current_level_ = terminal_level_;
80 led_.setLevel(current_level_);
81 return;
82 }
83 const Step& s = sequence_[pos_];
84 switch (s.type_) {
85 case Step::kSet: {
86 current_level_ = s.target_level_;
87 led_.setLevel(current_level_);
88 break;
89 }
90 case Step::kHold: {
91 next_delay = s.duration_millis_;
92 break;
93 }
94 case Step::kFade:
95 default: {
96 if (led_.fade(s.target_level_, roo_time::Millis(s.duration_millis_))) {
97 next_delay = s.duration_millis_;
98 } else {
99 fade_in_progress_ = true;
100 fade_start_level_ = current_level_;
101 fade_target_level_ = s.target_level_;
102 fade_start_time_ = roo_time::Uptime::Now();
103 fade_end_time_ =
104 fade_start_time_ + roo_time::Millis(s.duration_millis_);
105 next_delay = 20;
106 }
107 break;
108 }
109 }
110 ++pos_;
111 if (pos_ == sequence_.size() && repetitions_ != 0) {
112 if (repetitions_ > 0) --repetitions_;
113 pos_ = 0;
114 }
115 } while (next_delay == 0);
116 stepper_.scheduleAfter(roo_time::Millis(next_delay),
117 roo_scheduler::PRIORITY_ELEVATED);
118}
119
120BlinkSequence Blink(roo_time::Duration period, int duty_percent,
121 int rampup_percent_on, int rampup_percent_off) {
122 CHECK_GE(duty_percent, 0);
123 CHECK_LE(duty_percent, 100);
124 CHECK_GE(rampup_percent_on, 0);
125 CHECK_LE(rampup_percent_on, 100);
126 CHECK_GE(rampup_percent_off, 0);
127 CHECK_LE(rampup_percent_off, 100);
128 int millis = period.inMillis();
129 int millis_1st = duty_percent * millis / 100;
130 int millis_1st_rampup = rampup_percent_on * millis_1st / 100;
131 int millis_2nd = millis - millis_1st;
132 int millis_2nd_rampup = rampup_percent_off * millis_2nd / 100;
133
134 BlinkSequence result;
135
136 if (millis_1st_rampup > 0) {
137 result.add(FadeOn(Millis(millis_1st_rampup)));
138 } else {
139 result.add(TurnOn());
140 }
141 if (millis_1st_rampup < millis_1st) {
142 result.add(Hold(Millis(millis_1st - millis_1st_rampup)));
143 }
144
145 if (millis_2nd_rampup > 0) {
146 result.add(FadeOff(Millis(millis_2nd_rampup)));
147 } else {
148 result.add(TurnOff());
149 }
150 if (millis_2nd_rampup < millis_2nd) {
151 result.add(Hold(Millis(millis_2nd - millis_2nd_rampup)));
152 }
153
154 return result;
155}
156
157} // namespace roo_blink