Compare commits

...

2 Commits

Author SHA1 Message Date
2fcdd83124 Add Peripheerals/Button module
All checks were successful
continuous-integration/drone/push Build is passing
2021-04-17 23:30:46 +03:00
1dc2eb0927 Update cmake to C++17. 2021-04-17 22:47:53 +03:00
4 changed files with 207 additions and 6 deletions

View File

@ -12,7 +12,7 @@ project(skullc
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/)
set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD 17)
list(APPEND CMAKE_CXX_FLAGS "-Wall -Wextra") list(APPEND CMAKE_CXX_FLAGS "-Wall -Wextra")
option(WITH_TESTS "Enable unit testing." OFF) option(WITH_TESTS "Enable unit testing." OFF)
@ -20,10 +20,7 @@ option(WITH_HAL "Enable the compiling and deployment of the HAL dependent sectio
include(skullc-install) include(skullc-install)
if(WITH_HAL) add_subdirectory(Peripherals)
add_subdirectory(Peripherals)
endif()
add_subdirectory(Utility) add_subdirectory(Utility)
add_subdirectory(Messaging) add_subdirectory(Messaging)

View File

@ -0,0 +1,76 @@
/*
* peripherals_button.hpp
*
* Created on: Apr 17, 2021
* Author: erki
*/
#ifndef PERIPHERALS_BUTTON_HPP_
#define PERIPHERALS_BUTTON_HPP_
#include <cstdint>
namespace Peripherals
{
enum class ButtonPress : std::uint32_t
{
NOT_PRESSED,
SHORT_PRESS,
LONG_PRESS
};
template<typename G, typename H>
class Button
{
public:
using gpio = G;
using hal = H;
static constexpr std::uint32_t TIMEOUT_SHORT_PRESS = 50;
static constexpr std::uint32_t TIMEOUT_LONG_PRESS = 500;
Button() = delete;
explicit Button(const gpio& sw)
: _sw(sw)
{}
void update()
{
const bool is_pressed = _sw.Read();
ButtonPress new_state = ButtonPress::NOT_PRESSED;
if (is_pressed && !_was_pressed)
{
_time_pressed_down = hal::GetMillis();
} else if (!is_pressed && _was_pressed)
{
const std::uint32_t time_held = hal::GetMillis() - _time_pressed_down;
if (time_held > TIMEOUT_LONG_PRESS)
new_state = ButtonPress::LONG_PRESS;
else if (time_held > TIMEOUT_SHORT_PRESS)
new_state = ButtonPress::SHORT_PRESS;
_time_pressed_down = 0;
}
_was_pressed = is_pressed;
_current_state = new_state;
}
[[nodiscard]] ButtonPress getState() const
{
return _current_state;
}
private:
gpio _sw;
bool _was_pressed = false;
std::uint32_t _time_pressed_down = 0;
ButtonPress _current_state = ButtonPress::NOT_PRESSED;
};
}// namespace Peripherals
#endif /* PERIPHERALS_BUTTON_HPP_ */

View File

@ -13,12 +13,14 @@ add_executable(tests
main.cpp main.cpp
ringbuffer.cpp ringbuffer.cpp
packet.cpp packet.cpp
parser.cpp) parser.cpp
button.cpp)
target_link_libraries(tests target_link_libraries(tests
PUBLIC PUBLIC
skullc::utility skullc::utility
skullc::messaging skullc::messaging
skullc::peripherals
Catch2::Catch2 Catch2::Catch2
) )

126
Tests/button.cpp Normal file
View File

@ -0,0 +1,126 @@
//
// Created by erki on 17.04.21.
//
#include <catch2/catch.hpp>
#include "peripherals_button.hpp"
namespace
{
struct HAL
{
HAL()
{
millis = 1;
}
~HAL()
{
millis = 1;
}
static std::uint32_t millis;
static std::uint32_t GetMillis()
{
return millis;
}
};
std::uint32_t HAL::millis = 1;
struct Gpio
{
static bool set;
Gpio()
{
set = false;
}
bool Read()
{
return set;
}
};
bool Gpio::set = false;
}// namespace
using Button = Peripherals::Button<Gpio, HAL>;
TEST_CASE("Button reads no press as NOT_PRESSED.", "[peripherals],[button]")
{
Gpio g;
HAL hal;
Button button{g};
button.update();
HAL::millis = Button::TIMEOUT_LONG_PRESS + 10;
button.update();
REQUIRE(button.getState() == Peripherals::ButtonPress::NOT_PRESSED);
}
TEST_CASE("Button reads presses properly.", "[peripherals],[button]")
{
Gpio g;
HAL hal;
Button button{g};
Gpio::set = true;
button.update();
SECTION("Too short of a press is debounced.")
{
HAL::millis = Button::TIMEOUT_SHORT_PRESS - 1;
Gpio::set = false;
button.update();
REQUIRE(button.getState() == Peripherals::ButtonPress::NOT_PRESSED);
}
SECTION("Short press is identified properly.")
{
HAL::millis = Button::TIMEOUT_SHORT_PRESS + 2;
Gpio::set = false;
button.update();
REQUIRE(button.getState() == Peripherals::ButtonPress::SHORT_PRESS);
SECTION("Next state is NOT_PRESSED.")
{
HAL::millis += 1;
button.update();
REQUIRE(button.getState() == Peripherals::ButtonPress::NOT_PRESSED);
}
}
SECTION("Long press is identified properly.")
{
HAL::millis = Button::TIMEOUT_LONG_PRESS + 2;
Gpio::set = false;
button.update();
REQUIRE(button.getState() == Peripherals::ButtonPress::LONG_PRESS);
SECTION("Next state is NOT_PRESSED.")
{
HAL::millis += 1;
button.update();
REQUIRE(button.getState() == Peripherals::ButtonPress::NOT_PRESSED);
}
}
}