Add user_input module and use it instead of raw buttons

Encapsulates buttons and commands coming from the communication
pull/37/head
D.R.racer 2021-06-29 08:56:53 +02:00 committed by DRracer
parent af8c866f1a
commit 9a8038ccb6
14 changed files with 122 additions and 25 deletions

View File

@ -204,6 +204,7 @@ target_sources(
src/modules/permanent_storage.cpp src/modules/permanent_storage.cpp
src/modules/selector.cpp src/modules/selector.cpp
src/modules/timebase.cpp src/modules/timebase.cpp
src/modules/user_input.cpp
src/logic/command_base.cpp src/logic/command_base.cpp
src/logic/cut_filament.cpp src/logic/cut_filament.cpp
src/logic/eject_filament.cpp src/logic/eject_filament.cpp

View File

@ -1,5 +1,4 @@
#include "feed_to_finda.h" #include "feed_to_finda.h"
#include "../modules/buttons.h"
#include "../modules/finda.h" #include "../modules/finda.h"
#include "../modules/globals.h" #include "../modules/globals.h"
#include "../modules/idler.h" #include "../modules/idler.h"
@ -7,6 +6,7 @@
#include "../modules/leds.h" #include "../modules/leds.h"
#include "../modules/motion.h" #include "../modules/motion.h"
#include "../modules/permanent_storage.h" #include "../modules/permanent_storage.h"
#include "../modules/user_input.h"
namespace logic { namespace logic {
@ -14,9 +14,9 @@ namespace mm = modules::motion;
namespace mf = modules::finda; namespace mf = modules::finda;
namespace mi = modules::idler; namespace mi = modules::idler;
namespace ml = modules::leds; namespace ml = modules::leds;
namespace mb = modules::buttons;
namespace mg = modules::globals; namespace mg = modules::globals;
namespace ms = modules::selector; namespace ms = modules::selector;
namespace mu = modules::user_input;
void FeedToFinda::Reset(bool feedPhaseLimited) { void FeedToFinda::Reset(bool feedPhaseLimited) {
state = EngagingIdler; state = EngagingIdler;
@ -33,10 +33,11 @@ bool FeedToFinda::Step() {
state = PushingFilament; state = PushingFilament;
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::blink0); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::Color::green, ml::blink0);
mm::motion.PlanMove(feedPhaseLimited ? 1500 : 32767, 0, 0, 4000, 0, 0); //@@TODO constants mm::motion.PlanMove(feedPhaseLimited ? 1500 : 32767, 0, 0, 4000, 0, 0); //@@TODO constants
mu::userInput.Clear(); // remove all buffered events if any just before we wait for some input
} }
return false; return false;
case PushingFilament: { case PushingFilament: {
if (mf::finda.Pressed() || (feedPhaseLimited && mb::buttons.AnyButtonPressed())) { // @@TODO probably also a command from the printer if (mf::finda.Pressed() || (feedPhaseLimited && mu::userInput.AnyEvent())) { // @@TODO probably also a command from the printer
mm::motion.AbortPlannedMoves(); // stop pushing filament mm::motion.AbortPlannedMoves(); // stop pushing filament
// FINDA triggered - that means it works and detected the filament tip // FINDA triggered - that means it works and detected the filament tip
state = UnloadBackToPTFE; state = UnloadBackToPTFE;

View File

@ -1,5 +1,4 @@
#include "load_filament.h" #include "load_filament.h"
#include "../modules/buttons.h"
#include "../modules/finda.h" #include "../modules/finda.h"
#include "../modules/globals.h" #include "../modules/globals.h"
#include "../modules/idler.h" #include "../modules/idler.h"
@ -7,6 +6,7 @@
#include "../modules/motion.h" #include "../modules/motion.h"
#include "../modules/permanent_storage.h" #include "../modules/permanent_storage.h"
#include "../modules/selector.h" #include "../modules/selector.h"
#include "../modules/user_input.h"
namespace logic { namespace logic {
@ -18,6 +18,7 @@ namespace ms = modules::selector;
namespace mf = modules::finda; namespace mf = modules::finda;
namespace ml = modules::leds; namespace ml = modules::leds;
namespace mg = modules::globals; namespace mg = modules::globals;
namespace mu = modules::user_input;
void LoadFilament::Reset(uint8_t param) { void LoadFilament::Reset(uint8_t param) {
state = ProgressCode::EngagingIdler; state = ProgressCode::EngagingIdler;
@ -76,26 +77,28 @@ bool LoadFilament::Step() {
case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA
if (!mi::idler.Engaged()) { if (!mi::idler.Engaged()) {
state = ProgressCode::ERR1WaitingForUser; state = ProgressCode::ERR1WaitingForUser;
mu::userInput.Clear(); // remove all buffered events if any just before we wait for some input
} }
return false; return false;
case ProgressCode::ERR1WaitingForUser: { case ProgressCode::ERR1WaitingForUser: {
// waiting for user buttons and/or a command from the printer // waiting for user buttons and/or a command from the printer
bool help = modules::buttons::buttons.ButtonPressed(modules::buttons::Left) /*|| command_help()*/; mu::Event ev = mu::userInput.ConsumeEvent();
bool tryAgain = modules::buttons::buttons.ButtonPressed(modules::buttons::Middle) /*|| command_tryAgain()*/; switch (ev) {
bool userResolved = modules::buttons::buttons.ButtonPressed(modules::buttons::Right) /*|| command_userResolved()*/; case mu::Event::Left: // try to manually load just a tiny bit - help the filament with the pulley
if (help) {
// try to manually load just a tiny bit - help the filament with the pulley
state = ProgressCode::ERR1EngagingIdler; state = ProgressCode::ERR1EngagingIdler;
mi::idler.Engage(mg::globals.ActiveSlot()); mi::idler.Engage(mg::globals.ActiveSlot());
} else if (tryAgain) { break;
// try again the whole sequence case mu::Event::Middle: // try again the whole sequence
Reset(mg::globals.ActiveSlot()); Reset(mg::globals.ActiveSlot());
} else if (userResolved) { break;
// problem resolved - the user pushed the fillament by hand? case mu::Event::Right: // problem resolved - the user pushed the fillament by hand?
modules::leds::leds.SetMode(mg::globals.ActiveSlot(), modules::leds::red, modules::leds::off); modules::leds::leds.SetMode(mg::globals.ActiveSlot(), modules::leds::red, modules::leds::off);
modules::leds::leds.SetMode(mg::globals.ActiveSlot(), modules::leds::green, modules::leds::on); modules::leds::leds.SetMode(mg::globals.ActiveSlot(), modules::leds::green, modules::leds::on);
// mm::motion.PlanMove(mm::Pulley, 450, 5000); // @@TODO constants // mm::motion.PlanMove(mm::Pulley, 450, 5000); // @@TODO constants
state = ProgressCode::AvoidingGrind; state = ProgressCode::AvoidingGrind;
break;
default: // no event, continue waiting for user input
break;
} }
return false; return false;
} }

View File

@ -1,22 +1,22 @@
#include "unload_filament.h" #include "unload_filament.h"
#include "../modules/buttons.h"
#include "../modules/finda.h" #include "../modules/finda.h"
#include "../modules/globals.h" #include "../modules/globals.h"
#include "../modules/idler.h" #include "../modules/idler.h"
#include "../modules/leds.h" #include "../modules/leds.h"
#include "../modules/motion.h" #include "../modules/motion.h"
#include "../modules/permanent_storage.h" #include "../modules/permanent_storage.h"
#include "../modules/user_input.h"
namespace logic { namespace logic {
UnloadFilament unloadFilament; UnloadFilament unloadFilament;
namespace mb = modules::buttons;
namespace mm = modules::motion; namespace mm = modules::motion;
namespace mf = modules::finda; namespace mf = modules::finda;
namespace mi = modules::idler; namespace mi = modules::idler;
namespace ml = modules::leds; namespace ml = modules::leds;
namespace mg = modules::globals; namespace mg = modules::globals;
namespace mu = modules::user_input;
void UnloadFilament::Reset(uint8_t /*param*/) { void UnloadFilament::Reset(uint8_t /*param*/) {
// unloads filament from extruder - filament is above Bondtech gears // unloads filament from extruder - filament is above Bondtech gears
@ -71,26 +71,28 @@ bool UnloadFilament::Step() {
case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA case ProgressCode::ERR1DisengagingIdler: // couldn't unload to FINDA
if (!mi::idler.Engaged()) { if (!mi::idler.Engaged()) {
state = ProgressCode::ERR1WaitingForUser; state = ProgressCode::ERR1WaitingForUser;
mu::userInput.Clear(); // remove all buffered events if any just before we wait for some input
} }
return false; return false;
case ProgressCode::ERR1WaitingForUser: { case ProgressCode::ERR1WaitingForUser: {
// waiting for user buttons and/or a command from the printer // waiting for user buttons and/or a command from the printer
bool help = mb::buttons.ButtonPressed(mb::Left) /*|| command_help()*/; mu::Event ev = mu::userInput.ConsumeEvent();
bool tryAgain = mb::buttons.ButtonPressed(mb::Middle) /*|| command_tryAgain()*/; switch (ev) {
bool userResolved = mb::buttons.ButtonPressed(mb::Right) /*|| command_userResolved()*/; case mu::Event::Left: // try to manually unload just a tiny bit - help the filament with the pulley
if (help) {
// try to manually unload just a tiny bit - help the filament with the pulley
state = ProgressCode::ERR1EngagingIdler; state = ProgressCode::ERR1EngagingIdler;
mi::idler.Engage(mg::globals.ActiveSlot()); mi::idler.Engage(mg::globals.ActiveSlot());
} else if (tryAgain) { break;
// try again the whole sequence case mu::Event::Middle: // try again the whole sequence
Reset(0); //@@TODO validate the reset parameter Reset(0); //@@TODO validate the reset parameter
} else if (userResolved) { break;
// problem resolved - the user pulled the fillament by hand case mu::Event::Right: // problem resolved - the user pulled the fillament by hand
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::off); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::red, ml::off);
ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::on); ml::leds.SetMode(mg::globals.ActiveSlot(), ml::green, ml::on);
// mm::motion.PlanMove(mm::Pulley, 450, 5000); // @@TODO constants // mm::motion.PlanMove(mm::Pulley, 450, 5000); // @@TODO constants
state = ProgressCode::AvoidingGrind; state = ProgressCode::AvoidingGrind;
break;
default:
break;
} }
return false; return false;
} }

View File

@ -1,5 +1,4 @@
#include "unload_to_finda.h" #include "unload_to_finda.h"
#include "../modules/buttons.h"
#include "../modules/finda.h" #include "../modules/finda.h"
#include "../modules/globals.h" #include "../modules/globals.h"
#include "../modules/idler.h" #include "../modules/idler.h"

View File

@ -17,6 +17,7 @@
#include "modules/leds.h" #include "modules/leds.h"
#include "modules/protocol.h" #include "modules/protocol.h"
#include "modules/selector.h" #include "modules/selector.h"
#include "modules/user_input.h"
#include "logic/command_base.h" #include "logic/command_base.h"
#include "logic/cut_filament.h" #include "logic/cut_filament.h"
@ -34,6 +35,7 @@ namespace mi = modules::idler;
namespace ml = modules::leds; namespace ml = modules::leds;
namespace ms = modules::selector; namespace ms = modules::selector;
namespace mg = modules::globals; namespace mg = modules::globals;
namespace mu = modules::user_input;
namespace hu = hal::usart; namespace hu = hal::usart;
@ -193,6 +195,7 @@ void ProcessRequestMsg(const mp::RequestMsg &rq) {
switch (rq.code) { switch (rq.code) {
case mp::RequestMsgCodes::Button: case mp::RequestMsgCodes::Button:
// behave just like if the user pressed a button // behave just like if the user pressed a button
mu::userInput.ProcessMessage(rq.value);
break; break;
case mp::RequestMsgCodes::Finda: case mp::RequestMsgCodes::Finda:
// immediately report FINDA status // immediately report FINDA status

View File

@ -0,0 +1,38 @@
#include "user_input.h"
#include "buttons.h"
namespace modules {
namespace user_input {
UserInput userInput;
void UserInput::Step() {
if (buttons::buttons.ButtonPressed(0))
eventQueue.push_back(Event::Left);
if (buttons::buttons.ButtonPressed(1))
eventQueue.push_back(Event::Middle);
if (buttons::buttons.ButtonPressed(2))
eventQueue.push_back(Event::Right);
}
void UserInput::ProcessMessage(uint8_t ev) {
eventQueue.push_back((Event)ev);
}
Event UserInput::ConsumeEvent() {
if (eventQueue.IsEmpty())
return Event::NoEvent;
Event rv;
eventQueue.ConsumeFirst(rv);
return rv;
}
void UserInput::Clear() {
while (eventQueue.IsEmpty()) {
Event x;
eventQueue.ConsumeFirst(x);
}
}
} // namespace user_input
} // namespace modules

44
src/modules/user_input.h Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include <stdint.h>
#include "../hal/circle_buffer.hpp"
namespace modules {
/// User input module collects input from buttons and from communication for the logic layer
namespace user_input {
enum class Event : int8_t {
NoEvent = -1,
Left = 0,
Middle = 1,
Right = 2
};
class UserInput {
public:
UserInput() = default;
/// collects the buttons' state and enqueues the corresponding event
void Step();
/// enqueues a user event coming from a communication
void ProcessMessage(uint8_t ev);
/// dequeues the most recent event from the queue for processing
Event ConsumeEvent();
/// @returns true if there is at least one event in the event queue
bool AnyEvent() const { return !eventQueue.IsEmpty(); }
/// Remove all buffered events from the event queue
void Clear();
private:
CircleBuffer<Event, 4> eventQueue;
};
extern UserInput userInput;
} // namespace user_input
} // namespace modules

View File

@ -14,6 +14,7 @@ add_executable(
../../../../src/modules/leds.cpp ../../../../src/modules/leds.cpp
../../../../src/modules/permanent_storage.cpp ../../../../src/modules/permanent_storage.cpp
../../../../src/modules/selector.cpp ../../../../src/modules/selector.cpp
../../../../src/modules/user_input.cpp
../../modules/stubs/stub_adc.cpp ../../modules/stubs/stub_adc.cpp
../../modules/stubs/stub_eeprom.cpp ../../modules/stubs/stub_eeprom.cpp
../../modules/stubs/stub_shr16.cpp ../../modules/stubs/stub_shr16.cpp

View File

@ -14,6 +14,7 @@ add_executable(
../../../../src/modules/leds.cpp ../../../../src/modules/leds.cpp
../../../../src/modules/permanent_storage.cpp ../../../../src/modules/permanent_storage.cpp
../../../../src/modules/selector.cpp ../../../../src/modules/selector.cpp
../../../../src/modules/user_input.cpp
../../modules/stubs/stub_adc.cpp ../../modules/stubs/stub_adc.cpp
../../modules/stubs/stub_eeprom.cpp ../../modules/stubs/stub_eeprom.cpp
../../modules/stubs/stub_shr16.cpp ../../modules/stubs/stub_shr16.cpp

View File

@ -11,6 +11,7 @@ add_executable(
../../../../src/modules/leds.cpp ../../../../src/modules/leds.cpp
../../../../src/modules/permanent_storage.cpp ../../../../src/modules/permanent_storage.cpp
../../../../src/modules/selector.cpp ../../../../src/modules/selector.cpp
../../../../src/modules/user_input.cpp
../../modules/stubs/stub_adc.cpp ../../modules/stubs/stub_adc.cpp
../../modules/stubs/stub_eeprom.cpp ../../modules/stubs/stub_eeprom.cpp
../../modules/stubs/stub_shr16.cpp ../../modules/stubs/stub_shr16.cpp

View File

@ -13,6 +13,7 @@ add_executable(
../../../../src/modules/leds.cpp ../../../../src/modules/leds.cpp
../../../../src/modules/permanent_storage.cpp ../../../../src/modules/permanent_storage.cpp
../../../../src/modules/selector.cpp ../../../../src/modules/selector.cpp
../../../../src/modules/user_input.cpp
../../modules/stubs/stub_adc.cpp ../../modules/stubs/stub_adc.cpp
../../modules/stubs/stub_eeprom.cpp ../../modules/stubs/stub_eeprom.cpp
../../modules/stubs/stub_shr16.cpp ../../modules/stubs/stub_shr16.cpp

View File

@ -16,6 +16,7 @@ add_executable(
../../../../src/modules/leds.cpp ../../../../src/modules/leds.cpp
../../../../src/modules/permanent_storage.cpp ../../../../src/modules/permanent_storage.cpp
../../../../src/modules/selector.cpp ../../../../src/modules/selector.cpp
../../../../src/modules/user_input.cpp
../../modules/stubs/stub_adc.cpp ../../modules/stubs/stub_adc.cpp
../../modules/stubs/stub_eeprom.cpp ../../modules/stubs/stub_eeprom.cpp
../../modules/stubs/stub_shr16.cpp ../../modules/stubs/stub_shr16.cpp

View File

@ -13,6 +13,7 @@ add_executable(
../../../../src/modules/leds.cpp ../../../../src/modules/leds.cpp
../../../../src/modules/permanent_storage.cpp ../../../../src/modules/permanent_storage.cpp
../../../../src/modules/selector.cpp ../../../../src/modules/selector.cpp
../../../../src/modules/user_input.cpp
../../modules/stubs/stub_adc.cpp ../../modules/stubs/stub_adc.cpp
../../modules/stubs/stub_eeprom.cpp ../../modules/stubs/stub_eeprom.cpp
../../modules/stubs/stub_shr16.cpp ../../modules/stubs/stub_shr16.cpp