From bd335ec30d99c276f386a3e60c88210b54c22eb4 Mon Sep 17 00:00:00 2001 From: "D.R.racer" Date: Wed, 26 May 2021 11:39:24 +0200 Subject: [PATCH] Unit test for LEDs interface + fixes --- src/modules/leds.cpp | 8 +- src/modules/leds.h | 26 ++++-- tests/unit/modules/leds/CMakeLists.txt | 2 +- tests/unit/modules/leds/stub_shr16.cpp | 28 +++++++ tests/unit/modules/leds/test_leds.cpp | 107 ++++++++++++++++++++++++- 5 files changed, 161 insertions(+), 10 deletions(-) create mode 100644 tests/unit/modules/leds/stub_shr16.cpp diff --git a/src/modules/leds.cpp b/src/modules/leds.cpp index 631b64f..23fba84 100644 --- a/src/modules/leds.cpp +++ b/src/modules/leds.cpp @@ -1,5 +1,5 @@ #include "leds.h" -#include "hal/shr16.h" +#include "../hal/shr16.h" namespace modules { namespace leds { @@ -34,16 +34,18 @@ bool LED::Step(bool oddPeriod) { default: // do nothing break; } + return state.on; } -void LEDs::Step(uint8_t delta_ms) { +void LEDs::Step(uint16_t delta_ms) { ms += delta_ms; bool oddPeriod = ((ms / 1000U) & 0x01U) != 0; uint16_t result = 0; - for (uint8_t i = 0; i < ledPairs * 2; ++i) { + for (int8_t i = ledPairs * 2 - 1; i >= 0; --i) { result <<= 1; result |= leds[i].Step(oddPeriod); } + hal::shr16::shr16.SetLED(result); } diff --git a/src/modules/leds.h b/src/modules/leds.h index 801139a..cee5062 100644 --- a/src/modules/leds.h +++ b/src/modules/leds.h @@ -22,6 +22,11 @@ enum Mode { blink1 ///< start blinking at odd periods }; +enum Color { + green = 0, + red = 1 +}; + /// a single LED class LED { public: @@ -51,12 +56,12 @@ public: : ms(0) {}; /// step LED automaton - void Step(uint8_t delta_ms); + void Step(uint16_t delta_ms); inline constexpr uint8_t LedPairsCount() const { return ledPairs; } - inline void SetMode(uint8_t slot, bool red, Mode mode) { - SetMode(slot * 2 + red, mode); + inline void SetMode(uint8_t slot, Color color, Mode mode) { + SetMode(slot * 2 + color, mode); } inline void SetMode(uint8_t index, Mode mode) { leds[index].SetMode(mode); @@ -65,12 +70,23 @@ public: inline bool LedOn(uint8_t index) const { return leds[index].On(); } - inline bool LedOn(uint8_t slot, bool red) const { - return leds[slot * 2 + red].On(); + inline bool LedOn(uint8_t slot, Color color) const { + return leds[slot * 2 + color].On(); } private: constexpr static const uint8_t ledPairs = 5; + /// pairs of LEDs: + /// [0] - green LED slot 0 + /// [1] - red LED slot 0 + /// [2] - green LED slot 1 + /// [3] - red LED slot 1 + /// [4] - green LED slot 2 + /// [5] - red LED slot 2 + /// [6] - green LED slot 3 + /// [7] - red LED slot 3 + /// [8] - green LED slot 4 + /// [9] - red LED slot 4 LED leds[ledPairs * 2]; uint16_t ms; }; diff --git a/tests/unit/modules/leds/CMakeLists.txt b/tests/unit/modules/leds/CMakeLists.txt index 9f39584..7c8a23e 100644 --- a/tests/unit/modules/leds/CMakeLists.txt +++ b/tests/unit/modules/leds/CMakeLists.txt @@ -1,5 +1,5 @@ # define the test executable -add_executable(leds_tests ../../../../src/modules/leds.cpp test_leds.cpp) +add_executable(leds_tests ../../../../src/modules/leds.cpp stub_shr16.cpp test_leds.cpp) # define required search paths target_include_directories( diff --git a/tests/unit/modules/leds/stub_shr16.cpp b/tests/unit/modules/leds/stub_shr16.cpp new file mode 100644 index 0000000..6433ad4 --- /dev/null +++ b/tests/unit/modules/leds/stub_shr16.cpp @@ -0,0 +1,28 @@ +#include "shr16.h" + +namespace hal { +namespace shr16 { + +SHR16 shr16; + +uint16_t shr16_v_copy; + +void SHR16::Init() { + shr16_v_copy = 0; +} + +void SHR16::SetLED(uint16_t led) { + shr16_v_copy = ((led & 0x00ff) << 8) | ((led & 0x0300) >> 2); +} +void SHR16::SetTMCEnabled(uint8_t ena) { + // do nothing right now +} +void SHR16::SetTMCDir(uint8_t dir) { + // do nothing right now +} +void SHR16::Write(uint16_t v) { + // do nothing right now +} + +} // namespace shr16 +} // namespace hal diff --git a/tests/unit/modules/leds/test_leds.cpp b/tests/unit/modules/leds/test_leds.cpp index 68a9cff..0a6ca3b 100644 --- a/tests/unit/modules/leds/test_leds.cpp +++ b/tests/unit/modules/leds/test_leds.cpp @@ -1,8 +1,113 @@ #include "catch2/catch.hpp" #include "leds.h" +#include "shr16.h" using Catch::Matchers::Equals; -TEST_CASE("leds::basic", "[leds]") { +namespace hal { +namespace shr16 { +extern uint16_t shr16_v_copy; +} // namespace shr16 +} // namespace hal + +/// LEDS - hardcoded +#define SHR16_LEDG0 0x0100 +#define SHR16_LEDR0 0x0200 +#define SHR16_LEDG1 0x0400 +#define SHR16_LEDR1 0x0800 +#define SHR16_LEDG2 0x1000 +#define SHR16_LEDR2 0x2000 +#define SHR16_LEDG3 0x4000 +#define SHR16_LEDR3 0x8000 +#define SHR16_LEDG4 0x0040 +#define SHR16_LEDR4 0x0080 + +TEST_CASE("leds::single", "[leds]") { using namespace modules::leds; + using namespace hal::shr16; + + LEDs leds; + + uint8_t index; + Color color; + uint16_t shr16_register; + std::tie(index, color, shr16_register) = GENERATE( + std::make_tuple(0, green, SHR16_LEDG0), + std::make_tuple(0, red, SHR16_LEDR0), + std::make_tuple(1, green, SHR16_LEDG1), + std::make_tuple(1, red, SHR16_LEDR1), + std::make_tuple(2, green, SHR16_LEDG2), + std::make_tuple(2, red, SHR16_LEDR2), + std::make_tuple(3, green, SHR16_LEDG3), + std::make_tuple(3, red, SHR16_LEDR3), + std::make_tuple(4, green, SHR16_LEDG4), + std::make_tuple(4, red, SHR16_LEDR4)); + + shr16.Init(); // clears the register for the test + + // turn LED on + leds.SetMode(index, color, on); + leds.Step(0); + CHECK(leds.LedOn(index, color) == true); + CHECK(shr16_v_copy == shr16_register); + + // turn LED off + leds.SetMode(index, color, off); + leds.Step(0); + CHECK(leds.LedOn(index, color) == false); + CHECK(shr16_v_copy == 0); +} + +void TestBlink(uint8_t index, modules::leds::Color color, uint16_t shr16_register, bool shouldBeOn, modules::leds::Mode blinkMode) { + using namespace modules::leds; + using namespace hal::shr16; + LEDs leds; + + leds.SetMode(index, color, blinkMode); + leds.Step(1); + + REQUIRE(leds.LedOn(index, color) == shouldBeOn); + CHECK(shr16_v_copy == (shouldBeOn ? shr16_register : 0)); + + // test 4 seconds of blinking + for (uint8_t s = 1; s < 4; ++s) { + // one second elapsed ;) + leds.Step(1000); + shouldBeOn = !shouldBeOn; + CHECK(leds.LedOn(index, color) == shouldBeOn); + CHECK(shr16_v_copy == (shouldBeOn ? shr16_register : 0)); + } + + // turn LED off + leds.SetMode(index, color, off); + leds.Step(0); + CHECK(leds.LedOn(index, color) == false); + CHECK(shr16_v_copy == 0); +} + +TEST_CASE("leds::blink0-single", "[leds]") { + using namespace modules::leds; + using namespace hal::shr16; + + uint8_t index; + Color color; + uint16_t shr16_register; + std::tie(index, color, shr16_register) = GENERATE( + std::make_tuple(0, green, SHR16_LEDG0), + std::make_tuple(0, red, SHR16_LEDR0), + std::make_tuple(1, green, SHR16_LEDG1), + std::make_tuple(1, red, SHR16_LEDR1), + std::make_tuple(2, green, SHR16_LEDG2), + std::make_tuple(2, red, SHR16_LEDR2), + std::make_tuple(3, green, SHR16_LEDG3), + std::make_tuple(3, red, SHR16_LEDR3), + std::make_tuple(4, green, SHR16_LEDG4), + std::make_tuple(4, red, SHR16_LEDR4)); + + shr16.Init(); // clears the register for the test + + // set LED into blink0 mode - on in even periods of 1s intervals, starts as OFF + TestBlink(index, color, shr16_register, false, blink0); + + TestBlink(index, color, shr16_register, true, blink1); }