From 592fc56bfcb9447e43a906423a7fc8b560feccb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Thu, 28 Mar 2024 23:15:35 +0000 Subject: [PATCH 1/6] MMU: Sync code with 32-bit The changes in this commit are mainly formatting But there are some changes like adding a new function planner_draining() --- Firmware/mmu2.cpp | 120 ++++++++++++++++++------------ Firmware/mmu2.h | 25 ++++--- Firmware/mmu2_error_converter.cpp | 97 ++++++++++++++---------- Firmware/mmu2_log.h | 4 +- Firmware/mmu2_marlin.h | 1 + Firmware/mmu2_marlin1.cpp | 46 +++++++----- Firmware/mmu2_protocol.cpp | 9 +-- Firmware/mmu2_protocol.h | 13 +--- Firmware/mmu2_protocol_logic.cpp | 40 +++++----- Firmware/mmu2_protocol_logic.h | 44 +++++------ Firmware/mmu2_state.h | 7 +- 11 files changed, 231 insertions(+), 175 deletions(-) diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index 10c3643593..1622fcf0fc 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -34,7 +34,7 @@ void waitForHotendTargetTemp(uint16_t delay, F f) { } void WaitForHotendTargetTempBeep() { - waitForHotendTargetTemp(3000, []{ }); + waitForHotendTargetTemp(200, [] {}); MakeSound(Prompt); } @@ -73,14 +73,17 @@ void MMU2::Start() { mmu2Serial.flush(); // make sure the UART buffer is clear before starting communication SetCurrentTool(MMU2_NO_TOOL); - state = xState::Connecting; // start the communication - logic.Start(); logic.ResetRetryAttempts(); logic.ResetCommunicationTimeoutAttempts(); + + state = xState::Connecting; + logic.Start(); } +MMU2::~MMU2() {} + void MMU2::Stop() { StopKeepPowered(); PowerOff(); @@ -153,8 +156,9 @@ void MMU2::PowerOn() { } bool MMU2::ReadRegister(uint8_t address) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } do { logic.ReadRegister(address); // we may signal the accepted/rejected status of the response as return value of this function } while (!manage_response(false, false)); @@ -165,8 +169,9 @@ bool MMU2::ReadRegister(uint8_t address) { } bool __attribute__((noinline)) MMU2::WriteRegister(uint8_t address, uint16_t data) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } // special cases - intercept requests of registers which influence the printer's behaviour too + perform the change even on the printer's side switch (address) { @@ -192,12 +197,11 @@ void MMU2::mmu_loop() { // Atomic compare_exchange would have been the most appropriate solution here, but this gets called only in Marlin's task, // so thread safety should be kept static bool avoidRecursion = false; - if (avoidRecursion) + if (avoidRecursion) { return; + } avoidRecursion = true; - mmu_loop_inner(true); - avoidRecursion = false; } @@ -208,7 +212,7 @@ void __attribute__((noinline)) MMU2::mmu_loop_inner(bool reportErrors) { void MMU2::CheckFINDARunout() { // Check for FINDA filament runout - if (!FindaDetectsFilament() && check_fsensor()) { + if (!FindaDetectsFilament() && check_fsensor()) { // Check if we have filament runout detected from sensors SERIAL_ECHOLNPGM("FINDA filament runout!"); marlin_stop_and_save_print_to_ram(); restore_print_from_ram_and_continue(0); @@ -301,8 +305,12 @@ bool MMU2::VerifyFilamentEnteredPTFE() { filament_inserted = filament_inserted && (WhereIsFilament() == FilamentState::AT_FSENSOR); tlur.Progress(filament_inserted); safe_delay_keep_alive(0); + if (planner_draining()) { + return false; // power panic or a similar issue happened, bail out fast + } } } + Disable_E0(); if (!filament_inserted) { IncrementLoadFails(); @@ -318,8 +326,9 @@ bool MMU2::ToolChangeCommonOnce(uint8_t slot) { Disable_E0(); // it may seem counterintuitive to disable the E-motor, but it gets enabled in the planner whenever the E-motor is to move tool_change_extruder = slot; logic.ToolChange(slot); // let the MMU pull the filament out and push a new one in - if (manage_response(true, true)) + if (manage_response(true, true)) { break; + } // otherwise: failed to perform the command - unload first and then let it run again IncrementMMUFails(); @@ -335,7 +344,7 @@ bool MMU2::ToolChangeCommonOnce(uint8_t slot) { } if (VerifyFilamentEnteredPTFE()) { return true; // success - } else { // Prepare a retry attempt + } else { // Prepare a retry attempt UnloadInner(); if (retries == 2 && cutter_enabled()) { CutFilamentInner(slot); // try cutting filament tip at the last attempt @@ -347,6 +356,9 @@ bool MMU2::ToolChangeCommonOnce(uint8_t slot) { void MMU2::ToolChangeCommon(uint8_t slot) { while (!ToolChangeCommonOnce(slot)) { // while not successfully fed into extruder's PTFE tube + if (planner_draining()) { + return; // power panic happening, pretend the G-code finished ok + } // failed autoretry, report an error by forcing a "printer" error into the MMU infrastructure - it is a hack to leverage existing code // @@TODO theoretically logic layer may not need to be spoiled with the printer error - may be just the manage_response needs it... logic.SetPrinterError(ErrorCode::LOAD_TO_EXTRUDER_FAILED); @@ -357,15 +369,16 @@ void MMU2::ToolChangeCommon(uint8_t slot) { static_cast(manage_response(true, true)); // yes, I'd like to silence [[nodiscard]] warning at this spot by casting to void } - SetCurrentTool(slot); //filament change is finished + SetCurrentTool(slot); // filament change is finished SpoolJoin::spooljoin.setSlot(slot); ++toolchange_counter; } bool MMU2::tool_change(uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } if (slot != extruder) { if (/*FindaDetectsFilament()*/ @@ -390,8 +403,9 @@ bool MMU2::tool_change(uint8_t slot) { ///- Tx Same as T?, except nozzle doesn't have to be preheated. Tc must be placed after extruder nozzle is preheated to finish filament load. ///- Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated. bool MMU2::tool_change(char code, uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } FSensorBlockRunout blockRunout; @@ -435,8 +449,9 @@ void MMU2::SetCurrentTool(uint8_t ex){ } bool MMU2::set_filament_type(uint8_t /*slot*/, uint8_t /*type*/) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } // @@TODO - this is not supported in the new MMU yet // slot = slot; // @@TODO @@ -461,8 +476,9 @@ void MMU2::UnloadInner() { for (;;) { Disable_E0(); logic.UnloadFilament(); - if (manage_response(false, true)) + if (manage_response(false, true)) { break; + } IncrementMMUFails(); } MakeSound(Confirm); @@ -473,15 +489,16 @@ void MMU2::UnloadInner() { } bool MMU2::unload() { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; - - WaitForHotendTargetTempBeep(); + } { ReportingRAII rep(CommandInProgress::UnloadFilament); + WaitForHotendTargetTempBeep(); UnloadInner(); } + ScreenUpdateEnable(); return true; } @@ -490,15 +507,17 @@ void MMU2::CutFilamentInner(uint8_t slot) { for (;;) { Disable_E0(); logic.CutFilament(slot); - if (manage_response(false, true)) + if (manage_response(false, true)) { break; + } IncrementMMUFails(); } } bool MMU2::cut_filament(uint8_t slot, bool enableFullScreenMsg /*= true*/) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } if (enableFullScreenMsg) { FullScreenMsgCut(slot); @@ -528,8 +547,9 @@ bool MMU2::loading_test(uint8_t slot) { } bool MMU2::load_filament(uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } FullScreenMsgLoad(slot); { @@ -537,8 +557,9 @@ bool MMU2::load_filament(uint8_t slot) { for (;;) { Disable_E0(); logic.LoadFilament(slot); - if (manage_response(false, false)) + if (manage_response(false, false)) { break; + } IncrementMMUFails(); } MakeSound(SoundType::Confirm); @@ -548,10 +569,9 @@ bool MMU2::load_filament(uint8_t slot) { } bool MMU2::load_filament_to_nozzle(uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; - - WaitForHotendTargetTempBeep(); + } FullScreenMsgLoad(slot); { @@ -559,6 +579,8 @@ bool MMU2::load_filament_to_nozzle(uint8_t slot) { ReportingRAII rep(CommandInProgress::ToolChange); FSensorBlockRunout blockRunout; + WaitForHotendTargetTempBeep(); + if (extruder != MMU2_NO_TOOL) { // we already have some filament loaded - free it + shape its tip properly filament_ramming(); } @@ -574,8 +596,9 @@ bool MMU2::load_filament_to_nozzle(uint8_t slot) { } bool MMU2::eject_filament(uint8_t slot, bool enableFullScreenMsg /* = true */) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } if (enableFullScreenMsg) { FullScreenMsgEject(slot); @@ -589,8 +612,9 @@ bool MMU2::eject_filament(uint8_t slot, bool enableFullScreenMsg /* = true */) { for (;;) { Disable_E0(); logic.EjectFilament(slot); - if (manage_response(false, true)) + if (manage_response(false, true)) { break; + } IncrementMMUFails(); } SetCurrentTool(MMU2_NO_TOOL); @@ -611,8 +635,9 @@ void MMU2::Home(uint8_t mode) { } void MMU2::SaveHotendTemp(bool turn_off_nozzle) { - if (mmu_print_saved & SavedState::Cooldown) + if (mmu_print_saved & SavedState::Cooldown) { return; + } if (turn_off_nozzle && !(mmu_print_saved & SavedState::CooldownPending)) { Disable_E0(); @@ -701,8 +726,7 @@ void MMU2::CheckUserInput() { lastButton = Buttons::NoButton; // Clear it. } - if (mmu2.MMULastErrorSource() == MMU2::ErrorSourcePrinter && btn != Buttons::NoButton) - { + if (mmu2.MMULastErrorSource() == ErrorSourcePrinter && btn != Buttons::NoButton) { // When the printer has raised an error screen, and a button was selected // the error screen should always be dismissed. ClearPrinterError(); @@ -720,7 +744,7 @@ void MMU2::CheckUserInput() { SERIAL_ECHOLN((int)buttons_to_uint8t(btn)); ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else... - if (mmu2.MMULastErrorSource() == MMU2::ErrorSourceMMU) { + if (mmu2.MMULastErrorSource() == ErrorSourceMMU) { // Do not send a button to the MMU unless the MMU is in error state Button(buttons_to_uint8t(btn)); } @@ -782,6 +806,7 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { // - failed -> then do the safety moves on the printer like before // - finished ok -> proceed with reading other commands safe_delay_keep_alive(0); // calls LogicStep() and remembers its return status + // also disables stepper motor unlocking if (mmu_print_saved & SavedState::CooldownPending) { if (!nozzleTimeout.running()) { @@ -803,9 +828,8 @@ bool MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { // command/operation completed, let Marlin continue its work // 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. - if (!TuneMenuEntered()) - { + ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved. + if (!TuneMenuEntered()) { // 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 @@ -860,7 +884,7 @@ StepStatus MMU2::LogicStep(bool reportErrors) { case Finished: // At this point it is safe to trigger a runout and not interrupt the MMU protocol CheckFINDARunout(); - break; + [[fallthrough]]; // let Finished be reported the same way like Processing case Processing: OnMMUProgressMsg(logic.Progress()); @@ -920,15 +944,17 @@ void MMU2::filament_ramming() { execute_extruder_sequence(ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step)); } -void MMU2::execute_extruder_sequence(const E_Step *sequence, uint8_t steps) { +void MMU2::execute_extruder_sequence(const E_Step *sequence, uint8_t stepCount) { planner_synchronize(); - const E_Step *step = sequence; - for (uint8_t i = steps; i > 0; --i) { + // Plan the moves + for (const E_Step *step = sequence, *end = sequence + stepCount; step != end; step++) { extruder_move(pgm_read_float(&(step->extrude)), pgm_read_float(&(step->feedRate))); - step++; } - planner_synchronize(); // it looks like it's better to sync the moves at the end - smoother move (if the sequence is not too long). + + // Wait for the moves to finish + // it looks like it's better to sync the moves at the end - smoother move (if the sequence is not too long). + planner_synchronize(); Disable_E0(); } @@ -1031,7 +1057,7 @@ void MMU2::OnMMUProgressMsgChanged(ProgressCode pc) { switch (pc) { case ProgressCode::UnloadingToFinda: if ((CommandInProgress)logic.CommandInProgress() == CommandInProgress::UnloadFilament - || ((CommandInProgress)logic.CommandInProgress() == CommandInProgress::ToolChange)) { + || ((CommandInProgress)logic.CommandInProgress() == CommandInProgress::ToolChange)) { // If MK3S sent U0 command, ramming sequence takes care of releasing the filament. // If Toolchange is done while printing, PrusaSlicer takes care of releasing the filament // If printing is not in progress, ToolChange will issue a U0 command. @@ -1079,14 +1105,10 @@ void MMU2::OnMMUProgressMsgSame(ProgressCode pc) { case FilamentState::AT_FSENSOR: // fsensor triggered, finish FeedingToExtruder state loadFilamentStarted = false; - - // Abort any excess E-move from the planner queue planner_abort_queued_moves(); - - // After the MMU knows the FSENSOR is triggered it will: - // 1. Push the filament by additional 30mm (see fsensorToNozzle) - // 2. Disengage the idler and push another 2mm. - extruder_move(logic.ExtraLoadDistance() + 2, logic.PulleySlowFeedRate()); + { + extruder_move(logic.ExtraLoadDistance() + 2, logic.PulleySlowFeedRate()); + } break; case FilamentState::NOT_PRESENT: // fsensor not triggered, continue moving extruder diff --git a/Firmware/mmu2.h b/Firmware/mmu2.h index a39267c16d..bc06043932 100644 --- a/Firmware/mmu2.h +++ b/Firmware/mmu2.h @@ -11,6 +11,7 @@ typedef float feedRate_t; #else #include "protocol_logic.h" #include + #include #endif struct E_Step; @@ -32,6 +33,7 @@ struct Version { class MMU2 { public: MMU2(); + ~MMU2(); /// Powers ON the MMU, then initializes the UART and protocol logic void Start(); @@ -48,17 +50,17 @@ class MMU2 { /// Different levels of resetting the MMU enum ResetForm : uint8_t { - Software = 0, ///< sends a X0 command into the MMU, the MMU will watchdog-reset itself - ResetPin = 1, ///< trigger the reset pin of the MMU - CutThePower = 2, ///< power off and power on (that includes +5V and +24V power lines) + Software = 0, ///< sends a X0 command into the MMU, the MMU will watchdog-reset itself + ResetPin = 1, ///< trigger the reset pin of the MMU + CutThePower = 2, ///< power off and power on (that includes +5V and +24V power lines) EraseEEPROM = 42, ///< erase MMU EEPROM and then perform a software reset }; /// Saved print state on error. enum SavedState : uint8_t { - None = 0, // No state saved. + None = 0, // No state saved. ParkExtruder = 1, // The extruder was parked. - Cooldown = 2, // The extruder was allowed to cool. + Cooldown = 2, // The extruder was allowed to cool. CooldownPending = 4, }; @@ -207,9 +209,9 @@ class MMU2 { }; inline void InvokeErrorScreen(ErrorCode ec) { // The printer may not raise an error when the MMU is busy - if (!logic.CommandInProgress() // MMU must not be busy + if (!logic.CommandInProgress() // MMU must not be busy && MMUCurrentErrorCode() == ErrorCode::OK // The protocol must not be in error state - && lastErrorCode != ec) // The error code is not a duplicate + && lastErrorCode != ec) // The error code is not a duplicate { ReportError(ec, ErrorSource::ErrorSourcePrinter); } @@ -273,7 +275,9 @@ class MMU2 { StepStatus LogicStep(bool reportErrors); void filament_ramming(); - void execute_extruder_sequence(const E_Step *sequence, uint8_t steps); + + void execute_extruder_sequence(const E_Step *sequence, uint8_t stepCount); + void execute_load_to_nozzle_sequence(); /// Reports an error into attached ExtUIs @@ -342,8 +346,9 @@ class MMU2 { void SetCurrentTool(uint8_t ex); - ProtocolLogic logic; ///< implementation of the protocol logic layer - uint8_t extruder; ///< currently active slot in the MMU ... somewhat... not sure where to get it from yet + ProtocolLogic logic; ///< implementation of the protocol logic layer + + uint8_t extruder; ///< currently active slot in the MMU ... somewhat... not sure where to get it from yet uint8_t tool_change_extruder; ///< only used for UI purposes pos3d resume_position; diff --git a/Firmware/mmu2_error_converter.cpp b/Firmware/mmu2_error_converter.cpp index b5fe89ac87..edfe277083 100644 --- a/Firmware/mmu2_error_converter.cpp +++ b/Firmware/mmu2_error_converter.cpp @@ -29,17 +29,17 @@ static constexpr uint8_t FindErrorIndex(uint16_t pec) { return (i != errorCodesEnd) ? (i-errorCodes) : (errorCodesSize - 1); } -// check that the searching algoritm works -static_assert( FindErrorIndex(ERR_MECHANICAL_FINDA_DIDNT_TRIGGER) == 0); -static_assert( FindErrorIndex(ERR_MECHANICAL_FINDA_FILAMENT_STUCK) == 1); -static_assert( FindErrorIndex(ERR_MECHANICAL_FSENSOR_DIDNT_TRIGGER) == 2); -static_assert( FindErrorIndex(ERR_MECHANICAL_FSENSOR_FILAMENT_STUCK) == 3); +// check that the searching algorithm works +static_assert(FindErrorIndex(ERR_MECHANICAL_FINDA_DIDNT_TRIGGER) == 0); +static_assert(FindErrorIndex(ERR_MECHANICAL_FINDA_FILAMENT_STUCK) == 1); +static_assert(FindErrorIndex(ERR_MECHANICAL_FSENSOR_DIDNT_TRIGGER) == 2); +static_assert(FindErrorIndex(ERR_MECHANICAL_FSENSOR_FILAMENT_STUCK) == 3); -constexpr ErrorCode operator&(ErrorCode a, ErrorCode b){ +constexpr ErrorCode operator&(ErrorCode a, ErrorCode b) { return (ErrorCode)((uint16_t)a & (uint16_t)b); } -constexpr bool ContainsBit(ErrorCode ec, ErrorCode mask){ +constexpr bool ContainsBit(ErrorCode ec, ErrorCode mask) { return (uint16_t)ec & (uint16_t)mask; } @@ -96,93 +96,115 @@ uint8_t PrusaErrorCodeIndex(ErrorCode ec) { return FindErrorIndex(ERR_SYSTEM_UNLOAD_MANUALLY); case ErrorCode::MCU_UNDERVOLTAGE_VCC: return FindErrorIndex(ERR_ELECTRICAL_MMU_MCU_ERROR); - default: break; + default: + break; } // Electrical issues which can be detected somehow. // Need to be placed before TMC-related errors in order to process couples of error bits between single ones // and to keep the code size down. if (ContainsBit(ec, ErrorCode::TMC_PULLEY_BIT)) { - if ((ec & ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) == ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) + if ((ec & ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) == ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) { return FindErrorIndex(ERR_ELECTRICAL_MMU_PULLEY_SELFTEST_FAILED); + } } else if (ContainsBit(ec, ErrorCode::TMC_SELECTOR_BIT)) { - if ((ec & ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) == ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) + if ((ec & ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) == ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) { return FindErrorIndex(ERR_ELECTRICAL_MMU_SELECTOR_SELFTEST_FAILED); + } } else if (ContainsBit(ec, ErrorCode::TMC_IDLER_BIT)) { - if ((ec & ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) == ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) + if ((ec & ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) == ErrorCode::MMU_SOLDERING_NEEDS_ATTENTION) { return FindErrorIndex(ERR_ELECTRICAL_MMU_IDLER_SELFTEST_FAILED); + } } // TMC-related errors - multiple of these can occur at once // - in such a case we report the first which gets found/converted into Prusa-Error-Codes (usually the fact, that one TMC has an issue is serious enough) // By carefully ordering the checks here we can prioritize the errors being reported to the user. if (ContainsBit(ec, ErrorCode::TMC_PULLEY_BIT)) { - if (ContainsBit(ec, ErrorCode::TMC_IOIN_MISMATCH)) + if (ContainsBit(ec, ErrorCode::TMC_IOIN_MISMATCH)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_PULLEY_DRIVER_ERROR); - if (ContainsBit(ec, ErrorCode::TMC_RESET)) + } + if (ContainsBit(ec, ErrorCode::TMC_RESET)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_PULLEY_DRIVER_RESET); - if (ContainsBit(ec, ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)) + } + if (ContainsBit(ec, ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_PULLEY_UNDERVOLTAGE_ERROR); - if (ContainsBit(ec, ErrorCode::TMC_SHORT_TO_GROUND)) + } + if (ContainsBit(ec, ErrorCode::TMC_SHORT_TO_GROUND)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_PULLEY_DRIVER_SHORTED); - if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_WARN)) + } + if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_WARN)) { return FindErrorIndex(ERR_TEMPERATURE_WARNING_TMC_PULLEY_TOO_HOT); - if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_ERROR)) + } + if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_ERROR)) { return FindErrorIndex(ERR_TEMPERATURE_TMC_PULLEY_OVERHEAT_ERROR); + } } else if (ContainsBit(ec, ErrorCode::TMC_SELECTOR_BIT)) { - if (ContainsBit(ec, ErrorCode::TMC_IOIN_MISMATCH)) + if (ContainsBit(ec, ErrorCode::TMC_IOIN_MISMATCH)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_SELECTOR_DRIVER_ERROR); - if (ContainsBit(ec, ErrorCode::TMC_RESET)) + } + if (ContainsBit(ec, ErrorCode::TMC_RESET)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_SELECTOR_DRIVER_RESET); - if (ContainsBit(ec, ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)) + } + if (ContainsBit(ec, ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_SELECTOR_UNDERVOLTAGE_ERROR); - if (ContainsBit(ec, ErrorCode::TMC_SHORT_TO_GROUND)) + } + if (ContainsBit(ec, ErrorCode::TMC_SHORT_TO_GROUND)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_SELECTOR_DRIVER_SHORTED); - if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_WARN)) + } + if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_WARN)) { return FindErrorIndex(ERR_TEMPERATURE_WARNING_TMC_SELECTOR_TOO_HOT); - if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_ERROR)) + } + if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_ERROR)) { return FindErrorIndex(ERR_TEMPERATURE_TMC_SELECTOR_OVERHEAT_ERROR); + } } else if (ContainsBit(ec, ErrorCode::TMC_IDLER_BIT)) { - if (ContainsBit(ec, ErrorCode::TMC_IOIN_MISMATCH)) + if (ContainsBit(ec, ErrorCode::TMC_IOIN_MISMATCH)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_IDLER_DRIVER_ERROR); - if (ContainsBit(ec, ErrorCode::TMC_RESET)) + } + if (ContainsBit(ec, ErrorCode::TMC_RESET)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_IDLER_DRIVER_RESET); - if (ContainsBit(ec, ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)) + } + if (ContainsBit(ec, ErrorCode::TMC_UNDERVOLTAGE_ON_CHARGE_PUMP)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_IDLER_UNDERVOLTAGE_ERROR); - if (ContainsBit(ec, ErrorCode::TMC_SHORT_TO_GROUND)) + } + if (ContainsBit(ec, ErrorCode::TMC_SHORT_TO_GROUND)) { return FindErrorIndex(ERR_ELECTRICAL_TMC_IDLER_DRIVER_SHORTED); - if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_WARN)) + } + if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_WARN)) { return FindErrorIndex(ERR_TEMPERATURE_WARNING_TMC_IDLER_TOO_HOT); - if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_ERROR)) + } + if (ContainsBit(ec, ErrorCode::TMC_OVER_TEMPERATURE_ERROR)) { return FindErrorIndex(ERR_TEMPERATURE_TMC_IDLER_OVERHEAT_ERROR); + } } - // if nothing got caught, return a generic runtime error + // if nothing got caught, return a generic error return FindErrorIndex(ERR_OTHER_UNKNOWN_ERROR); } -uint16_t PrusaErrorCode(uint8_t i){ +uint16_t PrusaErrorCode(uint8_t i) { return pgm_read_word(errorCodes + i); } -const char * PrusaErrorTitle(uint8_t i){ +const char *PrusaErrorTitle(uint8_t i) { return (const char *)pgm_read_ptr(errorTitles + i); } -const char * PrusaErrorDesc(uint8_t i){ +const char *PrusaErrorDesc(uint8_t i) { return (const char *)pgm_read_ptr(errorDescs + i); } -uint8_t PrusaErrorButtons(uint8_t i){ +uint8_t PrusaErrorButtons(uint8_t i) { return pgm_read_byte(errorButtons + i); } -const char * PrusaErrorButtonTitle(uint8_t bi){ +const char *PrusaErrorButtonTitle(uint8_t bi) { // -1 represents the hidden NoOperation button which is not drawn in any way return (const char *)pgm_read_ptr(btnOperation + bi - 1); } -const char * PrusaErrorButtonMore(){ +const char *PrusaErrorButtonMore() { return MSG_BTN_MORE; } @@ -193,7 +215,6 @@ Buttons ButtonPressed(ErrorCode ec) { const auto result = ButtonAvailable(ec); buttonSelectedOperation = ButtonOperations::NoOperation; // Reset operation - return result; } @@ -342,7 +363,7 @@ Buttons ButtonAvailable(ErrorCode ec) { return Buttons::NoButton; } -void SetButtonResponse(ButtonOperations rsp){ +void SetButtonResponse(ButtonOperations rsp) { buttonSelectedOperation = rsp; } diff --git a/Firmware/mmu2_log.h b/Firmware/mmu2_log.h index 1d18a2b6db..25cecdf4ce 100644 --- a/Firmware/mmu2_log.h +++ b/Firmware/mmu2_log.h @@ -55,7 +55,7 @@ void LogEchoEvent_P(const char *msg_P); } while (0) #define MMU2_ERROR_MSG(S) MMU2_ECHO_MSG(S) //!@todo Decide MMU errors on serial line -#else // #ifndef UNITTEST +#else // #ifndef UNITTEST #include "stubs/stub_interfaces.h" #define MMU2_ECHO_MSGLN(S) marlinLogSim.AppendLine(S) #define MMU2_ERROR_MSGLN(S) marlinLogSim.AppendLine(S) @@ -65,4 +65,4 @@ void LogEchoEvent_P(const char *msg_P); #define SERIAL_ECHOPGM(S) /* */ #define SERIAL_ECHOLN(S) /*marlinLogSim.AppendLine(S)*/ -#endif // #ifndef UNITTEST +#endif // #ifndef UNITTEST diff --git a/Firmware/mmu2_marlin.h b/Firmware/mmu2_marlin.h index a2bfcb001d..2d4d84d043 100644 --- a/Firmware/mmu2_marlin.h +++ b/Firmware/mmu2_marlin.h @@ -28,6 +28,7 @@ void extruder_schedule_turning(float feed_rate); float move_raise_z(float delta); void planner_abort_queued_moves(); +bool planner_draining(); void planner_synchronize(); bool planner_any_moves(); float stepper_get_machine_position_E_mm(); diff --git a/Firmware/mmu2_marlin1.cpp b/Firmware/mmu2_marlin1.cpp index 255a4e8a6c..dc812a8b5b 100644 --- a/Firmware/mmu2_marlin1.cpp +++ b/Firmware/mmu2_marlin1.cpp @@ -38,6 +38,10 @@ void planner_abort_queued_moves() { planner_aborted = false; } +bool planner_draining() { + return planner_aborted; +} + void planner_synchronize() { st_synchronize(); } @@ -46,33 +50,33 @@ bool planner_any_moves() { return blocks_queued(); } -float planner_get_machine_position_E_mm(){ +float planner_get_machine_position_E_mm() { return current_position[E_AXIS]; } -float stepper_get_machine_position_E_mm(){ +float stepper_get_machine_position_E_mm() { return st_get_position_mm(E_AXIS); } -float planner_get_current_position_E(){ +float planner_get_current_position_E() { return current_position[E_AXIS]; } -void planner_set_current_position_E(float e){ +void planner_set_current_position_E(float e) { current_position[E_AXIS] = e; } -pos3d planner_current_position(){ +pos3d planner_current_position() { return pos3d(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS]); } -void motion_do_blocking_move_to_xy(float rx, float ry, float feedRate_mm_s){ +void motion_do_blocking_move_to_xy(float rx, float ry, float feedRate_mm_s) { current_position[X_AXIS] = rx; current_position[Y_AXIS] = ry; planner_line_to_current_position_sync(feedRate_mm_s); } -void motion_do_blocking_move_to_z(float z, float feedRate_mm_s){ +void motion_do_blocking_move_to_z(float z, float feedRate_mm_s) { current_position[Z_AXIS] = z; planner_line_to_current_position_sync(feedRate_mm_s); } @@ -84,32 +88,31 @@ void nozzle_park() { } bool marlin_printingIsActive() { - // return IS_SD_PRINTING || usb_timer_running(); return printer_active(); } -void marlin_manage_heater(){ +void marlin_manage_heater() { manage_heater(); } -void marlin_manage_inactivity(bool b){ - manage_inactivity(b); +void marlin_manage_inactivity(bool ignore_stepper_queue) { + manage_inactivity(ignore_stepper_queue); } -void marlin_idle(bool b){ +void marlin_idle(bool ignore_stepper_queue) { manage_heater(); - manage_inactivity(b); + manage_inactivity(ignore_stepper_queue); } -void marlin_refresh_print_state_in_ram(){ +void marlin_refresh_print_state_in_ram() { refresh_print_state_in_ram(); } -void marlin_clear_print_state_in_ram(){ +void marlin_clear_print_state_in_ram() { clear_print_state_in_ram(); } -void marlin_stop_and_save_print_to_ram(){ +void marlin_stop_and_save_print_to_ram() { stop_and_save_print_to_ram(0,0); } @@ -133,10 +136,15 @@ void safe_delay_keep_alive(uint16_t t) { delay_keep_alive(t); } -void Enable_E0(){ enable_e0(); } -void Disable_E0(){ disable_e0(); } +void Enable_E0() { + enable_e0(); +} + +void Disable_E0() { + disable_e0(); +} -bool all_axes_homed(){ +bool all_axes_homed() { return axis_known_position[X_AXIS] && axis_known_position[Y_AXIS]; } diff --git a/Firmware/mmu2_protocol.cpp b/Firmware/mmu2_protocol.cpp index c794432383..d770244552 100644 --- a/Firmware/mmu2_protocol.cpp +++ b/Firmware/mmu2_protocol.cpp @@ -1,4 +1,4 @@ -/// @file +/// @file mmu2_protocol.cpp #include "mmu2_protocol.h" // protocol definition @@ -112,11 +112,8 @@ DecodeStatus Protocol::DecodeRequest(uint8_t c) { rqState = RequestStates::Code; return DecodeStatus::MessageCompleted; } - } else { - requestMsg.code = RequestMsgCodes::unknown; - rqState = RequestStates::Error; - return DecodeStatus::Error; } + [[fallthrough]]; default: //case error: if (IsNewLine(c)) { rqState = RequestStates::Code; @@ -331,7 +328,7 @@ uint8_t Protocol::UInt8ToHex(uint8_t value, uint8_t *dst) { return charsOut; } -uint8_t Protocol::UInt16ToHex(uint16_t value, uint8_t *dst) { +uint8_t __attribute__((noinline)) Protocol::UInt16ToHex(uint16_t value, uint8_t *dst) { constexpr uint16_t topNibbleMask = 0xf000; if (value == 0) { *dst = '0'; diff --git a/Firmware/mmu2_protocol.h b/Firmware/mmu2_protocol.h index 65f7e8ab0b..bcb30de389 100644 --- a/Firmware/mmu2_protocol.h +++ b/Firmware/mmu2_protocol.h @@ -1,4 +1,4 @@ -/// @file protocol.h +/// @file mmu2_protocol.h #pragma once #include #include "mmu2_crc.h" @@ -8,6 +8,7 @@ namespace modules { /// @brief The MMU communication protocol implementation and related stuff. /// /// See description of the new protocol in the MMU 2021 doc + namespace protocol { /// Definition of request message codes @@ -179,17 +180,9 @@ class Protocol { /// @returns number of bytes written into txbuff static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff); - - - - - - - /// Encode response to Query operation status /// @param msg source request message for this response - /// @param code status of operation (Processing, Error, Finished) - /// @param value related to status of operation(e.g. error code or progress) + /// @param rcs status of operation (Processing, Error, Finished) /// @param txbuff where to format the message /// @returns number of bytes written into txbuff static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseCommandStatus rcs, uint8_t *txbuff); diff --git a/Firmware/mmu2_protocol_logic.cpp b/Firmware/mmu2_protocol_logic.cpp index 78122ab6af..25bab54d1c 100644 --- a/Firmware/mmu2_protocol_logic.cpp +++ b/Firmware/mmu2_protocol_logic.cpp @@ -6,7 +6,7 @@ // on MK3/S/+ we shuffle the timers a bit, thus "_millis" may not equal "millis" #include "system_timer.h" #else - // irrelevant on Buddy FW, just keep "_millis" as "millis" +// irrelevant on Buddy FW, just keep "_millis" as "millis" #include #define _millis millis #ifdef UNITTEST @@ -32,18 +32,18 @@ namespace MMU2 { static constexpr uint8_t supportedMmuFWVersion[3] PROGMEM = { mmuVersionMajor, mmuVersionMinor, mmuVersionPatch }; const Register ProtocolLogic::regs8Addrs[ProtocolLogic::regs8Count] PROGMEM = { - Register::FINDA_State, // FINDA state + Register::FINDA_State, // FINDA state Register::Set_Get_Selector_Slot, // Selector slot - Register::Set_Get_Idler_Slot, // Idler slot + Register::Set_Get_Idler_Slot, // Idler slot }; const Register ProtocolLogic::regs16Addrs[ProtocolLogic::regs16Count] PROGMEM = { - Register::MMU_Errors, // MMU errors - aka statistics + Register::MMU_Errors, // MMU errors - aka statistics Register::Get_Pulley_Position, // Pulley position [mm] }; const Register ProtocolLogic::initRegs8Addrs[ProtocolLogic::initRegs8Count] PROGMEM = { - Register::Extra_Load_Distance, // extra load distance [mm] + Register::Extra_Load_Distance, // extra load distance [mm] Register::Pulley_Slow_Feedrate, // pulley slow feedrate [mm/s] }; @@ -186,7 +186,7 @@ StepStatus ProtocolLogic::ExpectingMessage() { break; } } - [[fallthrough]]; // otherwise + [[fallthrough]]; // otherwise default: RecordUARTActivity(); // something has happened on the UART, update the timeout record return ProtocolError; @@ -194,7 +194,7 @@ StepStatus ProtocolLogic::ExpectingMessage() { } if (bytesConsumed != 0) { RecordUARTActivity(); // something has happened on the UART, update the timeout record - return Processing; // consumed some bytes, but message still not ready + return Processing; // consumed some bytes, but message still not ready } else if (Elapsed(linkLayerTimeout) && currentScope != Scope::Stopped) { return CommunicationTimeout; } @@ -267,6 +267,8 @@ StepStatus ProtocolLogic::ScopeStep() { if (!ExpectsResponse()) { // we are waiting for something switch (currentScope) { + case Scope::StartSeq: + return Processing; case Scope::DelayedRestart: return DelayedRestartWait(); case Scope::Idle: @@ -280,17 +282,18 @@ StepStatus ProtocolLogic::ScopeStep() { } } else { // we are expecting a message - if (auto expmsg = ExpectingMessage(); expmsg != MessageReady) // this whole statement takes 12B + if (auto expmsg = ExpectingMessage(); expmsg != MessageReady) { // this whole statement takes 12B return expmsg; + } // process message switch (currentScope) { case Scope::StartSeq: return StartSeqStep(); // ~270B case Scope::Idle: - return IdleStep(); // ~300B + return IdleStep(); // ~300B case Scope::Command: - return CommandStep(); // ~430B + return CommandStep(); // ~430B case Scope::Stopped: return StoppedStep(); default: @@ -335,7 +338,7 @@ StepStatus ProtocolLogic::StartSeqStep() { StepStatus ProtocolLogic::DelayedRestartWait() { if (Elapsed(heartBeatPeriod)) { // this basically means, that we are waiting until there is some traffic on while (uart->read() != -1) - ; // clear the input buffer + ; // clear the input buffer // switch to StartSeq Start(); } @@ -723,12 +726,13 @@ void ProtocolLogic::FormatLastResponseMsgAndClearLRB(char *dst) { for (uint8_t i = 0; i < lrb; ++i) { uint8_t b = lastReceivedBytes[i]; // Check for printable character, including space - if (b < 32 || b > 127) + if (b < 32 || b > 127) { b = '.'; + } *dst++ = b; } *dst = 0; // terminate properly - lrb = 0; // reset the input buffer index in case of a clean message + lrb = 0; // reset the input buffer index in case of a clean message } void ProtocolLogic::LogRequestMsg(const uint8_t *txbuff, uint8_t size) { @@ -738,8 +742,9 @@ void ProtocolLogic::LogRequestMsg(const uint8_t *txbuff, uint8_t size) { for (uint8_t i = 0; i < size; ++i) { uint8_t b = txbuff[i]; // Check for printable character, including space - if (b < 32 || b > 127) + if (b < 32 || b > 127) { b = '.'; + } tmp[i + 1] = b; } tmp[size + 1] = 0; @@ -809,7 +814,7 @@ StepStatus ProtocolLogic::Step() { // We are ok, switching to Idle if there is no potential next request planned. // But the trouble is we must report a finished command if the previous command has just been finished // i.e. only try to find some planned command if we just finished the Idle cycle - if (!ActivatePlannedRequest()) { // if nothing is planned, switch to Idle + if (!ActivatePlannedRequest()) { // if nothing is planned, switch to Idle SwitchToIdle(); } else if (ExpectsResponse()) { // if the previous cycle was Idle and now we have planned a new command -> avoid returning Finished @@ -845,8 +850,9 @@ StepStatus ProtocolLogic::Step() { } uint8_t ProtocolLogic::CommandInProgress() const { - if (currentScope != Scope::Command) + if (currentScope != Scope::Command) { return 0; + } return (uint8_t)ReqMsg().code; } @@ -862,7 +868,7 @@ void ProtocolLogic::ResetRetryAttempts() { retryAttempts = MAX_RETRIES; } -void __attribute__((noinline)) ProtocolLogic::ResetCommunicationTimeoutAttempts() { +void ProtocolLogic::ResetCommunicationTimeoutAttempts() { SERIAL_ECHOLNPGM("RSTCommTimeout"); dataTO.Reset(); } diff --git a/Firmware/mmu2_protocol_logic.h b/Firmware/mmu2_protocol_logic.h index 6e46360ed6..b22c56f7c4 100644 --- a/Firmware/mmu2_protocol_logic.h +++ b/Firmware/mmu2_protocol_logic.h @@ -52,22 +52,22 @@ class ProtocolLogic; /// ProtocolLogic stepping statuses enum StepStatus : uint_fast8_t { Processing = 0, - MessageReady, ///< a message has been successfully decoded from the received bytes - Finished, ///< Scope finished successfully - Interrupted, ///< received "Finished" message related to a different command than originally issued (most likely the MMU restarted while doing something) + MessageReady, ///< a message has been successfully decoded from the received bytes + Finished, ///< Scope finished successfully + Interrupted, ///< received "Finished" message related to a different command than originally issued (most likely the MMU restarted while doing something) CommunicationTimeout, ///< the MMU failed to respond to a request within a specified time frame - ProtocolError, ///< bytes read from the MMU didn't form a valid response - CommandRejected, ///< the MMU rejected the command due to some other command in progress, may be the user is operating the MMU locally (button commands) - CommandError, ///< the command in progress stopped due to unrecoverable error, user interaction required - VersionMismatch, ///< the MMU reports its firmware version incompatible with our implementation - PrinterError, ///< printer's explicit error - MMU is fine, but the printer was unable to complete the requested operation + ProtocolError, ///< bytes read from the MMU didn't form a valid response + CommandRejected, ///< the MMU rejected the command due to some other command in progress, may be the user is operating the MMU locally (button commands) + CommandError, ///< the command in progress stopped due to unrecoverable error, user interaction required + VersionMismatch, ///< the MMU reports its firmware version incompatible with our implementation + PrinterError, ///< printer's explicit error - MMU is fine, but the printer was unable to complete the requested operation CommunicationRecovered, - ButtonPushed, ///< The MMU reported the user pushed one of its three buttons. + ButtonPushed, ///< The MMU reported the user pushed one of its three buttons. }; -inline constexpr uint32_t linkLayerTimeout = 2000; ///< default link layer communication timeout +inline constexpr uint32_t linkLayerTimeout = 2000; ///< default link layer communication timeout inline constexpr uint32_t dataLayerTimeout = linkLayerTimeout * 3; ///< data layer communication timeout -inline constexpr uint32_t heartBeatPeriod = linkLayerTimeout / 2; ///< period of heart beat messages (Q0) +inline constexpr uint32_t heartBeatPeriod = linkLayerTimeout / 2; ///< period of heart beat messages (Q0) static_assert(heartBeatPeriod < linkLayerTimeout && linkLayerTimeout < dataLayerTimeout, "Incorrect ordering of timeouts"); @@ -229,9 +229,9 @@ class ProtocolLogic { ErrorCode explicitPrinterError; enum class State : uint_fast8_t { - Stopped, ///< stopped for whatever reason + Stopped, ///< stopped for whatever reason InitSequence, ///< initial sequence running - Running ///< normal operation - Idle + Command processing + Running ///< normal operation - Idle + Command processing }; enum class Scope : uint_fast8_t { @@ -347,25 +347,25 @@ class ProtocolLogic { /// Activate the planned state once the immediate response to a sent request arrived bool ActivatePlannedRequest(); - uint32_t lastUARTActivityMs; ///< timestamp - last ms when something occurred on the UART - DropOutFilter dataTO; ///< Filter of short consecutive drop outs which are recovered instantly + uint32_t lastUARTActivityMs; ///< timestamp - last ms when something occurred on the UART + DropOutFilter dataTO; ///< Filter of short consecutive drop outs which are recovered instantly - ResponseMsg rsp; ///< decoded response message from the MMU protocol + ResponseMsg rsp; ///< decoded response message from the MMU protocol - State state; ///< internal state of ProtocolLogic + State state; ///< internal state of ProtocolLogic - Protocol protocol; ///< protocol codec + Protocol protocol; ///< protocol codec std::array lastReceivedBytes; ///< remembers the last few bytes of incoming communication for diagnostic purposes uint8_t lrb; - MMU2Serial *uart; ///< UART interface + MMU2Serial *uart; ///< UART interface - ErrorCode errorCode; ///< last received error code from the MMU + ErrorCode errorCode; ///< last received error code from the MMU ProgressCode progressCode; ///< last received progress code from the MMU - Buttons buttonCode; ///< Last received button from the MMU. + Buttons buttonCode; ///< Last received button from the MMU. - uint8_t lastFSensor; ///< last state of filament sensor + uint8_t lastFSensor; ///< last state of filament sensor #ifndef __AVR__ uint8_t txbuff[Protocol::MaxRequestSize()]; ///< In Buddy FW - a static transmit buffer needs to exist as DMA cannot be used from CCMRAM. diff --git a/Firmware/mmu2_state.h b/Firmware/mmu2_state.h index 0961c8883c..9a6bcef158 100644 --- a/Firmware/mmu2_state.h +++ b/Firmware/mmu2_state.h @@ -13,9 +13,12 @@ namespace MMU2 { /// When the printer's FW starts, the MMU mode is either Stopped or NotResponding (based on user's preference). /// When the MMU successfully establishes communication, the state changes to Active. enum class xState : uint_fast8_t { - Active, ///< MMU has been detected, connected, communicates and is ready to be worked with. + /// The user doesn't want the printer to work with the MMU. The MMU itself is not powered and does not work at all. + /// !!! Must be 0 !!! marlin_vars.mmu2_state is set to 0 if not active + Stopped, + + Active, ///< MMU has been detected, connected, communicates and is ready to be worked with. Connecting, ///< MMU is connected but it doesn't communicate (yet). The user wants the MMU, but it is not ready to be worked with. - Stopped ///< The user doesn't want the printer to work with the MMU. The MMU itself is not powered and does not work at all. }; } // namespace MMU2 From 61b42701292af6ffb5e41680d0ec18c98ab4a043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Thu, 28 Mar 2024 23:25:40 +0000 Subject: [PATCH 2/6] MMU: allow inlining UInt16ToHex Saves 22 bytes of Flash --- Firmware/mmu2_protocol.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/mmu2_protocol.cpp b/Firmware/mmu2_protocol.cpp index d770244552..b8ce8d3332 100644 --- a/Firmware/mmu2_protocol.cpp +++ b/Firmware/mmu2_protocol.cpp @@ -328,7 +328,7 @@ uint8_t Protocol::UInt8ToHex(uint8_t value, uint8_t *dst) { return charsOut; } -uint8_t __attribute__((noinline)) Protocol::UInt16ToHex(uint16_t value, uint8_t *dst) { +uint8_t Protocol::UInt16ToHex(uint16_t value, uint8_t *dst) { constexpr uint16_t topNibbleMask = 0xf000; if (value == 0) { *dst = '0'; From 09f1d85e9c47fbd73d37639d45c543554850c7cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gu=C3=B0ni=20M=C3=A1r=20Gilbert?= Date: Thu, 28 Mar 2024 23:36:23 +0000 Subject: [PATCH 3/6] MMU: Revert changes to execute_extruder_sequence loop The previous for-loop is more memory efficient and saves 20 bytes of Flash --- Firmware/mmu2.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index 1622fcf0fc..c2203cdf90 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -948,8 +948,10 @@ void MMU2::execute_extruder_sequence(const E_Step *sequence, uint8_t stepCount) planner_synchronize(); // Plan the moves - for (const E_Step *step = sequence, *end = sequence + stepCount; step != end; step++) { + const E_Step *step = sequence; + for (uint8_t i = stepCount; i > 0; --i) { extruder_move(pgm_read_float(&(step->extrude)), pgm_read_float(&(step->feedRate))); + step++; } // Wait for the moves to finish From d548bb68fd7754162d8343c4ff4460cfa7d4afa3 Mon Sep 17 00:00:00 2001 From: gudnimg Date: Fri, 29 Mar 2024 18:01:30 +0000 Subject: [PATCH 4/6] MMU: revert WaitForHotendTargetTempBeep(); position in code The 8-bit FW uses a different Fullscreen UI which doesn't show the current temperature. So, for now, keep calling WaitForHotendTargetTempBeep before showing the full-screen message. --- Firmware/mmu2.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index c2203cdf90..2cab0aa2be 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -493,9 +493,10 @@ bool MMU2::unload() { return false; } + WaitForHotendTargetTempBeep(); + { ReportingRAII rep(CommandInProgress::UnloadFilament); - WaitForHotendTargetTempBeep(); UnloadInner(); } @@ -573,14 +574,14 @@ bool MMU2::load_filament_to_nozzle(uint8_t slot) { return false; } + WaitForHotendTargetTempBeep(); + FullScreenMsgLoad(slot); { // used for MMU-menu operation "Load to Nozzle" ReportingRAII rep(CommandInProgress::ToolChange); FSensorBlockRunout blockRunout; - WaitForHotendTargetTempBeep(); - if (extruder != MMU2_NO_TOOL) { // we already have some filament loaded - free it + shape its tip properly filament_ramming(); } From 99e306f4a3427a5c6018147cba7af4c642a15649 Mon Sep 17 00:00:00 2001 From: gudnimg Date: Sat, 6 Jul 2024 17:24:40 +0000 Subject: [PATCH 5/6] MMU: minor formatting sync --- Firmware/mmu2_error_converter.h | 2 +- Firmware/mmu2_marlin.h | 4 ++-- Firmware/mmu2_progress_converter.cpp | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Firmware/mmu2_error_converter.h b/Firmware/mmu2_error_converter.h index fea2ba2a10..3b18ee1e60 100644 --- a/Firmware/mmu2_error_converter.h +++ b/Firmware/mmu2_error_converter.h @@ -6,7 +6,7 @@ #include "mmu2/error_codes.h" #else #include "buttons.h" - #include "../../../../../../Prusa-Error-Codes/04_MMU/button_operations.h" + #include "../../../../../../Prusa-Error-Codes/include/button_operations.h" #include "../../../../../../Prusa-Firmware-MMU/src/logic/error_codes.h" #endif diff --git a/Firmware/mmu2_marlin.h b/Firmware/mmu2_marlin.h index 2d4d84d043..4ce1ac2440 100644 --- a/Firmware/mmu2_marlin.h +++ b/Firmware/mmu2_marlin.h @@ -43,8 +43,8 @@ void nozzle_park(); bool marlin_printingIsActive(); void marlin_manage_heater(); -void marlin_manage_inactivity(bool b); -void marlin_idle(bool b); +void marlin_manage_inactivity(bool ignore_stepper_queue); +void marlin_idle(bool ignore_stepper_queue); void marlin_refresh_print_state_in_ram(); void marlin_clear_print_state_in_ram(); void marlin_stop_and_save_print_to_ram(); diff --git a/Firmware/mmu2_progress_converter.cpp b/Firmware/mmu2_progress_converter.cpp index 29fd0d2500..c5c14c84af 100644 --- a/Firmware/mmu2_progress_converter.cpp +++ b/Firmware/mmu2_progress_converter.cpp @@ -30,7 +30,7 @@ static const char MSG_PROGRESS_HOMING[] PROGMEM_I1 = ISTR("Homing"); / static const char MSG_PROGRESS_MOVING_SELECTOR[] PROGMEM_I1 = ISTR("Moving selector"); ////MSG_PROGRESS_MOVING_SELECTOR c=20 static const char MSG_PROGRESS_FEED_FSENSOR[] PROGMEM_I1 = ISTR("Feeding to FSensor"); ////MSG_PROGRESS_FEED_FSENSOR c=20 -static const char * const progressTexts[] PROGMEM = { +static const char *const progressTexts[] PROGMEM = { _R(MSG_PROGRESS_OK), _R(MSG_PROGRESS_ENGAGE_IDLER), _R(MSG_PROGRESS_DISENGAGE_IDLER), @@ -62,11 +62,11 @@ static const char * const progressTexts[] PROGMEM = { _R(MSG_PROGRESS_FEED_FSENSOR) }; -const char * ProgressCodeToText(ProgressCode pc){ +const char *ProgressCodeToText(ProgressCode pc) { // @@TODO ?? a better fallback option? - return ( (uint16_t)pc <= (sizeof(progressTexts) / sizeof(progressTexts[0])) ) - ? static_cast(pgm_read_ptr(&progressTexts[(uint16_t)pc])) - : static_cast(pgm_read_ptr(&progressTexts[0])); + return ((uint16_t)pc <= (sizeof(progressTexts) / sizeof(progressTexts[0]))) + ? static_cast(pgm_read_ptr(&progressTexts[(uint16_t)pc])) + : static_cast(pgm_read_ptr(&progressTexts[0])); } } // namespace MMU2 From 4dc9fd4972e2cc5b0ae93fc75e3cd8f886af9c8b Mon Sep 17 00:00:00 2001 From: gudnimg Date: Tue, 23 Jul 2024 15:55:47 +0000 Subject: [PATCH 6/6] MMU: revert fallthrough in LogicStep --- Firmware/mmu2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index 2cab0aa2be..55405637b2 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -885,7 +885,7 @@ StepStatus MMU2::LogicStep(bool reportErrors) { case Finished: // At this point it is safe to trigger a runout and not interrupt the MMU protocol CheckFINDARunout(); - [[fallthrough]]; // let Finished be reported the same way like Processing + break; case Processing: OnMMUProgressMsg(logic.Progress());