From 2d6db40d74f6860cc8d0cc097d99d0e3d73507bb Mon Sep 17 00:00:00 2001 From: tmeissner Date: Tue, 2 Jun 2015 00:02:44 +0200 Subject: [PATCH] added some helper functions for out-of-bounds hecking & set/clear bits ledsImage; added tests for new functionality --- tdd_for_embedded_c/chapter04/src/LedDriver.c | 48 +++++++++++++++++-- tdd_for_embedded_c/chapter04/src/LedDriver.h | 6 ++- .../chapter04/test/LedDriverTest.c | 47 ++++++++++++++++++ .../chapter04/test/LedDriverTestRunner.c | 5 ++ 4 files changed, 101 insertions(+), 5 deletions(-) diff --git a/tdd_for_embedded_c/chapter04/src/LedDriver.c b/tdd_for_embedded_c/chapter04/src/LedDriver.c index eb8622e..855b890 100644 --- a/tdd_for_embedded_c/chapter04/src/LedDriver.c +++ b/tdd_for_embedded_c/chapter04/src/LedDriver.c @@ -4,6 +4,7 @@ enum {ALL_LEDS_ON = ~0x0000, ALL_LEDS_OFF = ~ALL_LEDS_ON}; +enum {FIRST_LED = 1, LAST_LED = 16}; static uint16_t *ledsAddress = NULL; // LEDs memory register location static uint16_t ledsImage; // internal variable to store LEDs state @@ -14,8 +15,24 @@ static uint16_t convertLedNumberToBit(int ledNumber) { } +static bool IsLedOutOfBound(int ledNumber) { + return (ledNumber < 1) || (ledNumber > 16); +} + + +static void SetLedImageBit(int ledNumber) { + ledsImage |= convertLedNumberToBit(ledNumber); +} + + +static void ClearLedImageBit(int ledNumber) { + ledsImage &= ~(convertLedNumberToBit(ledNumber)); +} + + static void updateHardware(void) { if(ledsAddress == NULL) { + RUNTIME_ERROR("LED Driver: NULL pointer access", -1); return; } *ledsAddress = ledsImage; @@ -23,6 +40,10 @@ static void updateHardware(void) { void LedDriver_Create(uint16_t *address) { + if(address == NULL) { + RUNTIME_ERROR("LED Driver: NULL pointer access", -1); + return; + } ledsAddress = address; ledsImage = ALL_LEDS_OFF; updateHardware(); @@ -34,12 +55,12 @@ void LedDriver_Destroy(uint16_t *address) { void LedDriver_TurnOn(int ledNumber) { - if(ledNumber < 0 || ledNumber > 16) { + if (IsLedOutOfBound(ledNumber)) { RUNTIME_ERROR("LED Driver: out-of-bounds LED", -1); return; } - ledsImage |= convertLedNumberToBit(ledNumber); + SetLedImageBit(ledNumber); updateHardware(); } @@ -51,11 +72,30 @@ void LedDriver_TurnAllOn(void) { void LedDriver_TurnOff(int ledNumber) { - if(ledNumber < 0 || ledNumber > 16) { + if (IsLedOutOfBound(ledNumber)) { RUNTIME_ERROR("LED Driver: out-of-bounds LED", -1); return; } - ledsImage &= ~(convertLedNumberToBit(ledNumber)); + ClearLedImageBit(ledNumber); updateHardware(); } + + +void LedDriver_TurnAllOff(void) { + ledsImage = ALL_LEDS_OFF; + updateHardware(); +} + + +bool LedDriver_IsOn(int ledNumber) { + if(IsLedOutOfBound(ledNumber)) { + return false; + } + return ledsImage & 1 << (ledNumber - 1); +} + + +bool LedDriver_IsOff(int ledNumber) { + return !(LedDriver_IsOn(ledNumber)); +} diff --git a/tdd_for_embedded_c/chapter04/src/LedDriver.h b/tdd_for_embedded_c/chapter04/src/LedDriver.h index f09c88f..3ca3fa1 100644 --- a/tdd_for_embedded_c/chapter04/src/LedDriver.h +++ b/tdd_for_embedded_c/chapter04/src/LedDriver.h @@ -1,5 +1,6 @@ #include #include +#include @@ -7,4 +8,7 @@ void LedDriver_Create(uint16_t *address); void LedDriver_Destroy(uint16_t *address); void LedDriver_TurnOn(int ledNumber); void LedDriver_TurnOff(int ledNumber); -void LedDriver_TurnAllOn(void); \ No newline at end of file +void LedDriver_TurnAllOn(void); +void LedDriver_TurnAllOff(void); +bool LedDriver_IsOn(int ledNumber); +bool LedDriver_IsOff(int ledNumber); diff --git a/tdd_for_embedded_c/chapter04/test/LedDriverTest.c b/tdd_for_embedded_c/chapter04/test/LedDriverTest.c index 7242bb0..0bfed2c 100644 --- a/tdd_for_embedded_c/chapter04/test/LedDriverTest.c +++ b/tdd_for_embedded_c/chapter04/test/LedDriverTest.c @@ -132,3 +132,50 @@ TEST(LedDriver, OutOfBoundsProducesRuntimeError) { IGNORE_TEST(LedDriver, OutOfBoundsToDo) { /* TODO: what should we do during runtime? */ } + + +TEST(LedDriver, IsOn) { + + TEST_ASSERT_FALSE(LedDriver_IsOn(11)); + LedDriver_TurnOn(11); + TEST_ASSERT_TRUE(LedDriver_IsOn(11)); + +} + + +TEST(LedDriver, OutOfBoundsLedsAreAlwaysOff) { + + TEST_ASSERT_TRUE(LedDriver_IsOff(0)); + TEST_ASSERT_TRUE(LedDriver_IsOff(17)); + TEST_ASSERT_FALSE(LedDriver_IsOn(0)); + TEST_ASSERT_FALSE(LedDriver_IsOn(17)); + +} + + +TEST(LedDriver, IsOff) { + + TEST_ASSERT_TRUE(LedDriver_IsOff(12)); + LedDriver_TurnOn(12); + TEST_ASSERT_FALSE(LedDriver_IsOff(12)); + +} + + +TEST(LedDriver, TurnOffMultipleLeds) { + + LedDriver_TurnAllOn(); + LedDriver_TurnOff(9); + LedDriver_TurnOff(8); + TEST_ASSERT_EQUAL(~(0x0180) & 0xFFFF, virtualLeds); + +} + + +TEST(LedDriver, TurnAllOff) { + + LedDriver_TurnAllOn(); + LedDriver_TurnAllOff(); + TEST_ASSERT_EQUAL(0x0000, virtualLeds); + +} diff --git a/tdd_for_embedded_c/chapter04/test/LedDriverTestRunner.c b/tdd_for_embedded_c/chapter04/test/LedDriverTestRunner.c index b558718..a80e686 100644 --- a/tdd_for_embedded_c/chapter04/test/LedDriverTestRunner.c +++ b/tdd_for_embedded_c/chapter04/test/LedDriverTestRunner.c @@ -7,7 +7,9 @@ TEST_GROUP_RUNNER(LedDriver) { RUN_TEST_CASE(LedDriver, TurnOnLedOne); RUN_TEST_CASE(LedDriver, TurnOffLedOne); RUN_TEST_CASE(LedDriver, TurnOnMultipleLeds); + RUN_TEST_CASE(LedDriver, TurnOffMultipleLeds); RUN_TEST_CASE(LedDriver, TurnAllOn); + RUN_TEST_CASE(LedDriver, TurnAllOff); RUN_TEST_CASE(LedDriver, TurnOffAnyLed); RUN_TEST_CASE(LedDriver, LedMemoryIsNotReadable); RUN_TEST_CASE(LedDriver, UpperAndLowerBounds); @@ -15,5 +17,8 @@ TEST_GROUP_RUNNER(LedDriver) { RUN_TEST_CASE(LedDriver, OutOfBoundsTurnOffDoesNotHarm); RUN_TEST_CASE(LedDriver, OutOfBoundsProducesRuntimeError); RUN_TEST_CASE(LedDriver, OutOfBoundsToDo); + RUN_TEST_CASE(LedDriver, IsOn); + RUN_TEST_CASE(LedDriver, OutOfBoundsLedsAreAlwaysOff); + RUN_TEST_CASE(LedDriver, IsOff); }