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
|
# generate linker map file
|
||||||
target_link_options(firmware PUBLIC -Wl,-Map=firmware.map)
|
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()
|
endif()
|
||||||
|
|
||||||
# add_link_dependency(firmware "${LINKER_SCRIPT}")
|
# add_link_dependency(firmware "${LINKER_SCRIPT}")
|
||||||
|
|
@ -197,6 +182,10 @@ endif()
|
||||||
target_include_directories(firmware PRIVATE include src)
|
target_include_directories(firmware PRIVATE include src)
|
||||||
|
|
||||||
target_compile_options(firmware PRIVATE -Wdouble-promotion)
|
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(
|
set_property(
|
||||||
SOURCE src/version.c
|
SOURCE src/version.c
|
||||||
|
|
@ -208,3 +197,7 @@ set_property(
|
||||||
FW_VERSION_SUFFIX=${PROJECT_VERSION_SUFFIX}
|
FW_VERSION_SUFFIX=${PROJECT_VERSION_SUFFIX}
|
||||||
FW_VERSION_SUFFIX_SHORT=${PROJECT_VERSION_SUFFIX_SHORT}
|
FW_VERSION_SUFFIX_SHORT=${PROJECT_VERSION_SUFFIX_SHORT}
|
||||||
)
|
)
|
||||||
|
if(NOT CMAKE_CROSSCOMPILING)
|
||||||
|
enable_testing()
|
||||||
|
add_subdirectory(tests)
|
||||||
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
/// Hardware Abstraction Layer for the ADC's
|
/// 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)
|
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