Skip to content

Commit

Permalink
Repeat() and Forever() for sequences
Browse files Browse the repository at this point in the history
  • Loading branch information
jandelgado committed Jan 23, 2021
1 parent db5d48f commit 144f0c8
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 7 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# JLed changelog

## [tbd] 4.6.0

* new: JLedSequence can be configured to play the sequence multiple times
using the `Repeat()` and `Forever()` methods

## [tbd] 4.5.3

* drop travis-ci, use github actions
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ an effect. The default value is 0 ms.
##### Repetitions
Use the `Repeat()` method to specify the number of repetition. The default
Use the `Repeat()` method to specify the number of repetitions. The default
value is 1 repetition. The `Forever()` methods sets to repeat the effect
forever. Each repetition includes a full period of the effect and the time
specified by `DelayAfter()` method.
Expand Down Expand Up @@ -382,11 +382,11 @@ effect when the previous finished. The constructor takes the mode (`PARALLEL`,
```c++
JLed leds[] = {
JLed(4).Blink(750, 250).Forever(),
JLed(3).Breathe(2000).Forever()
JLed(4).Blink(750, 250).Repeat(10),
JLed(3).Breathe(2000).Repeat(5);
};
JLedSequence sequence(JLedSequence::eMode::PARALLEL, leds);
auto sequence = JLedSequence(JLedSequence::eMode::PARALLEL, leds).Repeat(2);
void setup() {
}
Expand All @@ -405,6 +405,9 @@ The `JLedSequence` provides the following methods:
* `Update()` - updates the active `JLed` objects controlled by the sequence.
Like the `JLed::Update()` method, it returns `true` if an effect is running,
else `false`.
* Use the `Repeat(n)` method to specify the number of repetitions. The default
value is 1 repetition. The `Forever()` methods sets to repeat the sequence
forever.
* `Stop()` - turns off all `JLed` objects controlled by the sequence and
stops the sequence. Further calls to `Update()` will have no effect.
* `Reset()` - Resets all `JLed` objects controlled by the sequence and
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=JLed
version=4.5.2
version=4.6.0
author=Jan Delgado <jdelgado[at]gmx.net>
maintainer=Jan Delgado <jdelgado[at]gmx.net>
sentence=An Arduino library to control LEDs
Expand Down
35 changes: 33 additions & 2 deletions src/jled_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,15 +486,32 @@ class TJLedSequence {
: mode_{mode}, leds_{leds}, cur_{0}, n_{n} {}

bool Update() {
return mode_ == eMode::PARALLEL ? UpdateParallel()
: UpdateSequentially();
if (!is_running_) {
return false;
}

auto led_running = (mode_ == eMode::PARALLEL) ? UpdateParallel()
: UpdateSequentially();
if (led_running) {
return true;
}

for (auto i = 0u; i < n_; i++) {
leds_[i].Reset();
}

is_running_ = ++iteration_ < num_repetitions_ &&
num_repetitions_ != kRepeatForever;
return is_running_;
}

void Reset() {
for (auto i = 0u; i < n_; i++) {
leds_[i].Reset();
}
cur_ = 0;
iteration_ = 0;
is_running_ = true;
}

void Stop() {
Expand All @@ -503,11 +520,25 @@ class TJLedSequence {
}
}

// set number of repetitions for the sequence
TJLedSequence<T> Repeat(uint16_t num_repetitions) {
num_repetitions_ = num_repetitions;
return *this;
}

// repeat Forever
TJLedSequence<T> Forever() { return Repeat(kRepeatForever); }
bool IsForever() const { return num_repetitions_ == kRepeatForever; }

private:
const eMode mode_;
T* leds_;
size_t cur_;
const size_t n_;
static constexpr uint16_t kRepeatForever = 65535;
uint16_t num_repetitions_ = 1;
uint16_t iteration_ = 0;
bool is_running_ = true;
};

}; // namespace jled
Expand Down
30 changes: 30 additions & 0 deletions test/test_jled_sequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,36 @@ TEST_CASE("stop on sequence stops alle JLeds and turns them off",
REQUIRE(!leds[1].IsRunning());
}

TEST_CASE("reapeat plays the sequence N times", "[jled_sequence]") {
// 1 ms on, 1 ms off = 2ms off in total per iteration
TestJLed leds[] = {TestJLed(HalMock(1)).Blink(1, 1)};
auto seq = TestJLedSequence(TestJLedSequence::eMode::PARALLEL, leds)
.Repeat(2);

constexpr uint8_t expected[]{255, 0, 255, 0, 0};
uint32_t time = 0;

for (const auto val : expected) {
seq.Update();
REQUIRE(val == leds[0].Hal().Value());
leds[0].Hal().SetMillis(++time);
}
REQUIRE(!seq.Update());
}

TEST_CASE("Forever flag is initially set to false", "[jled_sequence]") {
TestJLed leds[] = {TestJLed(HalMock(1)).Blink(1, 1)};
auto seq = TestJLedSequence(TestJLedSequence::eMode::PARALLEL, leds);
REQUIRE_FALSE(seq.IsForever());
}

TEST_CASE("Forever flag is set by call to Forever()", "[jled_sequence]") {
TestJLed leds[] = {TestJLed(HalMock(1)).Blink(1, 1)};
auto seq = TestJLedSequence(TestJLedSequence::eMode::PARALLEL, leds)
.Forever();
REQUIRE(seq.IsForever());
}

TEST_CASE("reset on sequence resets all JLeds", "[jled_sequence]") {
// 1 ms on, 2 ms off + 2 ms delay = 3ms off in total per iteration
TestJLed leds[] = {TestJLed(HalMock(1)).Blink(1, 1),
Expand Down

0 comments on commit 144f0c8

Please sign in to comment.