Prusa-Firmware-MMU/tests/unit/modules/buttons/test_buttons.cpp

162 lines
5.6 KiB
C++

#include "catch2/catch.hpp"
#include "buttons.h"
#include "stub_adc.h"
using Catch::Matchers::Equals;
bool Step_Basic_One_Button_Test(modules::buttons::Buttons &b, uint8_t oversampleFactor, uint8_t testedButtonIndex, uint8_t otherButton1, uint8_t otherButton2) {
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // should detect the press but remain in detected state - wait for debounce
CHECK(!b.ButtonPressed(testedButtonIndex));
CHECK(!b.ButtonPressed(otherButton1));
CHECK(!b.ButtonPressed(otherButton2));
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // reset to waiting
CHECK(b.ButtonPressed(testedButtonIndex));
CHECK(!b.ButtonPressed(otherButton1));
CHECK(!b.ButtonPressed(otherButton2));
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // pressed again, still in debouncing state
CHECK(!b.ButtonPressed(testedButtonIndex));
CHECK(!b.ButtonPressed(otherButton1));
CHECK(!b.ButtonPressed(otherButton2));
return true;
}
/// This test verifies the behaviour of a single button. The other buttons must remain intact.
bool Step_Basic_One_Button(hal::adc::TADCData &&d, uint8_t testedButtonIndex) {
using namespace modules::buttons;
Buttons b;
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
constexpr uint8_t oversampleFactor = 100;
hal::adc::ReinitADC(std::move(d), oversampleFactor);
uint8_t otherButton1 = 1, otherButton2 = 2;
switch (testedButtonIndex) {
case 1:
otherButton1 = 0;
break;
case 2:
otherButton2 = 0;
break;
default:
break; // no change
}
return Step_Basic_One_Button_Test(b, oversampleFactor, testedButtonIndex, otherButton1, otherButton2);
}
TEST_CASE("buttons::Step-basic-button", "[buttons]") {
{
hal::adc::TADCData d({ 5, 6, 1023 });
CHECK(Step_Basic_One_Button(std::move(d), 0));
}
{
hal::adc::TADCData d({ 321, 359, 1023 });
CHECK(Step_Basic_One_Button(std::move(d), 1));
}
{
hal::adc::TADCData d({ 501, 529, 1023 });
CHECK(Step_Basic_One_Button(std::move(d), 2));
}
}
/// This test has to verify the independency of buttons - the ADC reads one button after the other
/// and the Buttons class should press first button and release, then the second one and then the third one
/// without being reinitialized.
TEST_CASE("buttons::Step-basic-button-one-after-other", "[buttons]") {
using namespace modules::buttons;
hal::adc::TADCData d({ 5, 6, 1023, 321, 359, 1023, 501, 529, 1023 });
Buttons b;
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
constexpr uint8_t oversampleFactor = 100;
hal::adc::ReinitADC(std::move(d), oversampleFactor);
CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 0, 1, 2));
CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 1, 0, 2));
CHECK(Step_Basic_One_Button_Test(b, oversampleFactor, 2, 0, 1));
}
/// This test tries to simulate a bouncing effect on data from ADC on the first button
TEST_CASE("buttons::Step-debounce-one-button", "[buttons]") {
using namespace modules::buttons;
// make a bounce event on the first press
hal::adc::TADCData d({ 5, 1023, 5, 9, 6, 7, 8, 1023, 1023 });
// need to oversample the data as debouncing takes 100 cycles to accept a pressed button
constexpr uint8_t oversampleFactor = 25;
hal::adc::ReinitADC(std::move(d), oversampleFactor);
Buttons b;
// 5
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // should detect the press but remain in detected state - wait for debounce
CHECK(!b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
// 1023
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // reset to waiting
CHECK(!b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
// 5
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // pressed again, still in debouncing state
CHECK(!b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
// 9
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // no change
CHECK(!b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
// 6
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // no change
CHECK(!b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
// 7
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // one step from "pressed"
CHECK(!b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
// 8
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // fifth set of samples - should report "pressed" finally
CHECK(b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
// 1023
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // sixth set of samples - button released (no debouncing on release)
CHECK(!b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
// 1023
for (uint8_t i = 0; i < oversampleFactor; ++i)
b.Step(hal::adc::ReadADC(0)); // seventh set of samples - still released
CHECK(!b.ButtonPressed(0));
CHECK(!b.ButtonPressed(1));
CHECK(!b.ButtonPressed(2));
}