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()
This commit is contained in:
parent
e405e9140c
commit
592fc56bfc
|
|
@ -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();
|
||||
|
||||
|
|
@ -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<void>(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()) {
|
||||
|
|
@ -804,8 +829,7 @@ 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.
|
||||
if (!TuneMenuEntered())
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
|
@ -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());
|
||||
}
|
||||
break;
|
||||
case FilamentState::NOT_PRESENT:
|
||||
// fsensor not triggered, continue moving extruder
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ typedef float feedRate_t;
|
|||
#else
|
||||
#include "protocol_logic.h"
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#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();
|
||||
|
|
@ -273,7 +275,9 @@ private:
|
|||
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
|
||||
|
|
@ -343,6 +347,7 @@ private:
|
|||
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
|
||||
uint8_t tool_change_extruder; ///< only used for UI purposes
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
bool all_axes_homed(){
|
||||
void Disable_E0() {
|
||||
disable_e0();
|
||||
}
|
||||
|
||||
bool all_axes_homed() {
|
||||
return axis_known_position[X_AXIS] && axis_known_position[Y_AXIS];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/// @file protocol.h
|
||||
/// @file mmu2_protocol.h
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#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 @@ public:
|
|||
/// @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);
|
||||
|
|
|
|||
|
|
@ -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 <wiring_time.h>
|
||||
#define _millis millis
|
||||
#ifdef UNITTEST
|
||||
|
|
@ -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,8 +282,9 @@ 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) {
|
||||
|
|
@ -723,8 +726,9 @@ 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
|
||||
|
|
@ -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;
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
/// 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
|
||||
|
|
|
|||
Loading…
Reference in New Issue