diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index 260610bc3..0ada3f71e 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -153,27 +153,6 @@ bool MMU2::ReadRegister(uint8_t address) { return true; } -bool MMU2::ReadRegisterInner(uint8_t address) { - if (!WaitForMMUReady()) - return false; - - // Plan a request for the register value at address - logic.ReadRegister(address); - - do { - // Maintain MMU communications - marlin_manage_inactivity(true); - mmu_loop_inner(false); - } while ( - logicStepLastStatus != StepStatus::Finished - && logic.rsp.request.value == address // If the MMU protocol is busy decoding another request, we must wait - ); - - // Update cached value - lastReadRegisterValue = logic.rsp.paramValue; - return true; -} - bool __attribute__((noinline)) MMU2::WriteRegister(uint8_t address, uint16_t data) { if (!WaitForMMUReady()) return false; @@ -840,7 +819,14 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { // the E may have some more moves to finish - wait for them ResumeHotendTemp(); ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved. - logic.ResetRetryAttempts(); // Reset the retry counter. + if (!isErrorScreenSleeping()) + { + // If the error screen is sleeping (running 'Tune' menu) + // then don't reset retry attempts because we this will trigger + // an automatic retry attempt when 'Tune' button is selected. We want the + // error screen to appear once more so the user can hit 'Retry' button manually. + logic.ResetRetryAttempts(); // Reset the retry counter. + } planner_synchronize(); return true; case Interrupted: diff --git a/Firmware/mmu2.h b/Firmware/mmu2.h index 8945f31a5..eb7a0a591 100644 --- a/Firmware/mmu2.h +++ b/Firmware/mmu2.h @@ -88,12 +88,6 @@ public: /// @returns true upon success bool ReadRegister(uint8_t address); - /// Variant of ReadRegister which runs in blocking context such as manage_response() - /// Be careful of using this as it is not recursion protected! - /// @param address Address of register in hexidecimal - /// @return true upon success - bool ReadRegisterInner(uint8_t address); - /// Write from a MMU register (See gcode M708) /// @param address Address of register in hexidecimal /// @param data Data to write to register diff --git a/Firmware/mmu2_reporting.cpp b/Firmware/mmu2_reporting.cpp index 757664e72..330a4a4c6 100644 --- a/Firmware/mmu2_reporting.cpp +++ b/Firmware/mmu2_reporting.cpp @@ -218,11 +218,22 @@ enum ReportErrorHookStates ReportErrorHookState = ReportErrorHookStates::RENDER_ // Helper variable to monitor knob in MMU error screen in blocking functions e.g. manage_response static bool is_mmu_error_monitor_active; +// Helper variable to stop rendering the error screen when the firmware is rendering complementary +// UI to resolve the error screen, for example tuning Idler Stallguard Threshold +// Set to false to allow the error screen to render again. +static bool putErrorScreenToSleep; + bool isErrorScreenRunning() { return is_mmu_error_monitor_active; } +bool isErrorScreenSleeping() { + return putErrorScreenToSleep; +} + void ReportErrorHook(CommandInProgress /*cip*/, uint16_t ec, uint8_t /*es*/) { + if (putErrorScreenToSleep) return; + if (mmu2.MMUCurrentErrorCode() == ErrorCode::OK && mmu2.MMULastErrorSource() == MMU2::ErrorSourceMMU) { // If the error code suddenly changes to OK, that means // a button was pushed on the MMU and the LCD should @@ -361,8 +372,6 @@ void ScreenClear(){ lcd_clear(); } -bool tuningDone = false; - struct TuneItem { uint8_t address; uint8_t minValue; @@ -389,24 +398,28 @@ static_assert(sizeof(menu_data)>= sizeof(_menu_tune_data_t),"_menu_tune_data_t d void tuneIdlerStallguardThresholdMenu() { static constexpr _menu_tune_data_t * const _md = (_menu_tune_data_t*)&(menu_data[0]); + + // Do not timeout the screen, otherwise there will be FW crash (menu recursion) + lcd_timeoutToStatus.stop(); if (_md->status == 0) { _md->status = 1; // Menu entered for the first time - lcd_timeoutToStatus.stop(); // Do not timeout the screen // Fetch the TuneItem from PROGMEM const uint8_t offset = (mmu2.MMUCurrentErrorCode() == ErrorCode::HOMING_IDLER_FAILED) ? 1 : 0; memcpy_P(&(_md->item), &TuneItems[offset], sizeof(TuneItem)); // Fetch the value which is currently in MMU EEPROM - mmu2.ReadRegisterInner((uint8_t)_md->item.address); + mmu2.ReadRegister((uint8_t)_md->item.address); _md->currentValue = mmu2.GetLastReadRegisterValue(); } MENU_BEGIN(); ON_MENU_LEAVE( - tuningDone = true; mmu2.WriteRegister(_md->item.address, (uint16_t)_md->currentValue); + putErrorScreenToSleep = false; + lcd_return_to_status(); + return; ); MENU_ITEM_BACK_P(_i("Done")); MENU_ITEM_EDIT_int3_P( @@ -419,12 +432,8 @@ void tuneIdlerStallguardThresholdMenu() { } void tuneIdlerStallguardThreshold() { - tuningDone = false; - menu_goto(tuneIdlerStallguardThresholdMenu, 0, 0, 0); - while(!tuningDone) { - delay_keep_alive(0); - } - lcd_return_to_status(); + putErrorScreenToSleep = true; + menu_submenu(tuneIdlerStallguardThresholdMenu); } } // namespace MMU2 diff --git a/Firmware/mmu2_reporting.h b/Firmware/mmu2_reporting.h index 0018e032a..55c07c2f3 100644 --- a/Firmware/mmu2_reporting.h +++ b/Firmware/mmu2_reporting.h @@ -25,6 +25,11 @@ void EndReport(CommandInProgress cip, uint16_t ec); /// Return true if the printer's LCD is drawing the error screen bool isErrorScreenRunning(); +/// Return true if the error screen is sleeping in the background +/// Error screen sleeps when the firmware is rendering complementary +/// UI to resolve the error screen, for example tuning Idler Stallguard Threshold +bool isErrorScreenSleeping(); + /// @brief Called when the MMU or MK3S sends operation error (even repeatedly). /// Render MMU error screen on the LCD. This must be non-blocking /// and allow the MMU and printer to communicate with each other.