Merge pull request #4454 from gudnimg/mmu-sync

MMU: Backport code changes from 32-bit firmware
This commit is contained in:
Guðni Már Gilbert 2023-10-23 06:31:06 +00:00 committed by GitHub
commit e7f56118d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 62 additions and 38 deletions

View File

@ -55,7 +55,7 @@ MMU2::MMU2()
void MMU2::Start() { void MMU2::Start() {
mmu2Serial.begin(MMU_BAUD); mmu2Serial.begin(MMU_BAUD);
PowerOn(); // I repurposed this to serve as our EEPROM disable toggle. PowerOn();
mmu2Serial.flush(); // make sure the UART buffer is clear before starting communication mmu2Serial.flush(); // make sure the UART buffer is clear before starting communication
extruder = MMU2_NO_TOOL; extruder = MMU2_NO_TOOL;
@ -63,13 +63,13 @@ void MMU2::Start() {
// start the communication // start the communication
logic.Start(); logic.Start();
logic.ResetRetryAttempts(); logic.ResetRetryAttempts();
logic.ResetCommunicationTimeoutAttempts();
} }
void MMU2::Stop() { void MMU2::Stop() {
StopKeepPowered(); StopKeepPowered();
PowerOff(); // This also disables the MMU in the EEPROM. PowerOff();
} }
void MMU2::StopKeepPowered() { void MMU2::StopKeepPowered() {
@ -125,11 +125,9 @@ void MMU2::TriggerResetPin() {
void MMU2::PowerCycle() { void MMU2::PowerCycle() {
// cut the power to the MMU and after a while restore it // cut the power to the MMU and after a while restore it
// Sadly, MK3/S/+ cannot do this // Sadly, MK3/S/+ cannot do this
// NOTE: the below will toggle the EEPROM var. Should we Stop();
// assert this function is never called in the MK3 FW? Do we even care?
PowerOff();
safe_delay_keep_alive(1000); safe_delay_keep_alive(1000);
PowerOn(); Start();
} }
void MMU2::PowerOff() { void MMU2::PowerOff() {
@ -191,12 +189,7 @@ void MMU2::mmu_loop() {
void __attribute__((noinline)) MMU2::mmu_loop_inner(bool reportErrors) { void __attribute__((noinline)) MMU2::mmu_loop_inner(bool reportErrors) {
logicStepLastStatus = LogicStep(reportErrors); // it looks like the mmu_loop doesn't need to be a blocking call logicStepLastStatus = LogicStep(reportErrors); // it looks like the mmu_loop doesn't need to be a blocking call
CheckErrorScreenUserInput();
if (isErrorScreenRunning()) {
// Call this every iteration to keep the knob rotation responsive
// This includes when mmu_loop is called within manage_response
ReportErrorHook((CommandInProgress)logic.CommandInProgress(), lastErrorCode, uint8_t(lastErrorSource));
}
} }
void MMU2::CheckFINDARunout() { void MMU2::CheckFINDARunout() {
@ -740,7 +733,8 @@ void MMU2::CheckUserInput() {
// ... but mmu2_power.cpp knows this and triggers a soft-reset instead. // ... but mmu2_power.cpp knows this and triggers a soft-reset instead.
break; break;
case Buttons::DisableMMU: case Buttons::DisableMMU:
Stop(); // Poweroff handles updating the EEPROM shutoff. Stop();
DisableMMUInSettings();
break; break;
case Buttons::StopPrint: case Buttons::StopPrint:
// @@TODO not sure if we shall handle this high level operation at this spot // @@TODO not sure if we shall handle this high level operation at this spot
@ -840,45 +834,58 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {
} }
StepStatus MMU2::LogicStep(bool reportErrors) { StepStatus MMU2::LogicStep(bool reportErrors) {
CheckUserInput(); // Process any buttons before proceeding with another MMU Query // Process any buttons before proceeding with another MMU Query
StepStatus ss = logic.Step(); CheckUserInput();
const StepStatus ss = logic.Step();
switch (ss) { switch (ss) {
case Finished: case Finished:
// At this point it is safe to trigger a runout and not interrupt the MMU protocol // At this point it is safe to trigger a runout and not interrupt the MMU protocol
CheckFINDARunout(); CheckFINDARunout();
break; break;
case Processing: case Processing:
OnMMUProgressMsg(logic.Progress()); OnMMUProgressMsg(logic.Progress());
break; break;
case ButtonPushed: case ButtonPushed:
lastButton = logic.Button(); lastButton = logic.Button();
LogEchoEvent_P(PSTR("MMU Button pushed")); LogEchoEvent_P(PSTR("MMU Button pushed"));
CheckUserInput(); // Process the button immediately CheckUserInput(); // Process the button immediately
break; break;
case Interrupted: case Interrupted:
// can be silently handed over to a higher layer, no processing necessary at this spot // can be silently handed over to a higher layer, no processing necessary at this spot
break; break;
default: default:
if (reportErrors) { if (reportErrors) {
switch (ss) { switch (ss) {
case CommandError: case CommandError:
ReportError(logic.Error(), ErrorSourceMMU); ReportError(logic.Error(), ErrorSourceMMU);
break; break;
case CommunicationTimeout: case CommunicationTimeout:
state = xState::Connecting; state = xState::Connecting;
ReportError(ErrorCode::MMU_NOT_RESPONDING, ErrorSourcePrinter); ReportError(ErrorCode::MMU_NOT_RESPONDING, ErrorSourcePrinter);
break; break;
case ProtocolError: case ProtocolError:
state = xState::Connecting; state = xState::Connecting;
ReportError(ErrorCode::PROTOCOL_ERROR, ErrorSourcePrinter); ReportError(ErrorCode::PROTOCOL_ERROR, ErrorSourcePrinter);
break; break;
case VersionMismatch: case VersionMismatch:
StopKeepPowered(); StopKeepPowered();
ReportError(ErrorCode::VERSION_MISMATCH, ErrorSourcePrinter); ReportError(ErrorCode::VERSION_MISMATCH, ErrorSourcePrinter);
break; break;
case PrinterError: case PrinterError:
ReportError(logic.PrinterError(), ErrorSourcePrinter); ReportError(logic.PrinterError(), ErrorSourcePrinter);
break; break;
default: default:
break; break;
} }
@ -888,6 +895,7 @@ StepStatus MMU2::LogicStep(bool reportErrors) {
if (logic.Running()) { if (logic.Running()) {
state = xState::Active; state = xState::Active;
} }
return ss; return ss;
} }

View File

@ -160,9 +160,15 @@ public:
/// @returns Current error code /// @returns Current error code
inline ErrorCode MMUCurrentErrorCode() const { return logic.Error(); } inline ErrorCode MMUCurrentErrorCode() const { return logic.Error(); }
/// @returns Command in progress
inline uint8_t GetCommandInProgress() const { return logic.CommandInProgress(); }
/// @returns Last error source /// @returns Last error source
inline ErrorSource MMULastErrorSource() const { return lastErrorSource; } inline ErrorSource MMULastErrorSource() const { return lastErrorSource; }
/// @returns Last error code
inline ErrorCode GetLastErrorCode() const { return lastErrorCode; }
/// @returns the version of the connected MMU FW. /// @returns the version of the connected MMU FW.
/// In the future we'll return the trully detected FW version /// In the future we'll return the trully detected FW version
Version GetMMUFWVersion() const { Version GetMMUFWVersion() const {

View File

@ -186,20 +186,15 @@ const char * PrusaErrorButtonMore(){
return MSG_BTN_MORE; return MSG_BTN_MORE;
} }
struct ResetOnExit {
ResetOnExit() = default;
~ResetOnExit(){
buttonSelectedOperation = ButtonOperations::NoOperation;
}
};
Buttons ButtonPressed(ErrorCode ec) { Buttons ButtonPressed(ErrorCode ec) {
if (buttonSelectedOperation == ButtonOperations::NoOperation) { if (buttonSelectedOperation == ButtonOperations::NoOperation) {
return Buttons::NoButton; // no button return Buttons::NoButton; // no button
} }
ResetOnExit ros; // clear buttonSelectedOperation on exit from this call const auto result = ButtonAvailable(ec);
return ButtonAvailable(ec); buttonSelectedOperation = ButtonOperations::NoOperation; // Reset operation
return result;
} }
Buttons ButtonAvailable(ErrorCode ec) { Buttons ButtonAvailable(ErrorCode ec) {

View File

@ -4,25 +4,20 @@
#include "fastio.h" #include "fastio.h"
#include <util/delay.h> #include <util/delay.h>
#include "mmu2.h" #include "mmu2.h"
#include "eeprom.h"
namespace MMU2 { namespace MMU2 {
// sadly, on MK3 we cannot do actual power cycle on HW... // On MK3 we cannot do actual power cycle on HW. Instead trigger a hardware reset.
// so we just block the MMU via EEPROM var instead.
void power_on() { void power_on() {
#ifdef MMU_HWRESET #ifdef MMU_HWRESET
WRITE(MMU_RST_PIN, 1); WRITE(MMU_RST_PIN, 1);
SET_OUTPUT(MMU_RST_PIN); // setup reset pin SET_OUTPUT(MMU_RST_PIN); // setup reset pin
#endif //MMU_HWRESET #endif //MMU_HWRESET
eeprom_update_byte((uint8_t *)EEPROM_MMU_ENABLED, true);
reset(); reset();
} }
void power_off() { void power_off() {
eeprom_update_byte((uint8_t *)EEPROM_MMU_ENABLED, false);
} }
void reset() { void reset() {

View File

@ -256,7 +256,7 @@ StepStatus ProtocolLogic::ProcessVersionResponse(uint8_t stage) {
SendVersion(stage); SendVersion(stage);
} }
} else { } else {
dataTO.Reset(); // got a meaningful response from the MMU, stop data layer timeout tracking ResetCommunicationTimeoutAttempts(); // got a meaningful response from the MMU, stop data layer timeout tracking
SendVersion(stage + 1); SendVersion(stage + 1);
} }
} }
@ -774,7 +774,7 @@ void ProtocolLogic::LogResponse() {
StepStatus ProtocolLogic::SuppressShortDropOuts(const char *msg_P, StepStatus ss) { StepStatus ProtocolLogic::SuppressShortDropOuts(const char *msg_P, StepStatus ss) {
if (dataTO.Record(ss)) { if (dataTO.Record(ss)) {
LogError(msg_P); LogError(msg_P);
dataTO.Reset(); // prepare for another run of consecutive retries before firing an error ResetCommunicationTimeoutAttempts(); // prepare for another run of consecutive retries before firing an error
return dataTO.InitialCause(); return dataTO.InitialCause();
} else { } else {
return Processing; // suppress short drop outs of communication return Processing; // suppress short drop outs of communication
@ -865,6 +865,11 @@ void ProtocolLogic::ResetRetryAttempts() {
retryAttempts = MAX_RETRIES; retryAttempts = MAX_RETRIES;
} }
void __attribute__((noinline)) ProtocolLogic::ResetCommunicationTimeoutAttempts() {
SERIAL_ECHOLNPGM("RSTCommTimeout");
dataTO.Reset();
}
bool DropOutFilter::Record(StepStatus ss) { bool DropOutFilter::Record(StepStatus ss) {
if (occurrences == maxOccurrences) { if (occurrences == maxOccurrences) {
cause = ss; cause = ss;

View File

@ -186,6 +186,8 @@ public:
/// Reset the retryAttempts back to the default value /// Reset the retryAttempts back to the default value
void ResetRetryAttempts(); void ResetRetryAttempts();
void ResetCommunicationTimeoutAttempts();
constexpr bool InAutoRetry() const { return inAutoRetry; } constexpr bool InAutoRetry() const { return inAutoRetry; }
void SetInAutoRetry(bool iar) { void SetInAutoRetry(bool iar) {
inAutoRetry = iar; inAutoRetry = iar;

View File

@ -1,4 +1,5 @@
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "eeprom.h"
#include "mmu2.h" #include "mmu2.h"
#include "mmu2_log.h" #include "mmu2_log.h"
#include "mmu2_reporting.h" #include "mmu2_reporting.h"
@ -221,8 +222,12 @@ static bool is_mmu_error_monitor_active;
// Set to false to allow the error screen to render again. // Set to false to allow the error screen to render again.
static bool putErrorScreenToSleep; static bool putErrorScreenToSleep;
bool isErrorScreenRunning() { void CheckErrorScreenUserInput() {
return is_mmu_error_monitor_active; if (is_mmu_error_monitor_active) {
// Call this every iteration to keep the knob rotation responsive
// This includes when mmu_loop is called within manage_response
ReportErrorHook((CommandInProgress)mmu2.GetCommandInProgress(), mmu2.GetLastErrorCode(), mmu2.MMULastErrorSource());
}
} }
bool TuneMenuEntered() { bool TuneMenuEntered() {
@ -336,6 +341,11 @@ void TryLoadUnloadReporter::DumpToSerial(){
MMU2_ECHO_MSGLN(buf); MMU2_ECHO_MSGLN(buf);
} }
/// Disables MMU in EEPROM
void DisableMMUInSettings() {
eeprom_update_byte((uint8_t *)EEPROM_MMU_ENABLED, false);
}
void IncrementLoadFails(){ void IncrementLoadFails(){
eeprom_increment_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL); eeprom_increment_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL);
eeprom_increment_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT); eeprom_increment_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT);

View File

@ -29,8 +29,8 @@ void BeginReport(CommandInProgress cip, ProgressCode ec);
/// Called at the end of every MMU operation /// Called at the end of every MMU operation
void EndReport(CommandInProgress cip, ProgressCode ec); void EndReport(CommandInProgress cip, ProgressCode ec);
/// Return true if the printer's LCD is drawing the error screen /// Checks for error screen user input, if the error screen is open
bool isErrorScreenRunning(); void CheckErrorScreenUserInput();
/// Return true if the error screen is sleeping in the background /// Return true if the error screen is sleeping in the background
/// Error screen sleeps when the firmware is rendering complementary /// Error screen sleeps when the firmware is rendering complementary
@ -81,6 +81,9 @@ bool MMUAvailable();
/// Global Enable/Disable use MMU (to be stored in EEPROM) /// Global Enable/Disable use MMU (to be stored in EEPROM)
bool UseMMU(); bool UseMMU();
/// Disables MMU in EEPROM
void DisableMMUInSettings();
/// Increments EEPROM cell - number of failed loads into the nozzle /// Increments EEPROM cell - number of failed loads into the nozzle
/// Note: technically, this is not an MMU error but an error of the printer. /// Note: technically, this is not an MMU error but an error of the printer.
void IncrementLoadFails(); void IncrementLoadFails();