Buttons module implementation
A module representing a model of the 3 buttons Includes a unit test project (empty at this stage)pull/12/head
parent
47528c3bca
commit
d47765cad8
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/// Hardware Abstraction Layer for the ADC's
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1 +0,0 @@
|
|||
int main() {}
|
||||
|
|
@ -1 +1,2 @@
|
|||
add_subdirectory(buttons)
|
||||
add_subdirectory(protocol)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
Loading…
Reference in New Issue