Skip to content

Commit

Permalink
Reset jled object when effect changes (#26)
Browse files Browse the repository at this point in the history
* changing an effect starts animation over (addresses #25)
  • Loading branch information
jandelgado authored Jun 20, 2019
1 parent 8647eb6 commit 0de3a09
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 46 deletions.
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# JLed changelog

## [2019-06-20] 4.2.0

* changing an effect resets the Jled object so it starts over with the
new effect (see #25). Prior to this change, calling `Reset()` was
necessary.

## [2019-05-11] 4.1.2

* fix: ESP32 dynamic channel assignment fixed. Sequence demo now working
as expected.
as expected (see #22).

## [2019-05-07] 4.1.1

* fix: version format in library.properties (removed leading `v`)
* fix: version format in library.properties (removed leading `v`; see #21)

## [2019-03-10] v4.1.0

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.1.2
version=4.2.0
author=Jan Delgado <jdelgado[at]gmx.net>
maintainer=Jan Delgado <jdelgado[at]gmx.net>
sentence=An Arduino library to control LEDs
Expand Down
52 changes: 25 additions & 27 deletions src/jled_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ class FadeOffBrightnessEvaluator : public CloneableBrightnessEvaluator {
// But we do it with integers only.
class BreatheBrightnessEvaluator : public CloneableBrightnessEvaluator {
uint16_t period_;

public:
BreatheBrightnessEvaluator() = delete;
explicit BreatheBrightnessEvaluator(uint16_t period) : period_(period) {}
Expand Down Expand Up @@ -260,64 +261,55 @@ class TJLed {
bool IsLowActive() const { return GetFlag(FL_LOW_ACTIVE); }

// turn LED on
B& On() {
return Set(kFullBrightness);
}
B& On() { return Set(kFullBrightness); }

// turn LED off
B& Off() {
return Set(kZeroBrightness);
}
B& Off() { return Set(kZeroBrightness); }

// Sets LED to given brightness
B& Set(uint8_t brightness) {
// note: we use placement new and therefore not need to keep track of
// mem allocated
brightness_eval_ =
new (brightness_eval_buf_) ConstantBrightnessEvaluator(brightness);
return static_cast<B&>(*this);
return SetBrightnessEval(new (brightness_eval_buf_)
ConstantBrightnessEvaluator(brightness));
}

// Fade LED on
B& FadeOn(uint16_t duration) {
brightness_eval_ =
new (brightness_eval_buf_) FadeOnBrightnessEvaluator(duration);
return static_cast<B&>(*this);
return SetBrightnessEval(new (brightness_eval_buf_)
FadeOnBrightnessEvaluator(duration));
}

// Fade LED off - acutally is just inverted version of FadeOn()
B& FadeOff(uint16_t duration) {
brightness_eval_ =
new (brightness_eval_buf_) FadeOffBrightnessEvaluator(duration);
return static_cast<B&>(*this);
return SetBrightnessEval(new (brightness_eval_buf_)
FadeOffBrightnessEvaluator(duration));
}

// Set effect to Breathe, with the given period time in ms.
B& Breathe(uint16_t period) {
brightness_eval_ =
new (brightness_eval_buf_) BreatheBrightnessEvaluator(period);
return static_cast<B&>(*this);
return SetBrightnessEval(new (brightness_eval_buf_)
BreatheBrightnessEvaluator(period));
}

// Set effect to Blink, with the given on- and off- duration values.
B& Blink(uint16_t duration_on, uint16_t duration_off) {
brightness_eval_ = new (brightness_eval_buf_)
BlinkBrightnessEvaluator(duration_on, duration_off);
return static_cast<B&>(*this);
return SetBrightnessEval(
new (brightness_eval_buf_)
BlinkBrightnessEvaluator(duration_on, duration_off));
}

// Set effect to Candle light simulation
B& Candle(uint8_t speed = 6, uint8_t jitter = 15,
uint16_t period = 0xffff) {
brightness_eval_ = new (brightness_eval_buf_)
CandleBrightnessEvaluator(speed, jitter, period);
return static_cast<B&>(*this);
return SetBrightnessEval(
new (brightness_eval_buf_)
CandleBrightnessEvaluator(speed, jitter, period));
}

// Use a user provided brightness evaluator.
B& UserFunc(BrightnessEvaluator* ube) {
brightness_eval_ = ube;
return static_cast<B&>(*this);
B& UserFunc(BrightnessEvaluator* user_eval) {
return SetBrightnessEval(user_eval);
}

// set number of repetitions for effect.
Expand Down Expand Up @@ -414,6 +406,12 @@ class TJLed {
return true;
}

B& SetBrightnessEval(BrightnessEvaluator* be) {
brightness_eval_ = be;
// start over after the brightness evaluator changed
return Reset();
}

private:
static constexpr uint8_t FL_IN_DELAY_AFTER_PHASE = (1 << 0);
static constexpr uint8_t FL_STOPPED = (1 << 1);
Expand Down
53 changes: 37 additions & 16 deletions test/test_jled.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Copyright 2017 Jan Delgado [email protected]
#include <jled_base.h> // NOLINT
#include <map>
#include <utility>
#include "catch.hpp"
#include "hal_mock.h" // NOLINT

Expand Down Expand Up @@ -345,32 +346,52 @@ TEST_CASE("Update returns true while updating, else false", "[jled]") {

TEST_CASE("After Reset() the effect can be restarted", "[jled]") {
TestJLed jled(10);
uint32_t time = 0;
typedef std::pair<bool, uint8_t> p;

// 1 ms on, 2 ms off + 2 ms delay = 3ms off in total per iteration
jled.Blink(1, 1);
constexpr uint8_t expected[]{/* 1ms on */ 255,
/* 1ms off */ 0,
/* finally off */ 0};
uint32_t time = 0;
jled.Blink(1, 2);
constexpr p expected[]{p{true, 255}, p{true, 0}, p{false, 0}, p{false, 0}};

for (const auto val : expected) {
jled.Update();
REQUIRE(val == jled.Hal().Value());
jled.Hal().SetMillis(++time);
for (const auto x : expected) {
jled.Hal().SetMillis(time++);
REQUIRE(x.first == jled.Update());
REQUIRE(x.second == jled.Hal().Value());
}
REQUIRE(!jled.Update());

// after Reset() effect starts over
jled.Reset();
for (const auto val : expected) {
jled.Update();
REQUIRE(val == jled.Hal().Value());
jled.Hal().SetMillis(++time);
for (const auto x : expected) {
jled.Hal().SetMillis(time++);
REQUIRE(x.first == jled.Update());
REQUIRE(x.second == jled.Hal().Value());
}
REQUIRE(!jled.Update());
}

TEST_CASE("Changing the effect resets object and starts over", "[jled]") {
TestJLed jled(10);
uint32_t time = 0;
typedef std::pair<bool, uint8_t> p;

// 1 ms on, 2 ms off + 2 ms delay = 3ms off in total per iteration
jled.Blink(1, 2);
constexpr p expected_blink[]{p{true, 255}, p{true, 0}, p{false, 0},
p{false, 0}};

for (const auto x : expected_blink) {
jled.Hal().SetMillis(time++);
REQUIRE(x.first == jled.Update());
REQUIRE(x.second == jled.Hal().Value());
}

// expect to start over after changing effect.
jled.FadeOff(1000);
REQUIRE(jled.Update());
REQUIRE(0 < jled.Hal().Value());
}

TEST_CASE("random generator delivers PRN's as expected", "[jled]") {
jled::rand_seed(0);
REQUIRE(0x59 == jled::rand8());
REQUIRE(0x159>>1 == jled::rand8());
REQUIRE(0x159 >> 1 == jled::rand8());
}

0 comments on commit 0de3a09

Please sign in to comment.