Fix unit tests
parent
5a636529ca
commit
d80a58cfdb
|
|
@ -22,7 +22,7 @@ static constexpr const uint8_t toolCount = 5U; ///< Max number of extruders/tool
|
||||||
static_assert(toolCount < 15, "Up to 14 valid slots (+1 parking) is supported in EEPROM storage");
|
static_assert(toolCount < 15, "Up to 14 valid slots (+1 parking) is supported in EEPROM storage");
|
||||||
|
|
||||||
// Printer's filament sensor setup
|
// Printer's filament sensor setup
|
||||||
static constexpr const uint16_t fsensorDebounceMs = 10;
|
static constexpr const uint16_t fsensorDebounceMs = 2;
|
||||||
|
|
||||||
// LEDS
|
// LEDS
|
||||||
/// The complete period of LED's blinking (i.e. ON and OFF together)
|
/// The complete period of LED's blinking (i.e. ON and OFF together)
|
||||||
|
|
|
||||||
|
|
@ -17,23 +17,39 @@ void UserInput::Step() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserInput::ProcessMessage(uint8_t ev) {
|
void UserInput::ProcessMessage(uint8_t ev) {
|
||||||
eventQueue.push((Event)ev);
|
eventQueue.push((Event)(ev | Event::FromPrinter));
|
||||||
|
}
|
||||||
|
|
||||||
|
Event UserInput::StripFromPrinterBit(uint8_t e) {
|
||||||
|
e &= (uint8_t)(~Event::FromPrinter);
|
||||||
|
return (Event)e;
|
||||||
}
|
}
|
||||||
|
|
||||||
Event UserInput::ConsumeEvent() {
|
Event UserInput::ConsumeEvent() {
|
||||||
if (printerInCharge) {
|
if (printerInCharge) {
|
||||||
|
Event rv = eventQueue.front();
|
||||||
|
if (rv & Event::FromPrinter) {
|
||||||
|
eventQueue.pop(rv);
|
||||||
|
return StripFromPrinterBit(rv);
|
||||||
|
}
|
||||||
return Event::NoEvent;
|
return Event::NoEvent;
|
||||||
} else {
|
} else {
|
||||||
return ConsumeEventForPrinter();
|
Event rv;
|
||||||
|
eventQueue.pop(rv);
|
||||||
|
return StripFromPrinterBit(rv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Event UserInput::ConsumeEventForPrinter() {
|
Event UserInput::ConsumeEventForPrinter() {
|
||||||
if (eventQueue.empty())
|
if (eventQueue.empty())
|
||||||
return Event::NoEvent;
|
return Event::NoEvent;
|
||||||
Event rv;
|
Event rv = eventQueue.front();
|
||||||
|
if (rv & Event::FromPrinter) {
|
||||||
|
// do not send the same buttons back but leave them in the queue for the MMU FW
|
||||||
|
return Event::NoEvent;
|
||||||
|
}
|
||||||
eventQueue.pop(rv);
|
eventQueue.pop(rv);
|
||||||
return rv;
|
return StripFromPrinterBit(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserInput::Clear() {
|
void UserInput::Clear() {
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,12 @@ namespace modules {
|
||||||
namespace user_input {
|
namespace user_input {
|
||||||
|
|
||||||
/// Beware - button codes intentionally match the protocol button encoding for optimization purposes
|
/// Beware - button codes intentionally match the protocol button encoding for optimization purposes
|
||||||
enum class Event : int8_t {
|
enum Event : uint8_t {
|
||||||
NoEvent = -1,
|
NoEvent = 0x7f,
|
||||||
Left = 0,
|
Right = 0,
|
||||||
Middle = 1,
|
Middle = 1,
|
||||||
Right = 2
|
Left = 2,
|
||||||
|
FromPrinter = 0x80
|
||||||
};
|
};
|
||||||
|
|
||||||
class UserInput {
|
class UserInput {
|
||||||
|
|
@ -58,6 +59,8 @@ public:
|
||||||
private:
|
private:
|
||||||
CircularBuffer<Event, uint_fast8_t, 4> eventQueue;
|
CircularBuffer<Event, uint_fast8_t, 4> eventQueue;
|
||||||
bool printerInCharge = false;
|
bool printerInCharge = false;
|
||||||
|
|
||||||
|
static Event StripFromPrinterBit(uint8_t e);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern UserInput userInput;
|
extern UserInput userInput;
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,25 @@ void LoadFilamentSuccessful(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LoadFilamentSuccessfulWithRehomeSelector(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
// Stage 2 - feeding to finda
|
||||||
|
// make FINDA switch on
|
||||||
|
REQUIRE(WhileCondition(lf, std::bind(SimulateFeedToFINDA, _1, 100), 5000));
|
||||||
|
REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, slot, slot, true, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::RetractingFromFinda));
|
||||||
|
|
||||||
|
// Stage 3 - retracting from finda
|
||||||
|
// we'll assume the finda is working correctly here
|
||||||
|
REQUIRE(WhileCondition(lf, std::bind(SimulateRetractFromFINDA, _1, 100), 5000));
|
||||||
|
REQUIRE(WhileCondition(
|
||||||
|
lf, [&](uint32_t) { return lf.State() == ProgressCode::RetractingFromFinda; }, 50000));
|
||||||
|
REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, slot, 0xff, false, true, ml::off, ml::off, ErrorCode::RUNNING, ProgressCode::DisengagingIdler));
|
||||||
|
|
||||||
|
// Stage 4 - disengaging Idler + homing Selector simultaneously
|
||||||
|
SimulateSelectorHoming(lf);
|
||||||
|
|
||||||
|
REQUIRE(VerifyState(lf, mg::FilamentLoadState::AtPulley, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::off, ErrorCode::OK, ProgressCode::OK));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("load_filament::regular_load_to_slot_0-4", "[load_filament]") {
|
TEST_CASE("load_filament::regular_load_to_slot_0-4", "[load_filament]") {
|
||||||
for (uint8_t slot = 0; slot < config::toolCount; ++slot) {
|
for (uint8_t slot = 0; slot < config::toolCount; ++slot) {
|
||||||
logic::LoadFilament lf;
|
logic::LoadFilament lf;
|
||||||
|
|
@ -106,10 +125,12 @@ void FailedLoadToFindaResolveHelp(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
// - resolve the problem by hand - after pressing the button we shall check, that FINDA is off and we should do what?
|
// - resolve the problem by hand - after pressing the button we shall check, that FINDA is off and we should do what?
|
||||||
|
|
||||||
// In this case we check the first option
|
// In this case we check the first option
|
||||||
PressButtonAndDebounce(lf, mb::Left);
|
PressButtonAndDebounce(lf, mb::Left, false);
|
||||||
|
|
||||||
REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::blink0, ErrorCode::RUNNING, ProgressCode::ERREngagingIdler));
|
REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::blink0, ErrorCode::RUNNING, ProgressCode::ERREngagingIdler));
|
||||||
|
|
||||||
|
SimulateIdlerHoming(lf);
|
||||||
|
|
||||||
// Stage 4 - engage the idler
|
// Stage 4 - engage the idler
|
||||||
REQUIRE(WhileTopState(lf, ProgressCode::ERREngagingIdler, idlerEngageDisengageMaxSteps));
|
REQUIRE(WhileTopState(lf, ProgressCode::ERREngagingIdler, idlerEngageDisengageMaxSteps));
|
||||||
|
|
||||||
|
|
@ -144,7 +165,7 @@ void FailedLoadToFindaResolveManual(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
|
||||||
// Perform press on button 2 + debounce + switch on FINDA
|
// Perform press on button 2 + debounce + switch on FINDA
|
||||||
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high);
|
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::high);
|
||||||
PressButtonAndDebounce(lf, mb::Right);
|
PressButtonAndDebounce(lf, mb::Right, false);
|
||||||
|
|
||||||
// the Idler also engages in this call as this is planned as the next step
|
// the Idler also engages in this call as this is planned as the next step
|
||||||
SimulateIdlerHoming(lf);
|
SimulateIdlerHoming(lf);
|
||||||
|
|
@ -189,7 +210,7 @@ void FailedLoadToFindaResolveManual(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
|
|
||||||
void FailedLoadToFindaResolveManualNoFINDA(uint8_t slot, logic::LoadFilament &lf) {
|
void FailedLoadToFindaResolveManualNoFINDA(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
// Perform press on button 2 + debounce + keep FINDA OFF (i.e. the user didn't solve anything)
|
// Perform press on button 2 + debounce + keep FINDA OFF (i.e. the user didn't solve anything)
|
||||||
PressButtonAndDebounce(lf, mb::Right);
|
PressButtonAndDebounce(lf, mb::Right, false);
|
||||||
|
|
||||||
SimulateIdlerHoming(lf);
|
SimulateIdlerHoming(lf);
|
||||||
|
|
||||||
|
|
@ -200,14 +221,16 @@ void FailedLoadToFindaResolveManualNoFINDA(uint8_t slot, logic::LoadFilament &lf
|
||||||
}
|
}
|
||||||
|
|
||||||
void FailedLoadToFindaResolveTryAgain(uint8_t slot, logic::LoadFilament &lf) {
|
void FailedLoadToFindaResolveTryAgain(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
PressButtonAndDebounce(lf, mb::Middle);
|
PressButtonAndDebounce(lf, mb::Middle, false);
|
||||||
|
|
||||||
// the state machine should have restarted
|
// the state machine should have restarted
|
||||||
// Idler's position needs to be ignored as it has started homing after the button press
|
// Idler's position needs to be ignored as it has started homing after the button press
|
||||||
REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, config::toolCount, slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda));
|
REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, config::toolCount, slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda));
|
||||||
ClearButtons(lf);
|
ClearButtons(lf);
|
||||||
|
|
||||||
LoadFilamentSuccessful(slot, lf);
|
SimulateIdlerHoming(lf);
|
||||||
|
|
||||||
|
LoadFilamentSuccessfulWithRehomeSelector(slot, lf);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_ok", "[load_filament]") {
|
TEST_CASE("load_filament::failed_load_to_finda_0-4_resolve_help_second_ok", "[load_filament]") {
|
||||||
|
|
@ -330,7 +353,7 @@ void LoadFilamentStopped(uint8_t slot, logic::LoadFilament &lf) {
|
||||||
REQUIRE_FALSE(WhileTopState(lf, ProgressCode::FeedingToFinda, 5000));
|
REQUIRE_FALSE(WhileTopState(lf, ProgressCode::FeedingToFinda, 5000));
|
||||||
|
|
||||||
// now press a button
|
// now press a button
|
||||||
PressButtonAndDebounce(lf, mb::Middle);
|
PressButtonAndDebounce(lf, mb::Middle, false);
|
||||||
|
|
||||||
REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, slot, slot, false, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::RetractingFromFinda));
|
REQUIRE(VerifyState(lf, mg::FilamentLoadState::InSelector, slot, slot, false, true, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::RetractingFromFinda));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ bool SimulateFailedHomeSelectorPostfix(logic::CommandBase &cb) {
|
||||||
if (mm::motion.Enabled(mm::Selector))
|
if (mm::motion.Enabled(mm::Selector))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
PressButtonAndDebounce(cb, mb::Middle);
|
PressButtonAndDebounce(cb, mb::Middle, false);
|
||||||
|
|
||||||
// it shall start homing again
|
// it shall start homing again
|
||||||
if (cb.Error() != ErrorCode::RUNNING)
|
if (cb.Error() != ErrorCode::RUNNING)
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ void ForceReinitAllAutomata() {
|
||||||
new (&mpu::pulley) mpu::Pulley();
|
new (&mpu::pulley) mpu::Pulley();
|
||||||
new (&ms::selector) ms::Selector();
|
new (&ms::selector) ms::Selector();
|
||||||
new (&mm::motion) mm::Motion();
|
new (&mm::motion) mm::Motion();
|
||||||
|
new (&mui::userInput) mui::UserInput();
|
||||||
|
|
||||||
hal::eeprom::ClearEEPROM();
|
hal::eeprom::ClearEEPROM();
|
||||||
|
|
||||||
|
|
@ -133,13 +134,19 @@ bool SimulateRetractFromFINDA(uint32_t step, uint32_t findaOff) {
|
||||||
return mf::finda.Pressed();
|
return mf::finda.Pressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex) {
|
void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex, bool fromPrinter) {
|
||||||
|
if (fromPrinter) {
|
||||||
|
mui::userInput.ProcessMessage(btnIndex);
|
||||||
|
main_loop();
|
||||||
|
cb.Step();
|
||||||
|
} else {
|
||||||
hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCLimits[btnIndex][0] + 1);
|
hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCLimits[btnIndex][0] + 1);
|
||||||
while (!mb::buttons.ButtonPressed(btnIndex)) {
|
while (!mb::buttons.ButtonPressed(btnIndex)) {
|
||||||
main_loop();
|
main_loop();
|
||||||
cb.Step(); // Inner
|
cb.Step(); // Inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClearButtons(logic::CommandBase &cb) {
|
void ClearButtons(logic::CommandBase &cb) {
|
||||||
hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCMaxValue);
|
hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCMaxValue);
|
||||||
|
|
@ -148,3 +155,10 @@ void ClearButtons(logic::CommandBase &cb) {
|
||||||
cb.Step(); // Inner
|
cb.Step(); // Inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetFSensorStateAndDebounce(bool press) {
|
||||||
|
mfs::fsensor.ProcessMessage(press);
|
||||||
|
for (uint8_t fs = 0; fs < config::fsensorDebounceMs + 1; ++fs) {
|
||||||
|
main_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,11 @@ bool SimulateUnloadToFINDA(uint32_t step, uint32_t fsOff, uint32_t findaOff);
|
||||||
bool SimulateFeedToFINDA(uint32_t step, uint32_t findaOn);
|
bool SimulateFeedToFINDA(uint32_t step, uint32_t findaOn);
|
||||||
bool SimulateRetractFromFINDA(uint32_t step, uint32_t findaOff);
|
bool SimulateRetractFromFINDA(uint32_t step, uint32_t findaOff);
|
||||||
|
|
||||||
void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex);
|
void PressButtonAndDebounce(logic::CommandBase &cb, uint8_t btnIndex, bool fromPrinter);
|
||||||
void ClearButtons(logic::CommandBase &cb);
|
void ClearButtons(logic::CommandBase &cb);
|
||||||
|
|
||||||
|
void SetFSensorStateAndDebounce(bool press);
|
||||||
|
|
||||||
// these are recommended max steps for simulated movement of the idler and selector
|
// these are recommended max steps for simulated movement of the idler and selector
|
||||||
// - roughly the amount of motion steps from one end to the other + some margin
|
// - roughly the amount of motion steps from one end to the other + some margin
|
||||||
// ... could be computed in the future from the pre-set number of microsteps and real positions
|
// ... could be computed in the future from the pre-set number of microsteps and real positions
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include "../../../../src/modules/motion.h"
|
#include "../../../../src/modules/motion.h"
|
||||||
#include "../../../../src/modules/permanent_storage.h"
|
#include "../../../../src/modules/permanent_storage.h"
|
||||||
#include "../../../../src/modules/selector.h"
|
#include "../../../../src/modules/selector.h"
|
||||||
|
#include "../../../../src/modules/user_input.h"
|
||||||
|
|
||||||
#include "../../../../src/logic/tool_change.h"
|
#include "../../../../src/logic/tool_change.h"
|
||||||
|
|
||||||
|
|
@ -67,7 +68,7 @@ void ToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) {
|
||||||
|
|
||||||
REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle));
|
REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle));
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
mfs::fsensor.ProcessMessage(true);
|
SetFSensorStateAndDebounce(true);
|
||||||
|
|
||||||
// restart the automaton
|
// restart the automaton
|
||||||
tc.Reset(toSlot);
|
tc.Reset(toSlot);
|
||||||
|
|
@ -98,8 +99,8 @@ void NoToolChange(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSlot) {
|
||||||
|
|
||||||
REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle));
|
REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle));
|
||||||
// the filament is LOADED
|
// the filament is LOADED
|
||||||
mfs::fsensor.ProcessMessage(true);
|
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
|
SetFSensorStateAndDebounce(true);
|
||||||
|
|
||||||
REQUIRE(VerifyEnvironmentState(mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::off, ml::off));
|
REQUIRE(VerifyEnvironmentState(mg::FilamentLoadState::InNozzle, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::off, ml::off));
|
||||||
|
|
||||||
|
|
@ -177,7 +178,7 @@ void ToolChangeFailLoadToFinda(logic::ToolChange &tc, uint8_t fromSlot, uint8_t
|
||||||
|
|
||||||
REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle));
|
REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle));
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
mfs::fsensor.ProcessMessage(true);
|
SetFSensorStateAndDebounce(true);
|
||||||
|
|
||||||
// restart the automaton
|
// restart the automaton
|
||||||
tc.Reset(toSlot);
|
tc.Reset(toSlot);
|
||||||
|
|
@ -197,7 +198,7 @@ void ToolChangeFailLoadToFinda(logic::ToolChange &tc, uint8_t fromSlot, uint8_t
|
||||||
|
|
||||||
void ToolChangeFailLoadToFindaLeftBtn(logic::ToolChange &tc, uint8_t toSlot) {
|
void ToolChangeFailLoadToFindaLeftBtn(logic::ToolChange &tc, uint8_t toSlot) {
|
||||||
// now waiting for user input
|
// now waiting for user input
|
||||||
PressButtonAndDebounce(tc, mb::Left);
|
PressButtonAndDebounce(tc, mb::Left, true);
|
||||||
|
|
||||||
REQUIRE(WhileTopState(tc, ProgressCode::ERREngagingIdler, 5000UL));
|
REQUIRE(WhileTopState(tc, ProgressCode::ERREngagingIdler, 5000UL));
|
||||||
ClearButtons(tc);
|
ClearButtons(tc);
|
||||||
|
|
@ -223,7 +224,7 @@ void ToolChangeFailLoadToFindaLeftBtn(logic::ToolChange &tc, uint8_t toSlot) {
|
||||||
|
|
||||||
void ToolChangeFailLoadToFindaMiddleBtn(logic::ToolChange &tc, uint8_t toSlot) {
|
void ToolChangeFailLoadToFindaMiddleBtn(logic::ToolChange &tc, uint8_t toSlot) {
|
||||||
// now waiting for user input
|
// now waiting for user input
|
||||||
PressButtonAndDebounce(tc, mb::Middle);
|
PressButtonAndDebounce(tc, mb::Middle, true);
|
||||||
|
|
||||||
REQUIRE(WhileCondition(
|
REQUIRE(WhileCondition(
|
||||||
tc,
|
tc,
|
||||||
|
|
@ -251,8 +252,10 @@ void ToolChangeFailLoadToFindaMiddleBtn(logic::ToolChange &tc, uint8_t toSlot) {
|
||||||
void ToolChangeFailLoadToFindaRightBtnFINDA_FSensor(logic::ToolChange &tc, uint8_t toSlot) {
|
void ToolChangeFailLoadToFindaRightBtnFINDA_FSensor(logic::ToolChange &tc, uint8_t toSlot) {
|
||||||
// now waiting for user input - press FINDA and FSensor
|
// now waiting for user input - press FINDA and FSensor
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
mfs::fsensor.ProcessMessage(true);
|
REQUIRE(mf::finda.Pressed());
|
||||||
PressButtonAndDebounce(tc, mb::Right);
|
SetFSensorStateAndDebounce(true);
|
||||||
|
REQUIRE(mfs::fsensor.Pressed());
|
||||||
|
PressButtonAndDebounce(tc, mb::Right, true);
|
||||||
|
|
||||||
CheckFinishedCorrectly(tc, toSlot);
|
CheckFinishedCorrectly(tc, toSlot);
|
||||||
|
|
||||||
|
|
@ -262,7 +265,7 @@ void ToolChangeFailLoadToFindaRightBtnFINDA_FSensor(logic::ToolChange &tc, uint8
|
||||||
void ToolChangeFailLoadToFindaRightBtnFINDA(logic::ToolChange &tc, uint8_t toSlot) {
|
void ToolChangeFailLoadToFindaRightBtnFINDA(logic::ToolChange &tc, uint8_t toSlot) {
|
||||||
// now waiting for user input - press FINDA
|
// now waiting for user input - press FINDA
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
PressButtonAndDebounce(tc, mb::Right);
|
PressButtonAndDebounce(tc, mb::Right, true);
|
||||||
|
|
||||||
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser));
|
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), toSlot, true, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser));
|
||||||
|
|
||||||
|
|
@ -271,7 +274,7 @@ void ToolChangeFailLoadToFindaRightBtnFINDA(logic::ToolChange &tc, uint8_t toSlo
|
||||||
|
|
||||||
void ToolChangeFailLoadToFindaRightBtn(logic::ToolChange &tc, uint8_t toSlot) {
|
void ToolChangeFailLoadToFindaRightBtn(logic::ToolChange &tc, uint8_t toSlot) {
|
||||||
// now waiting for user input - do not press anything
|
// now waiting for user input - do not press anything
|
||||||
PressButtonAndDebounce(tc, mb::Right);
|
PressButtonAndDebounce(tc, mb::Right, true);
|
||||||
|
|
||||||
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), toSlot, false, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser));
|
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), toSlot, false, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_ON, ProgressCode::ERRWaitingForUser));
|
||||||
|
|
||||||
|
|
@ -332,7 +335,7 @@ void ToolChangeFailFSensor(logic::ToolChange &tc, uint8_t fromSlot, uint8_t toSl
|
||||||
|
|
||||||
REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle));
|
REQUIRE(EnsureActiveSlotIndex(fromSlot, mg::FilamentLoadState::InNozzle));
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
mfs::fsensor.ProcessMessage(true);
|
SetFSensorStateAndDebounce(true);
|
||||||
|
|
||||||
// restart the automaton
|
// restart the automaton
|
||||||
tc.Reset(toSlot);
|
tc.Reset(toSlot);
|
||||||
|
|
@ -348,8 +351,8 @@ void ToolChangeFailFSensorMiddleBtn(logic::ToolChange &tc, uint8_t fromSlot, uin
|
||||||
using namespace std::placeholders;
|
using namespace std::placeholders;
|
||||||
|
|
||||||
// user pulls filament out from the fsensor and presses Retry
|
// user pulls filament out from the fsensor and presses Retry
|
||||||
mfs::fsensor.ProcessMessage(false);
|
SetFSensorStateAndDebounce(false);
|
||||||
PressButtonAndDebounce(tc, mb::Middle);
|
PressButtonAndDebounce(tc, mb::Middle, true);
|
||||||
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::idler.IdleSlotIndex(), fromSlot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
|
REQUIRE(VerifyState(tc, mg::FilamentLoadState::InSelector, mi::idler.IdleSlotIndex(), fromSlot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::UnloadingFilament));
|
||||||
REQUIRE(tc.unl.State() == ProgressCode::FeedingToFinda); // MMU must find out where the filament is FS is OFF, FINDA is OFF
|
REQUIRE(tc.unl.State() == ProgressCode::FeedingToFinda); // MMU must find out where the filament is FS is OFF, FINDA is OFF
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ void FindaDidntTriggerResolveHelp(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// In this case we check the first option
|
// In this case we check the first option
|
||||||
|
|
||||||
// Perform press on button 0 + debounce
|
// Perform press on button 0 + debounce
|
||||||
PressButtonAndDebounce(uf, mb::Left);
|
PressButtonAndDebounce(uf, mb::Left, false);
|
||||||
|
|
||||||
// we still think we have filament loaded at this stage
|
// we still think we have filament loaded at this stage
|
||||||
// idler should have been disengaged
|
// idler should have been disengaged
|
||||||
|
|
@ -180,6 +180,8 @@ void FindaDidntTriggerResolveHelp(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// red LED should blink, green LED should be off
|
// red LED should blink, green LED should be off
|
||||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, false, ml::off, ml::blink0, ErrorCode::RUNNING, ProgressCode::ERREngagingIdler));
|
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, false, ml::off, ml::blink0, ErrorCode::RUNNING, ProgressCode::ERREngagingIdler));
|
||||||
|
|
||||||
|
SimulateIdlerHoming(uf);
|
||||||
|
|
||||||
// Stage 4 - engage the idler
|
// Stage 4 - engage the idler
|
||||||
REQUIRE(WhileTopState(uf, ProgressCode::ERREngagingIdler, idlerEngageDisengageMaxSteps));
|
REQUIRE(WhileTopState(uf, ProgressCode::ERREngagingIdler, idlerEngageDisengageMaxSteps));
|
||||||
|
|
||||||
|
|
@ -249,7 +251,7 @@ void FindaDidntTriggerResolveTryAgain(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// - resolve the problem by hand - after pressing the button we shall check, that FINDA is off and we should do what?
|
// - resolve the problem by hand - after pressing the button we shall check, that FINDA is off and we should do what?
|
||||||
|
|
||||||
// In this case we check the second option
|
// In this case we check the second option
|
||||||
PressButtonAndDebounce(uf, mb::Middle);
|
PressButtonAndDebounce(uf, mb::Middle, false);
|
||||||
|
|
||||||
// we still think we have filament loaded at this stage
|
// we still think we have filament loaded at this stage
|
||||||
// idler should have been disengaged
|
// idler should have been disengaged
|
||||||
|
|
@ -296,7 +298,7 @@ void FailedUnloadResolveManual(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
|
|
||||||
// Perform press on button 2 + debounce + switch off FINDA
|
// Perform press on button 2 + debounce + switch off FINDA
|
||||||
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
|
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
|
||||||
PressButtonAndDebounce(uf, mb::Right);
|
PressButtonAndDebounce(uf, mb::Right, false);
|
||||||
|
|
||||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda));
|
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::blink0, ml::off, ErrorCode::RUNNING, ProgressCode::FeedingToFinda));
|
||||||
|
|
||||||
|
|
@ -320,7 +322,7 @@ void FailedUnloadResolveManualFINDAon(uint8_t slot, logic::UnloadFilament &uf) {
|
||||||
// simulate the user fixed the issue himself
|
// simulate the user fixed the issue himself
|
||||||
|
|
||||||
// Perform press on button 2 + debounce + keep FINDA on
|
// Perform press on button 2 + debounce + keep FINDA on
|
||||||
PressButtonAndDebounce(uf, mb::Right);
|
PressButtonAndDebounce(uf, mb::Right, false);
|
||||||
|
|
||||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERRWaitingForUser));
|
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, true, false, ml::off, ml::blink0, ErrorCode::FINDA_DIDNT_SWITCH_OFF, ProgressCode::ERRWaitingForUser));
|
||||||
}
|
}
|
||||||
|
|
@ -329,9 +331,9 @@ void FailedUnloadResolveManualFSensorOn(uint8_t slot, logic::UnloadFilament &uf)
|
||||||
// simulate the user fixed the issue himself
|
// simulate the user fixed the issue himself
|
||||||
|
|
||||||
// Perform press on button 2 + debounce + keep FSensor on
|
// Perform press on button 2 + debounce + keep FSensor on
|
||||||
mfs::fsensor.ProcessMessage(true);
|
SetFSensorStateAndDebounce(true);
|
||||||
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
|
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
|
||||||
PressButtonAndDebounce(uf, mb::Right);
|
PressButtonAndDebounce(uf, mb::Right, false);
|
||||||
|
|
||||||
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_OFF, ProgressCode::ERRWaitingForUser));
|
REQUIRE(VerifyState(uf, mg::FilamentLoadState::InSelector, mi::Idler::IdleSlotIndex(), slot, false, false, ml::off, ml::blink0, ErrorCode::FSENSOR_DIDNT_SWITCH_OFF, ProgressCode::ERRWaitingForUser));
|
||||||
}
|
}
|
||||||
|
|
@ -367,7 +369,7 @@ TEST_CASE("unload_filament::unload_homing_retry", "[unload_filament][homing]") {
|
||||||
|
|
||||||
// simulate the user fixed the issue himself (not really important, we are after a failed homing of the selector)
|
// simulate the user fixed the issue himself (not really important, we are after a failed homing of the selector)
|
||||||
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
|
hal::gpio::WritePin(FINDA_PIN, hal::gpio::Level::low);
|
||||||
PressButtonAndDebounce(uf, mb::Right);
|
PressButtonAndDebounce(uf, mb::Right, false);
|
||||||
SimulateIdlerHoming(uf); // make Idler happy
|
SimulateIdlerHoming(uf); // make Idler happy
|
||||||
|
|
||||||
REQUIRE(WhileCondition(uf, std::bind(SimulateFeedToFINDA, _1, 100), 5000));
|
REQUIRE(WhileCondition(uf, std::bind(SimulateFeedToFINDA, _1, 100), 5000));
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ TEST_CASE("unload_to_finda::regular_unload", "[unload_to_finda]") {
|
||||||
// we need finda ON
|
// we need finda ON
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
// fsensor should be ON
|
// fsensor should be ON
|
||||||
mfs::fsensor.ProcessMessage(true);
|
SetFSensorStateAndDebounce(true);
|
||||||
// and MMU "thinks" it has the filament loaded
|
// and MMU "thinks" it has the filament loaded
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ TEST_CASE("unload_to_finda::unload_without_FINDA_trigger", "[unload_to_finda]")
|
||||||
// we need finda ON
|
// we need finda ON
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
// fsensor should be ON
|
// fsensor should be ON
|
||||||
mfs::fsensor.ProcessMessage(true);
|
SetFSensorStateAndDebounce(true);
|
||||||
// and MMU "thinks" it has the filament loaded
|
// and MMU "thinks" it has the filament loaded
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||||
|
|
||||||
|
|
@ -124,7 +124,7 @@ TEST_CASE("unload_to_finda::unload_without_FSensor_trigger", "[unload_to_finda]"
|
||||||
// we need finda ON
|
// we need finda ON
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
// fsensor should be ON
|
// fsensor should be ON
|
||||||
mfs::fsensor.ProcessMessage(true);
|
SetFSensorStateAndDebounce(true);
|
||||||
// and MMU "thinks" it has the filament loaded
|
// and MMU "thinks" it has the filament loaded
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||||
|
|
||||||
|
|
@ -165,7 +165,7 @@ TEST_CASE("unload_to_finda::unload_repeated", "[unload_to_finda]") {
|
||||||
// we need finda ON
|
// we need finda ON
|
||||||
SetFINDAStateAndDebounce(true);
|
SetFINDAStateAndDebounce(true);
|
||||||
// fsensor should be ON
|
// fsensor should be ON
|
||||||
mfs::fsensor.ProcessMessage(true);
|
SetFSensorStateAndDebounce(true);
|
||||||
// and MMU "thinks" it has the filament loaded
|
// and MMU "thinks" it has the filament loaded
|
||||||
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
mg::globals.SetFilamentLoaded(mg::globals.ActiveSlot(), mg::FilamentLoadState::InNozzle);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,3 +5,4 @@ add_subdirectory(speed_table)
|
||||||
add_subdirectory(pulse_gen)
|
add_subdirectory(pulse_gen)
|
||||||
add_subdirectory(motion)
|
add_subdirectory(motion)
|
||||||
add_subdirectory(timebase)
|
add_subdirectory(timebase)
|
||||||
|
add_subdirectory(user_input)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# define the test executable
|
||||||
|
add_executable(
|
||||||
|
user_input_tests
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/buttons.cpp ${CMAKE_SOURCE_DIR}/src/modules/debouncer.cpp
|
||||||
|
${CMAKE_SOURCE_DIR}/src/modules/user_input.cpp ${MODULES_STUBS_DIR}/stub_adc.cpp
|
||||||
|
${MODULES_STUBS_DIR}/stub_timebase.cpp test_user_input.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# define required search paths
|
||||||
|
target_include_directories(
|
||||||
|
user_input_tests PUBLIC ${CMAKE_SOURCE_DIR}/src/modules ${CMAKE_SOURCE_DIR}/src/hal
|
||||||
|
)
|
||||||
|
|
||||||
|
# tell build system about the test case
|
||||||
|
add_catch_test(user_input_tests)
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
#include "catch2/catch.hpp"
|
||||||
|
#include "../stubs/stub_adc.h"
|
||||||
|
#include "../stubs/stub_timebase.h"
|
||||||
|
#include "buttons.h"
|
||||||
|
#include "../hal/adc.h"
|
||||||
|
#include "user_input.h"
|
||||||
|
|
||||||
|
void PressButtonAndDebounce(uint8_t btnIndex) {
|
||||||
|
hal::adc::SetADC(config::buttonsADCIndex, config::buttonADCLimits[btnIndex][0] + 1);
|
||||||
|
while (!mb::buttons.ButtonPressed(btnIndex)) {
|
||||||
|
mb::buttons.Step();
|
||||||
|
mui::userInput.Step();
|
||||||
|
mt::IncMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("user_input::printer_in_charge", "[user_input]") {
|
||||||
|
uint8_t button;
|
||||||
|
mui::Event event;
|
||||||
|
std::tie(button, event) = GENERATE(
|
||||||
|
std::make_tuple(mb::Left, mui::Event::Left),
|
||||||
|
std::make_tuple(mb::Middle, mui::Event::Middle),
|
||||||
|
std::make_tuple(mb::Right, mui::Event::Right));
|
||||||
|
|
||||||
|
mt::ReinitTimebase();
|
||||||
|
mb::Buttons b;
|
||||||
|
// reset UI
|
||||||
|
new (&mui::userInput) mui::UserInput();
|
||||||
|
REQUIRE_FALSE(mui::userInput.PrinterInCharge());
|
||||||
|
|
||||||
|
// set printer in charge
|
||||||
|
mui::userInput.SetPrinterInCharge(true);
|
||||||
|
REQUIRE(mui::userInput.PrinterInCharge());
|
||||||
|
|
||||||
|
// put some button into the buffer - should be marked as "from printer"
|
||||||
|
mui::userInput.ProcessMessage(button);
|
||||||
|
// i.e. we should NOT be able to extract that message with ConsumeEventForPrinter()
|
||||||
|
REQUIRE(mui::userInput.ConsumeEventForPrinter() == mui::NoEvent);
|
||||||
|
// but we should be able to extract that message with ConsumeEvent()
|
||||||
|
REQUIRE(mui::userInput.ConsumeEvent() == event);
|
||||||
|
|
||||||
|
// press a button on the MMU
|
||||||
|
PressButtonAndDebounce(button);
|
||||||
|
REQUIRE(mb::buttons.ButtonPressed(button));
|
||||||
|
// we should NOT be able to extract the event with ConsumeEvent
|
||||||
|
REQUIRE(mui::userInput.ConsumeEvent() == mui::NoEvent);
|
||||||
|
// but we should be able to extract that message with ConsumeEventForPrinter
|
||||||
|
REQUIRE(mui::userInput.ConsumeEventForPrinter() == event);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("user_input::button_pressed_MMU", "[user_input]") {
|
||||||
|
uint8_t button;
|
||||||
|
mui::Event event;
|
||||||
|
std::tie(button, event) = GENERATE(
|
||||||
|
std::make_tuple(mb::Left, mui::Event::Left),
|
||||||
|
std::make_tuple(mb::Middle, mui::Event::Middle),
|
||||||
|
std::make_tuple(mb::Right, mui::Event::Right));
|
||||||
|
|
||||||
|
// create a button press
|
||||||
|
mt::ReinitTimebase();
|
||||||
|
mb::Buttons b;
|
||||||
|
|
||||||
|
// reset UI
|
||||||
|
new (&mui::userInput) mui::UserInput();
|
||||||
|
REQUIRE_FALSE(mui::userInput.PrinterInCharge());
|
||||||
|
|
||||||
|
PressButtonAndDebounce(button);
|
||||||
|
REQUIRE(mb::buttons.ButtonPressed(button));
|
||||||
|
// we should be able to extract the event with ConsumeEvent
|
||||||
|
REQUIRE(mui::userInput.ConsumeEvent() == event);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue