Buttons module implementation

A module representing a model of the 3 buttons
Includes a unit test project (empty at this stage)
pull/15/head
D.R.racer 2021-05-19 08:49:04 +02:00 committed by DRracer
parent 47528c3bca
commit ba8eacfe33
9 changed files with 143 additions and 16 deletions

View File

@ -175,21 +175,6 @@ if(CMAKE_CROSSCOMPILING)
# generate linker map file
target_link_options(firmware PUBLIC -Wl,-Map=firmware.map)
target_sources(
firmware PRIVATE src/main.cpp src/hal/avr/cpu.cpp src/modules/protocol.cpp
src/hal/avr/usart.cpp
)
else()
enable_testing()
add_subdirectory(tests)
# TODO - still need to decide about the dummy_main.cpp - for unit tests it should not be necessary
# to make a separate main.cpp file
target_sources(
firmware PRIVATE tests/unit/dummy_main.cpp src/hal/avr/cpu.cpp src/modules/protocol.cpp
)
endif()
# add_link_dependency(firmware "${LINKER_SCRIPT}")
@ -197,6 +182,10 @@ endif()
target_include_directories(firmware PRIVATE include src)
target_compile_options(firmware PRIVATE -Wdouble-promotion)
target_sources(
firmware PRIVATE src/main.cpp src/hal/avr/cpu.cpp src/hal/avr/usart.cpp src/modules/protocol.cpp
src/modules/buttons.cpp
)
set_property(
SOURCE src/version.c
@ -208,3 +197,7 @@ set_property(
FW_VERSION_SUFFIX=${PROJECT_VERSION_SUFFIX}
FW_VERSION_SUFFIX_SHORT=${PROJECT_VERSION_SUFFIX_SHORT}
)
if(NOT CMAKE_CROSSCOMPILING)
enable_testing()
add_subdirectory(tests)
endif()

View File

@ -1,4 +1,5 @@
#pragma once
#include <stdint.h>
/// Hardware Abstraction Layer for the ADC's

74
src/modules/buttons.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "buttons.h"
#include "../hal/adc.h"
namespace modules {
uint16_t Buttons::tmpTiming = 0;
// original idea from: https://www.eeweb.com/debouncing-push-buttons-using-a-state-machine-approach
void Button::Step(uint16_t time, bool press) {
switch (state) {
case State::Waiting:
if (press) {
state = State::Detected;
timeLastChange = time;
tmp = press;
}
break;
case State::Detected:
if (tmp == press) {
if (time - timeLastChange > debounce) {
state = State::WaitForRelease;
}
} else {
state = State::Waiting;
}
break;
case State::WaitForRelease:
if (!press) {
state = State::Update;
}
break;
case State::Update:
pressed = tmp;
state = State::Waiting;
timeLastChange = time;
tmp = false;
break;
default:
state = State::Waiting;
timeLastChange = time;
tmp = false;
pressed = false;
}
}
int8_t Buttons::Sample() {
// decode 3 buttons' levels from one ADC
uint16_t raw = hal::ADC::ReadADC(0);
// Button 1 - 0
// Button 2 - 344
// Button 3 - 516
// Doesn't handle multiple pressed buttons at once
if (raw < 10)
return 0;
else if (raw > 320 && raw < 360)
return 1;
else if (raw > 500 && raw < 530)
return 2;
return -1;
}
void Buttons::Step() {
// @@TODO temporary timing
++tmpTiming;
int8_t currentState = Sample();
for (uint_fast8_t b = 0; b < N; ++b) {
// this button was pressed if b == currentState, released otherwise
buttons[b].Step(tmpTiming, b == currentState);
}
}
} // namespace modules

View File

@ -1 +0,0 @@
int main() {}

View File

@ -1 +1,2 @@
add_subdirectory(buttons)
add_subdirectory(protocol)

View File

@ -0,0 +1,10 @@
# define the test executable
add_executable(buttons_tests ../../../../src/modules/buttons.cpp stub_adc.cpp test_buttons.cpp)
# define required search paths
target_include_directories(
buttons_tests PUBLIC ${CMAKE_SOURCE_DIR}/src/modules ${CMAKE_SOURCE_DIR}/src/hal
)
# tell build system about the test case
add_catch_test(buttons_tests)

View File

@ -0,0 +1,20 @@
#include "adc.h"
#include "stub_adc.h"
#include <vector>
namespace hal {
namespace ADC {
static TADCData values2Return;
static TADCData::const_iterator rdptr = values2Return.cbegin();
void ReinitADC(TADCData d) {
values2Return = d;
rdptr = values2Return.cbegin();
}
/// ADC access routines
uint16_t ReadADC(uint8_t /*adc*/) { return rdptr != values2Return.end() ? *rdptr++ : 0; }
} // namespace ADC
} // namespace hal

View File

@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
#include <vector>
namespace hal {
namespace ADC {
using TADCData = std::vector<uint16_t>;
void ReinitADC(TADCData d);
} // namespace ADC
} // namespace hal

View File

@ -0,0 +1,15 @@
#include "catch2/catch.hpp"
#include "buttons.h"
#include "stub_adc.h"
using Catch::Matchers::Equals;
TEST_CASE("buttons::Step", "[buttons]") {
using namespace modules;
hal::ADC::TADCData d = { 1, 2, 3, 4, 5 };
hal::ADC::ReinitADC(d);
Buttons b;
b.Step();
}