diff --git a/tdd_for_embedded_c/chapter04/src/LedDriver.c b/tdd_for_embedded_c/chapter04/src/LedDriver.c index f3436b9..eb8622e 100644 --- a/tdd_for_embedded_c/chapter04/src/LedDriver.c +++ b/tdd_for_embedded_c/chapter04/src/LedDriver.c @@ -1,8 +1,12 @@ #include "LedDriver.h" +#include "../util/RuntimeError.h" -static uint16_t *ledsAddress; +enum {ALL_LEDS_ON = ~0x0000, ALL_LEDS_OFF = ~ALL_LEDS_ON}; + +static uint16_t *ledsAddress = NULL; // LEDs memory register location +static uint16_t ledsImage; // internal variable to store LEDs state static uint16_t convertLedNumberToBit(int ledNumber) { @@ -10,9 +14,18 @@ static uint16_t convertLedNumberToBit(int ledNumber) { } +static void updateHardware(void) { + if(ledsAddress == NULL) { + return; + } + *ledsAddress = ledsImage; +} + + void LedDriver_Create(uint16_t *address) { ledsAddress = address; - *ledsAddress = 0x0000; + ledsImage = ALL_LEDS_OFF; + updateHardware(); } @@ -21,10 +34,28 @@ void LedDriver_Destroy(uint16_t *address) { void LedDriver_TurnOn(int ledNumber) { - *ledsAddress |= convertLedNumberToBit(ledNumber); + if(ledNumber < 0 || ledNumber > 16) { + RUNTIME_ERROR("LED Driver: out-of-bounds LED", -1); + return; + } + + ledsImage |= convertLedNumberToBit(ledNumber); + updateHardware(); +} + + +void LedDriver_TurnAllOn(void) { + ledsImage = ALL_LEDS_ON; + updateHardware(); } void LedDriver_TurnOff(int ledNumber) { - *ledsAddress = 0x0000; + if(ledNumber < 0 || ledNumber > 16) { + RUNTIME_ERROR("LED Driver: out-of-bounds LED", -1); + return; + } + + ledsImage &= ~(convertLedNumberToBit(ledNumber)); + updateHardware(); } diff --git a/tdd_for_embedded_c/chapter04/src/LedDriver.h b/tdd_for_embedded_c/chapter04/src/LedDriver.h index 662d639..f09c88f 100644 --- a/tdd_for_embedded_c/chapter04/src/LedDriver.h +++ b/tdd_for_embedded_c/chapter04/src/LedDriver.h @@ -1,8 +1,10 @@ #include +#include void LedDriver_Create(uint16_t *address); void LedDriver_Destroy(uint16_t *address); void LedDriver_TurnOn(int ledNumber); -void LedDriver_TurnOff(int ledNumber); \ No newline at end of file +void LedDriver_TurnOff(int ledNumber); +void LedDriver_TurnAllOn(void); \ No newline at end of file diff --git a/tdd_for_embedded_c/chapter04/test/LedDriverTest.c b/tdd_for_embedded_c/chapter04/test/LedDriverTest.c index 987d67e..7242bb0 100644 --- a/tdd_for_embedded_c/chapter04/test/LedDriverTest.c +++ b/tdd_for_embedded_c/chapter04/test/LedDriverTest.c @@ -1,5 +1,7 @@ #include "unity_fixture.h" #include "../src/LedDriver.h" +#include "../mocks/RuntimeErrorStub.h" + TEST_GROUP(LedDriver); @@ -54,3 +56,79 @@ TEST(LedDriver, TurnOnMultipleLeds) { TEST_ASSERT_EQUAL_HEX16(0x0180, virtualLeds); } + + +TEST(LedDriver, TurnAllOn) { + + LedDriver_TurnAllOn(); + + TEST_ASSERT_EQUAL_HEX16(0xFFFF, virtualLeds); + +} + + +TEST(LedDriver, TurnOffAnyLed) { + + LedDriver_TurnAllOn(); + LedDriver_TurnOff(8); + + TEST_ASSERT_EQUAL_HEX16(0xFF7F, virtualLeds); + +} + + +TEST(LedDriver, LedMemoryIsNotReadable) { + + virtualLeds = 0xFFFF; + LedDriver_TurnOn(8); + + TEST_ASSERT_EQUAL_HEX16(0x0080, virtualLeds); + +} + + +TEST(LedDriver, UpperAndLowerBounds) { + + LedDriver_TurnOn(1); + LedDriver_TurnOn(16); + + TEST_ASSERT_EQUAL_HEX16(0x8001, virtualLeds); + +} + + +TEST(LedDriver, OutOfBoundsTurnOnDoesNotHarm) { + + LedDriver_TurnOn(-1); + LedDriver_TurnOn(0); + LedDriver_TurnOn(17); + LedDriver_TurnOn(3141); + + TEST_ASSERT_EQUAL_HEX16(0x0000, virtualLeds); + +} + +TEST(LedDriver, OutOfBoundsTurnOffDoesNotHarm) { + + LedDriver_TurnAllOn(); + LedDriver_TurnOff(-1); + LedDriver_TurnOff(0); + LedDriver_TurnOff(17); + LedDriver_TurnOff(3141); + + TEST_ASSERT_EQUAL_HEX16(0xFFFF, virtualLeds); + +} + + +TEST(LedDriver, OutOfBoundsProducesRuntimeError) { + LedDriver_TurnOn(-1); + + TEST_ASSERT_EQUAL_STRING("LED Driver: out-of-bounds LED", RuntimeErrorStub_GetLastError()); + TEST_ASSERT_EQUAL(-1, RuntimeErrorStub_GetLastParameter()); +} + + +IGNORE_TEST(LedDriver, OutOfBoundsToDo) { + /* TODO: what should we do during runtime? */ +} diff --git a/tdd_for_embedded_c/chapter04/test/LedDriverTestRunner.c b/tdd_for_embedded_c/chapter04/test/LedDriverTestRunner.c index 89c9674..b558718 100644 --- a/tdd_for_embedded_c/chapter04/test/LedDriverTestRunner.c +++ b/tdd_for_embedded_c/chapter04/test/LedDriverTestRunner.c @@ -7,5 +7,13 @@ TEST_GROUP_RUNNER(LedDriver) { RUN_TEST_CASE(LedDriver, TurnOnLedOne); RUN_TEST_CASE(LedDriver, TurnOffLedOne); RUN_TEST_CASE(LedDriver, TurnOnMultipleLeds); + RUN_TEST_CASE(LedDriver, TurnAllOn); + RUN_TEST_CASE(LedDriver, TurnOffAnyLed); + RUN_TEST_CASE(LedDriver, LedMemoryIsNotReadable); + RUN_TEST_CASE(LedDriver, UpperAndLowerBounds); + RUN_TEST_CASE(LedDriver, OutOfBoundsTurnOnDoesNotHarm); + RUN_TEST_CASE(LedDriver, OutOfBoundsTurnOffDoesNotHarm); + RUN_TEST_CASE(LedDriver, OutOfBoundsProducesRuntimeError); + RUN_TEST_CASE(LedDriver, OutOfBoundsToDo); }