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() {
|
void WaitForHotendTargetTempBeep() {
|
||||||
waitForHotendTargetTemp(3000, []{ });
|
waitForHotendTargetTemp(200, [] {});
|
||||||
MakeSound(Prompt);
|
MakeSound(Prompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,14 +73,17 @@ void MMU2::Start() {
|
||||||
mmu2Serial.flush(); // make sure the UART buffer is clear before starting communication
|
mmu2Serial.flush(); // make sure the UART buffer is clear before starting communication
|
||||||
|
|
||||||
SetCurrentTool(MMU2_NO_TOOL);
|
SetCurrentTool(MMU2_NO_TOOL);
|
||||||
state = xState::Connecting;
|
|
||||||
|
|
||||||
// start the communication
|
// start the communication
|
||||||
logic.Start();
|
|
||||||
logic.ResetRetryAttempts();
|
logic.ResetRetryAttempts();
|
||||||
logic.ResetCommunicationTimeoutAttempts();
|
logic.ResetCommunicationTimeoutAttempts();
|
||||||
|
|
||||||
|
state = xState::Connecting;
|
||||||
|
logic.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MMU2::~MMU2() {}
|
||||||
|
|
||||||
void MMU2::Stop() {
|
void MMU2::Stop() {
|
||||||
StopKeepPowered();
|
StopKeepPowered();
|
||||||
PowerOff();
|
PowerOff();
|
||||||
|
|
@ -153,8 +156,9 @@ void MMU2::PowerOn() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMU2::ReadRegister(uint8_t address) {
|
bool MMU2::ReadRegister(uint8_t address) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
do {
|
do {
|
||||||
logic.ReadRegister(address); // we may signal the accepted/rejected status of the response as return value of this function
|
logic.ReadRegister(address); // we may signal the accepted/rejected status of the response as return value of this function
|
||||||
} while (!manage_response(false, false));
|
} 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) {
|
bool __attribute__((noinline)) MMU2::WriteRegister(uint8_t address, uint16_t data) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// special cases - intercept requests of registers which influence the printer's behaviour too + perform the change even on the printer's side
|
// special cases - intercept requests of registers which influence the printer's behaviour too + perform the change even on the printer's side
|
||||||
switch (address) {
|
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,
|
// 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
|
// so thread safety should be kept
|
||||||
static bool avoidRecursion = false;
|
static bool avoidRecursion = false;
|
||||||
if (avoidRecursion)
|
if (avoidRecursion) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
avoidRecursion = true;
|
avoidRecursion = true;
|
||||||
|
|
||||||
mmu_loop_inner(true);
|
mmu_loop_inner(true);
|
||||||
|
|
||||||
avoidRecursion = false;
|
avoidRecursion = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -208,7 +212,7 @@ void __attribute__((noinline)) MMU2::mmu_loop_inner(bool reportErrors) {
|
||||||
|
|
||||||
void MMU2::CheckFINDARunout() {
|
void MMU2::CheckFINDARunout() {
|
||||||
// Check for FINDA filament runout
|
// 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!");
|
SERIAL_ECHOLNPGM("FINDA filament runout!");
|
||||||
marlin_stop_and_save_print_to_ram();
|
marlin_stop_and_save_print_to_ram();
|
||||||
restore_print_from_ram_and_continue(0);
|
restore_print_from_ram_and_continue(0);
|
||||||
|
|
@ -301,8 +305,12 @@ bool MMU2::VerifyFilamentEnteredPTFE() {
|
||||||
filament_inserted = filament_inserted && (WhereIsFilament() == FilamentState::AT_FSENSOR);
|
filament_inserted = filament_inserted && (WhereIsFilament() == FilamentState::AT_FSENSOR);
|
||||||
tlur.Progress(filament_inserted);
|
tlur.Progress(filament_inserted);
|
||||||
safe_delay_keep_alive(0);
|
safe_delay_keep_alive(0);
|
||||||
|
if (planner_draining()) {
|
||||||
|
return false; // power panic or a similar issue happened, bail out fast
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Disable_E0();
|
Disable_E0();
|
||||||
if (!filament_inserted) {
|
if (!filament_inserted) {
|
||||||
IncrementLoadFails();
|
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
|
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;
|
tool_change_extruder = slot;
|
||||||
logic.ToolChange(slot); // let the MMU pull the filament out and push a new one in
|
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;
|
break;
|
||||||
|
}
|
||||||
// otherwise: failed to perform the command - unload first and then let it run again
|
// otherwise: failed to perform the command - unload first and then let it run again
|
||||||
IncrementMMUFails();
|
IncrementMMUFails();
|
||||||
|
|
||||||
|
|
@ -335,7 +344,7 @@ bool MMU2::ToolChangeCommonOnce(uint8_t slot) {
|
||||||
}
|
}
|
||||||
if (VerifyFilamentEnteredPTFE()) {
|
if (VerifyFilamentEnteredPTFE()) {
|
||||||
return true; // success
|
return true; // success
|
||||||
} else { // Prepare a retry attempt
|
} else { // Prepare a retry attempt
|
||||||
UnloadInner();
|
UnloadInner();
|
||||||
if (retries == 2 && cutter_enabled()) {
|
if (retries == 2 && cutter_enabled()) {
|
||||||
CutFilamentInner(slot); // try cutting filament tip at the last attempt
|
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) {
|
void MMU2::ToolChangeCommon(uint8_t slot) {
|
||||||
while (!ToolChangeCommonOnce(slot)) { // while not successfully fed into extruder's PTFE tube
|
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
|
// 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...
|
// @@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);
|
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
|
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);
|
SpoolJoin::spooljoin.setSlot(slot);
|
||||||
|
|
||||||
++toolchange_counter;
|
++toolchange_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMU2::tool_change(uint8_t slot) {
|
bool MMU2::tool_change(uint8_t slot) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (slot != extruder) {
|
if (slot != extruder) {
|
||||||
if (/*FindaDetectsFilament()*/
|
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.
|
///- 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.
|
///- 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) {
|
bool MMU2::tool_change(char code, uint8_t slot) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FSensorBlockRunout blockRunout;
|
FSensorBlockRunout blockRunout;
|
||||||
|
|
||||||
|
|
@ -435,8 +449,9 @@ void MMU2::SetCurrentTool(uint8_t ex){
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMU2::set_filament_type(uint8_t /*slot*/, uint8_t /*type*/) {
|
bool MMU2::set_filament_type(uint8_t /*slot*/, uint8_t /*type*/) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// @@TODO - this is not supported in the new MMU yet
|
// @@TODO - this is not supported in the new MMU yet
|
||||||
// slot = slot; // @@TODO
|
// slot = slot; // @@TODO
|
||||||
|
|
@ -461,8 +476,9 @@ void MMU2::UnloadInner() {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Disable_E0();
|
Disable_E0();
|
||||||
logic.UnloadFilament();
|
logic.UnloadFilament();
|
||||||
if (manage_response(false, true))
|
if (manage_response(false, true)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
IncrementMMUFails();
|
IncrementMMUFails();
|
||||||
}
|
}
|
||||||
MakeSound(Confirm);
|
MakeSound(Confirm);
|
||||||
|
|
@ -473,15 +489,16 @@ void MMU2::UnloadInner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMU2::unload() {
|
bool MMU2::unload() {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
WaitForHotendTargetTempBeep();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ReportingRAII rep(CommandInProgress::UnloadFilament);
|
ReportingRAII rep(CommandInProgress::UnloadFilament);
|
||||||
|
WaitForHotendTargetTempBeep();
|
||||||
UnloadInner();
|
UnloadInner();
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenUpdateEnable();
|
ScreenUpdateEnable();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -490,15 +507,17 @@ void MMU2::CutFilamentInner(uint8_t slot) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Disable_E0();
|
Disable_E0();
|
||||||
logic.CutFilament(slot);
|
logic.CutFilament(slot);
|
||||||
if (manage_response(false, true))
|
if (manage_response(false, true)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
IncrementMMUFails();
|
IncrementMMUFails();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMU2::cut_filament(uint8_t slot, bool enableFullScreenMsg /*= true*/) {
|
bool MMU2::cut_filament(uint8_t slot, bool enableFullScreenMsg /*= true*/) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (enableFullScreenMsg) {
|
if (enableFullScreenMsg) {
|
||||||
FullScreenMsgCut(slot);
|
FullScreenMsgCut(slot);
|
||||||
|
|
@ -528,8 +547,9 @@ bool MMU2::loading_test(uint8_t slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMU2::load_filament(uint8_t slot) {
|
bool MMU2::load_filament(uint8_t slot) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
FullScreenMsgLoad(slot);
|
FullScreenMsgLoad(slot);
|
||||||
{
|
{
|
||||||
|
|
@ -537,8 +557,9 @@ bool MMU2::load_filament(uint8_t slot) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Disable_E0();
|
Disable_E0();
|
||||||
logic.LoadFilament(slot);
|
logic.LoadFilament(slot);
|
||||||
if (manage_response(false, false))
|
if (manage_response(false, false)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
IncrementMMUFails();
|
IncrementMMUFails();
|
||||||
}
|
}
|
||||||
MakeSound(SoundType::Confirm);
|
MakeSound(SoundType::Confirm);
|
||||||
|
|
@ -548,10 +569,9 @@ bool MMU2::load_filament(uint8_t slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MMU2::load_filament_to_nozzle(uint8_t slot) {
|
bool MMU2::load_filament_to_nozzle(uint8_t slot) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
WaitForHotendTargetTempBeep();
|
|
||||||
|
|
||||||
FullScreenMsgLoad(slot);
|
FullScreenMsgLoad(slot);
|
||||||
{
|
{
|
||||||
|
|
@ -559,6 +579,8 @@ bool MMU2::load_filament_to_nozzle(uint8_t slot) {
|
||||||
ReportingRAII rep(CommandInProgress::ToolChange);
|
ReportingRAII rep(CommandInProgress::ToolChange);
|
||||||
FSensorBlockRunout blockRunout;
|
FSensorBlockRunout blockRunout;
|
||||||
|
|
||||||
|
WaitForHotendTargetTempBeep();
|
||||||
|
|
||||||
if (extruder != MMU2_NO_TOOL) { // we already have some filament loaded - free it + shape its tip properly
|
if (extruder != MMU2_NO_TOOL) { // we already have some filament loaded - free it + shape its tip properly
|
||||||
filament_ramming();
|
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 */) {
|
bool MMU2::eject_filament(uint8_t slot, bool enableFullScreenMsg /* = true */) {
|
||||||
if (!WaitForMMUReady())
|
if (!WaitForMMUReady()) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (enableFullScreenMsg) {
|
if (enableFullScreenMsg) {
|
||||||
FullScreenMsgEject(slot);
|
FullScreenMsgEject(slot);
|
||||||
|
|
@ -589,8 +612,9 @@ bool MMU2::eject_filament(uint8_t slot, bool enableFullScreenMsg /* = true */) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Disable_E0();
|
Disable_E0();
|
||||||
logic.EjectFilament(slot);
|
logic.EjectFilament(slot);
|
||||||
if (manage_response(false, true))
|
if (manage_response(false, true)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
IncrementMMUFails();
|
IncrementMMUFails();
|
||||||
}
|
}
|
||||||
SetCurrentTool(MMU2_NO_TOOL);
|
SetCurrentTool(MMU2_NO_TOOL);
|
||||||
|
|
@ -611,8 +635,9 @@ void MMU2::Home(uint8_t mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU2::SaveHotendTemp(bool turn_off_nozzle) {
|
void MMU2::SaveHotendTemp(bool turn_off_nozzle) {
|
||||||
if (mmu_print_saved & SavedState::Cooldown)
|
if (mmu_print_saved & SavedState::Cooldown) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (turn_off_nozzle && !(mmu_print_saved & SavedState::CooldownPending)) {
|
if (turn_off_nozzle && !(mmu_print_saved & SavedState::CooldownPending)) {
|
||||||
Disable_E0();
|
Disable_E0();
|
||||||
|
|
@ -701,8 +726,7 @@ void MMU2::CheckUserInput() {
|
||||||
lastButton = Buttons::NoButton; // Clear it.
|
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
|
// When the printer has raised an error screen, and a button was selected
|
||||||
// the error screen should always be dismissed.
|
// the error screen should always be dismissed.
|
||||||
ClearPrinterError();
|
ClearPrinterError();
|
||||||
|
|
@ -720,7 +744,7 @@ void MMU2::CheckUserInput() {
|
||||||
SERIAL_ECHOLN((int)buttons_to_uint8t(btn));
|
SERIAL_ECHOLN((int)buttons_to_uint8t(btn));
|
||||||
ResumeHotendTemp(); // Recover the hotend temp before we attempt to do anything else...
|
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
|
// Do not send a button to the MMU unless the MMU is in error state
|
||||||
Button(buttons_to_uint8t(btn));
|
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
|
// - failed -> then do the safety moves on the printer like before
|
||||||
// - finished ok -> proceed with reading other commands
|
// - finished ok -> proceed with reading other commands
|
||||||
safe_delay_keep_alive(0); // calls LogicStep() and remembers its return status
|
safe_delay_keep_alive(0); // calls LogicStep() and remembers its return status
|
||||||
|
// also disables stepper motor unlocking
|
||||||
|
|
||||||
if (mmu_print_saved & SavedState::CooldownPending) {
|
if (mmu_print_saved & SavedState::CooldownPending) {
|
||||||
if (!nozzleTimeout.running()) {
|
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
|
// command/operation completed, let Marlin continue its work
|
||||||
// the E may have some more moves to finish - wait for them
|
// the E may have some more moves to finish - wait for them
|
||||||
ResumeHotendTemp();
|
ResumeHotendTemp();
|
||||||
ResumeUnpark(); // We can now travel back to the tower or wherever we were when we saved.
|
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)
|
// If the error screen is sleeping (running 'Tune' menu)
|
||||||
// then don't reset retry attempts because we this will trigger
|
// then don't reset retry attempts because we this will trigger
|
||||||
// an automatic retry attempt when 'Tune' button is selected. We want the
|
// an automatic retry attempt when 'Tune' button is selected. We want the
|
||||||
|
|
@ -860,7 +884,7 @@ StepStatus MMU2::LogicStep(bool reportErrors) {
|
||||||
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;
|
[[fallthrough]]; // let Finished be reported the same way like Processing
|
||||||
|
|
||||||
case Processing:
|
case Processing:
|
||||||
OnMMUProgressMsg(logic.Progress());
|
OnMMUProgressMsg(logic.Progress());
|
||||||
|
|
@ -920,15 +944,17 @@ void MMU2::filament_ramming() {
|
||||||
execute_extruder_sequence(ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step));
|
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();
|
planner_synchronize();
|
||||||
|
|
||||||
const E_Step *step = sequence;
|
// Plan the moves
|
||||||
for (uint8_t i = steps; i > 0; --i) {
|
for (const E_Step *step = sequence, *end = sequence + stepCount; step != end; step++) {
|
||||||
extruder_move(pgm_read_float(&(step->extrude)), pgm_read_float(&(step->feedRate)));
|
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();
|
Disable_E0();
|
||||||
}
|
}
|
||||||
|
|
@ -1031,7 +1057,7 @@ void MMU2::OnMMUProgressMsgChanged(ProgressCode pc) {
|
||||||
switch (pc) {
|
switch (pc) {
|
||||||
case ProgressCode::UnloadingToFinda:
|
case ProgressCode::UnloadingToFinda:
|
||||||
if ((CommandInProgress)logic.CommandInProgress() == CommandInProgress::UnloadFilament
|
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 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 Toolchange is done while printing, PrusaSlicer takes care of releasing the filament
|
||||||
// If printing is not in progress, ToolChange will issue a U0 command.
|
// 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:
|
case FilamentState::AT_FSENSOR:
|
||||||
// fsensor triggered, finish FeedingToExtruder state
|
// fsensor triggered, finish FeedingToExtruder state
|
||||||
loadFilamentStarted = false;
|
loadFilamentStarted = false;
|
||||||
|
|
||||||
// Abort any excess E-move from the planner queue
|
|
||||||
planner_abort_queued_moves();
|
planner_abort_queued_moves();
|
||||||
|
{
|
||||||
// After the MMU knows the FSENSOR is triggered it will:
|
extruder_move(logic.ExtraLoadDistance() + 2, logic.PulleySlowFeedRate());
|
||||||
// 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;
|
break;
|
||||||
case FilamentState::NOT_PRESENT:
|
case FilamentState::NOT_PRESENT:
|
||||||
// fsensor not triggered, continue moving extruder
|
// fsensor not triggered, continue moving extruder
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ typedef float feedRate_t;
|
||||||
#else
|
#else
|
||||||
#include "protocol_logic.h"
|
#include "protocol_logic.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <memory>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct E_Step;
|
struct E_Step;
|
||||||
|
|
@ -32,6 +33,7 @@ struct Version {
|
||||||
class MMU2 {
|
class MMU2 {
|
||||||
public:
|
public:
|
||||||
MMU2();
|
MMU2();
|
||||||
|
~MMU2();
|
||||||
|
|
||||||
/// Powers ON the MMU, then initializes the UART and protocol logic
|
/// Powers ON the MMU, then initializes the UART and protocol logic
|
||||||
void Start();
|
void Start();
|
||||||
|
|
@ -48,17 +50,17 @@ public:
|
||||||
|
|
||||||
/// Different levels of resetting the MMU
|
/// Different levels of resetting the MMU
|
||||||
enum ResetForm : uint8_t {
|
enum ResetForm : uint8_t {
|
||||||
Software = 0, ///< sends a X0 command into the MMU, the MMU will watchdog-reset itself
|
Software = 0, ///< sends a X0 command into the MMU, the MMU will watchdog-reset itself
|
||||||
ResetPin = 1, ///< trigger the reset pin of the MMU
|
ResetPin = 1, ///< trigger the reset pin of the MMU
|
||||||
CutThePower = 2, ///< power off and power on (that includes +5V and +24V power lines)
|
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
|
EraseEEPROM = 42, ///< erase MMU EEPROM and then perform a software reset
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Saved print state on error.
|
/// Saved print state on error.
|
||||||
enum SavedState : uint8_t {
|
enum SavedState : uint8_t {
|
||||||
None = 0, // No state saved.
|
None = 0, // No state saved.
|
||||||
ParkExtruder = 1, // The extruder was parked.
|
ParkExtruder = 1, // The extruder was parked.
|
||||||
Cooldown = 2, // The extruder was allowed to cool.
|
Cooldown = 2, // The extruder was allowed to cool.
|
||||||
CooldownPending = 4,
|
CooldownPending = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -207,9 +209,9 @@ public:
|
||||||
};
|
};
|
||||||
inline void InvokeErrorScreen(ErrorCode ec) {
|
inline void InvokeErrorScreen(ErrorCode ec) {
|
||||||
// The printer may not raise an error when the MMU is busy
|
// 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
|
&& 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);
|
ReportError(ec, ErrorSource::ErrorSourcePrinter);
|
||||||
}
|
}
|
||||||
|
|
@ -273,7 +275,9 @@ private:
|
||||||
StepStatus LogicStep(bool reportErrors);
|
StepStatus LogicStep(bool reportErrors);
|
||||||
|
|
||||||
void filament_ramming();
|
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();
|
void execute_load_to_nozzle_sequence();
|
||||||
|
|
||||||
/// Reports an error into attached ExtUIs
|
/// Reports an error into attached ExtUIs
|
||||||
|
|
@ -342,8 +346,9 @@ private:
|
||||||
|
|
||||||
void SetCurrentTool(uint8_t ex);
|
void SetCurrentTool(uint8_t ex);
|
||||||
|
|
||||||
ProtocolLogic logic; ///< implementation of the protocol logic layer
|
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 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
|
uint8_t tool_change_extruder; ///< only used for UI purposes
|
||||||
|
|
||||||
pos3d resume_position;
|
pos3d resume_position;
|
||||||
|
|
|
||||||
|
|
@ -29,17 +29,17 @@ static constexpr uint8_t FindErrorIndex(uint16_t pec) {
|
||||||
return (i != errorCodesEnd) ? (i-errorCodes) : (errorCodesSize - 1);
|
return (i != errorCodesEnd) ? (i-errorCodes) : (errorCodesSize - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check that the searching algoritm works
|
// check that the searching algorithm works
|
||||||
static_assert( FindErrorIndex(ERR_MECHANICAL_FINDA_DIDNT_TRIGGER) == 0);
|
static_assert(FindErrorIndex(ERR_MECHANICAL_FINDA_DIDNT_TRIGGER) == 0);
|
||||||
static_assert( FindErrorIndex(ERR_MECHANICAL_FINDA_FILAMENT_STUCK) == 1);
|
static_assert(FindErrorIndex(ERR_MECHANICAL_FINDA_FILAMENT_STUCK) == 1);
|
||||||
static_assert( FindErrorIndex(ERR_MECHANICAL_FSENSOR_DIDNT_TRIGGER) == 2);
|
static_assert(FindErrorIndex(ERR_MECHANICAL_FSENSOR_DIDNT_TRIGGER) == 2);
|
||||||
static_assert( FindErrorIndex(ERR_MECHANICAL_FSENSOR_FILAMENT_STUCK) == 3);
|
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);
|
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;
|
return (uint16_t)ec & (uint16_t)mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,93 +96,115 @@ uint8_t PrusaErrorCodeIndex(ErrorCode ec) {
|
||||||
return FindErrorIndex(ERR_SYSTEM_UNLOAD_MANUALLY);
|
return FindErrorIndex(ERR_SYSTEM_UNLOAD_MANUALLY);
|
||||||
case ErrorCode::MCU_UNDERVOLTAGE_VCC:
|
case ErrorCode::MCU_UNDERVOLTAGE_VCC:
|
||||||
return FindErrorIndex(ERR_ELECTRICAL_MMU_MCU_ERROR);
|
return FindErrorIndex(ERR_ELECTRICAL_MMU_MCU_ERROR);
|
||||||
default: break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Electrical issues which can be detected somehow.
|
// 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
|
// 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.
|
// and to keep the code size down.
|
||||||
if (ContainsBit(ec, ErrorCode::TMC_PULLEY_BIT)) {
|
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);
|
return FindErrorIndex(ERR_ELECTRICAL_MMU_PULLEY_SELFTEST_FAILED);
|
||||||
|
}
|
||||||
} else if (ContainsBit(ec, ErrorCode::TMC_SELECTOR_BIT)) {
|
} 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);
|
return FindErrorIndex(ERR_ELECTRICAL_MMU_SELECTOR_SELFTEST_FAILED);
|
||||||
|
}
|
||||||
} else if (ContainsBit(ec, ErrorCode::TMC_IDLER_BIT)) {
|
} 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);
|
return FindErrorIndex(ERR_ELECTRICAL_MMU_IDLER_SELFTEST_FAILED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TMC-related errors - multiple of these can occur at once
|
// 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)
|
// - 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.
|
// 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_PULLEY_BIT)) {
|
||||||
if (ContainsBit(ec, ErrorCode::TMC_IOIN_MISMATCH))
|
if (ContainsBit(ec, ErrorCode::TMC_IOIN_MISMATCH)) {
|
||||||
return FindErrorIndex(ERR_ELECTRICAL_TMC_PULLEY_DRIVER_ERROR);
|
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);
|
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);
|
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);
|
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);
|
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);
|
return FindErrorIndex(ERR_TEMPERATURE_TMC_PULLEY_OVERHEAT_ERROR);
|
||||||
|
}
|
||||||
} else if (ContainsBit(ec, ErrorCode::TMC_SELECTOR_BIT)) {
|
} 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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
return FindErrorIndex(ERR_TEMPERATURE_TMC_SELECTOR_OVERHEAT_ERROR);
|
||||||
|
}
|
||||||
} else if (ContainsBit(ec, ErrorCode::TMC_IDLER_BIT)) {
|
} 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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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);
|
return FindErrorIndex(ERR_OTHER_UNKNOWN_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t PrusaErrorCode(uint8_t i){
|
uint16_t PrusaErrorCode(uint8_t i) {
|
||||||
return pgm_read_word(errorCodes + 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);
|
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);
|
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);
|
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
|
// -1 represents the hidden NoOperation button which is not drawn in any way
|
||||||
return (const char *)pgm_read_ptr(btnOperation + bi - 1);
|
return (const char *)pgm_read_ptr(btnOperation + bi - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * PrusaErrorButtonMore(){
|
const char *PrusaErrorButtonMore() {
|
||||||
return MSG_BTN_MORE;
|
return MSG_BTN_MORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -193,7 +215,6 @@ Buttons ButtonPressed(ErrorCode ec) {
|
||||||
|
|
||||||
const auto result = ButtonAvailable(ec);
|
const auto result = ButtonAvailable(ec);
|
||||||
buttonSelectedOperation = ButtonOperations::NoOperation; // Reset operation
|
buttonSelectedOperation = ButtonOperations::NoOperation; // Reset operation
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -342,7 +363,7 @@ Buttons ButtonAvailable(ErrorCode ec) {
|
||||||
return Buttons::NoButton;
|
return Buttons::NoButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetButtonResponse(ButtonOperations rsp){
|
void SetButtonResponse(ButtonOperations rsp) {
|
||||||
buttonSelectedOperation = rsp;
|
buttonSelectedOperation = rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ void LogEchoEvent_P(const char *msg_P);
|
||||||
} while (0)
|
} while (0)
|
||||||
#define MMU2_ERROR_MSG(S) MMU2_ECHO_MSG(S) //!@todo Decide MMU errors on serial line
|
#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"
|
#include "stubs/stub_interfaces.h"
|
||||||
#define MMU2_ECHO_MSGLN(S) marlinLogSim.AppendLine(S)
|
#define MMU2_ECHO_MSGLN(S) marlinLogSim.AppendLine(S)
|
||||||
#define MMU2_ERROR_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_ECHOPGM(S) /* */
|
||||||
#define SERIAL_ECHOLN(S) /*marlinLogSim.AppendLine(S)*/
|
#define SERIAL_ECHOLN(S) /*marlinLogSim.AppendLine(S)*/
|
||||||
|
|
||||||
#endif // #ifndef UNITTEST
|
#endif // #ifndef UNITTEST
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ void extruder_schedule_turning(float feed_rate);
|
||||||
float move_raise_z(float delta);
|
float move_raise_z(float delta);
|
||||||
|
|
||||||
void planner_abort_queued_moves();
|
void planner_abort_queued_moves();
|
||||||
|
bool planner_draining();
|
||||||
void planner_synchronize();
|
void planner_synchronize();
|
||||||
bool planner_any_moves();
|
bool planner_any_moves();
|
||||||
float stepper_get_machine_position_E_mm();
|
float stepper_get_machine_position_E_mm();
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,10 @@ void planner_abort_queued_moves() {
|
||||||
planner_aborted = false;
|
planner_aborted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool planner_draining() {
|
||||||
|
return planner_aborted;
|
||||||
|
}
|
||||||
|
|
||||||
void planner_synchronize() {
|
void planner_synchronize() {
|
||||||
st_synchronize();
|
st_synchronize();
|
||||||
}
|
}
|
||||||
|
|
@ -46,33 +50,33 @@ bool planner_any_moves() {
|
||||||
return blocks_queued();
|
return blocks_queued();
|
||||||
}
|
}
|
||||||
|
|
||||||
float planner_get_machine_position_E_mm(){
|
float planner_get_machine_position_E_mm() {
|
||||||
return current_position[E_AXIS];
|
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);
|
return st_get_position_mm(E_AXIS);
|
||||||
}
|
}
|
||||||
|
|
||||||
float planner_get_current_position_E(){
|
float planner_get_current_position_E() {
|
||||||
return current_position[E_AXIS];
|
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;
|
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]);
|
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[X_AXIS] = rx;
|
||||||
current_position[Y_AXIS] = ry;
|
current_position[Y_AXIS] = ry;
|
||||||
planner_line_to_current_position_sync(feedRate_mm_s);
|
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;
|
current_position[Z_AXIS] = z;
|
||||||
planner_line_to_current_position_sync(feedRate_mm_s);
|
planner_line_to_current_position_sync(feedRate_mm_s);
|
||||||
}
|
}
|
||||||
|
|
@ -84,32 +88,31 @@ void nozzle_park() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool marlin_printingIsActive() {
|
bool marlin_printingIsActive() {
|
||||||
// return IS_SD_PRINTING || usb_timer_running();
|
|
||||||
return printer_active();
|
return printer_active();
|
||||||
}
|
}
|
||||||
|
|
||||||
void marlin_manage_heater(){
|
void marlin_manage_heater() {
|
||||||
manage_heater();
|
manage_heater();
|
||||||
}
|
}
|
||||||
|
|
||||||
void marlin_manage_inactivity(bool b){
|
void marlin_manage_inactivity(bool ignore_stepper_queue) {
|
||||||
manage_inactivity(b);
|
manage_inactivity(ignore_stepper_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void marlin_idle(bool b){
|
void marlin_idle(bool ignore_stepper_queue) {
|
||||||
manage_heater();
|
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();
|
refresh_print_state_in_ram();
|
||||||
}
|
}
|
||||||
|
|
||||||
void marlin_clear_print_state_in_ram(){
|
void marlin_clear_print_state_in_ram() {
|
||||||
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);
|
stop_and_save_print_to_ram(0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -133,10 +136,15 @@ void safe_delay_keep_alive(uint16_t t) {
|
||||||
delay_keep_alive(t);
|
delay_keep_alive(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Enable_E0(){ enable_e0(); }
|
void Enable_E0() {
|
||||||
void Disable_E0(){ disable_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];
|
return axis_known_position[X_AXIS] && axis_known_position[Y_AXIS];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/// @file
|
/// @file mmu2_protocol.cpp
|
||||||
#include "mmu2_protocol.h"
|
#include "mmu2_protocol.h"
|
||||||
|
|
||||||
// protocol definition
|
// protocol definition
|
||||||
|
|
@ -112,11 +112,8 @@ DecodeStatus Protocol::DecodeRequest(uint8_t c) {
|
||||||
rqState = RequestStates::Code;
|
rqState = RequestStates::Code;
|
||||||
return DecodeStatus::MessageCompleted;
|
return DecodeStatus::MessageCompleted;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
requestMsg.code = RequestMsgCodes::unknown;
|
|
||||||
rqState = RequestStates::Error;
|
|
||||||
return DecodeStatus::Error;
|
|
||||||
}
|
}
|
||||||
|
[[fallthrough]];
|
||||||
default: //case error:
|
default: //case error:
|
||||||
if (IsNewLine(c)) {
|
if (IsNewLine(c)) {
|
||||||
rqState = RequestStates::Code;
|
rqState = RequestStates::Code;
|
||||||
|
|
@ -331,7 +328,7 @@ uint8_t Protocol::UInt8ToHex(uint8_t value, uint8_t *dst) {
|
||||||
return charsOut;
|
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;
|
constexpr uint16_t topNibbleMask = 0xf000;
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
*dst = '0';
|
*dst = '0';
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
/// @file protocol.h
|
/// @file mmu2_protocol.h
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "mmu2_crc.h"
|
#include "mmu2_crc.h"
|
||||||
|
|
@ -8,6 +8,7 @@ namespace modules {
|
||||||
/// @brief The MMU communication protocol implementation and related stuff.
|
/// @brief The MMU communication protocol implementation and related stuff.
|
||||||
///
|
///
|
||||||
/// See description of the new protocol in the MMU 2021 doc
|
/// See description of the new protocol in the MMU 2021 doc
|
||||||
|
|
||||||
namespace protocol {
|
namespace protocol {
|
||||||
|
|
||||||
/// Definition of request message codes
|
/// Definition of request message codes
|
||||||
|
|
@ -179,17 +180,9 @@ public:
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
|
static uint8_t EncodeResponseReadFINDA(const RequestMsg &msg, uint8_t findaValue, uint8_t *txbuff);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Encode response to Query operation status
|
/// Encode response to Query operation status
|
||||||
/// @param msg source request message for this response
|
/// @param msg source request message for this response
|
||||||
/// @param code status of operation (Processing, Error, Finished)
|
/// @param rcs status of operation (Processing, Error, Finished)
|
||||||
/// @param value related to status of operation(e.g. error code or progress)
|
|
||||||
/// @param txbuff where to format the message
|
/// @param txbuff where to format the message
|
||||||
/// @returns number of bytes written into txbuff
|
/// @returns number of bytes written into txbuff
|
||||||
static uint8_t EncodeResponseQueryOperation(const RequestMsg &msg, ResponseCommandStatus rcs, uint8_t *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"
|
// on MK3/S/+ we shuffle the timers a bit, thus "_millis" may not equal "millis"
|
||||||
#include "system_timer.h"
|
#include "system_timer.h"
|
||||||
#else
|
#else
|
||||||
// irrelevant on Buddy FW, just keep "_millis" as "millis"
|
// irrelevant on Buddy FW, just keep "_millis" as "millis"
|
||||||
#include <wiring_time.h>
|
#include <wiring_time.h>
|
||||||
#define _millis millis
|
#define _millis millis
|
||||||
#ifdef UNITTEST
|
#ifdef UNITTEST
|
||||||
|
|
@ -32,18 +32,18 @@ namespace MMU2 {
|
||||||
static constexpr uint8_t supportedMmuFWVersion[3] PROGMEM = { mmuVersionMajor, mmuVersionMinor, mmuVersionPatch };
|
static constexpr uint8_t supportedMmuFWVersion[3] PROGMEM = { mmuVersionMajor, mmuVersionMinor, mmuVersionPatch };
|
||||||
|
|
||||||
const Register ProtocolLogic::regs8Addrs[ProtocolLogic::regs8Count] PROGMEM = {
|
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_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 = {
|
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]
|
Register::Get_Pulley_Position, // Pulley position [mm]
|
||||||
};
|
};
|
||||||
|
|
||||||
const Register ProtocolLogic::initRegs8Addrs[ProtocolLogic::initRegs8Count] PROGMEM = {
|
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]
|
Register::Pulley_Slow_Feedrate, // pulley slow feedrate [mm/s]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -186,7 +186,7 @@ StepStatus ProtocolLogic::ExpectingMessage() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[[fallthrough]]; // otherwise
|
[[fallthrough]]; // otherwise
|
||||||
default:
|
default:
|
||||||
RecordUARTActivity(); // something has happened on the UART, update the timeout record
|
RecordUARTActivity(); // something has happened on the UART, update the timeout record
|
||||||
return ProtocolError;
|
return ProtocolError;
|
||||||
|
|
@ -194,7 +194,7 @@ StepStatus ProtocolLogic::ExpectingMessage() {
|
||||||
}
|
}
|
||||||
if (bytesConsumed != 0) {
|
if (bytesConsumed != 0) {
|
||||||
RecordUARTActivity(); // something has happened on the UART, update the timeout record
|
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) {
|
} else if (Elapsed(linkLayerTimeout) && currentScope != Scope::Stopped) {
|
||||||
return CommunicationTimeout;
|
return CommunicationTimeout;
|
||||||
}
|
}
|
||||||
|
|
@ -267,6 +267,8 @@ StepStatus ProtocolLogic::ScopeStep() {
|
||||||
if (!ExpectsResponse()) {
|
if (!ExpectsResponse()) {
|
||||||
// we are waiting for something
|
// we are waiting for something
|
||||||
switch (currentScope) {
|
switch (currentScope) {
|
||||||
|
case Scope::StartSeq:
|
||||||
|
return Processing;
|
||||||
case Scope::DelayedRestart:
|
case Scope::DelayedRestart:
|
||||||
return DelayedRestartWait();
|
return DelayedRestartWait();
|
||||||
case Scope::Idle:
|
case Scope::Idle:
|
||||||
|
|
@ -280,17 +282,18 @@ StepStatus ProtocolLogic::ScopeStep() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// we are expecting a message
|
// 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;
|
return expmsg;
|
||||||
|
}
|
||||||
|
|
||||||
// process message
|
// process message
|
||||||
switch (currentScope) {
|
switch (currentScope) {
|
||||||
case Scope::StartSeq:
|
case Scope::StartSeq:
|
||||||
return StartSeqStep(); // ~270B
|
return StartSeqStep(); // ~270B
|
||||||
case Scope::Idle:
|
case Scope::Idle:
|
||||||
return IdleStep(); // ~300B
|
return IdleStep(); // ~300B
|
||||||
case Scope::Command:
|
case Scope::Command:
|
||||||
return CommandStep(); // ~430B
|
return CommandStep(); // ~430B
|
||||||
case Scope::Stopped:
|
case Scope::Stopped:
|
||||||
return StoppedStep();
|
return StoppedStep();
|
||||||
default:
|
default:
|
||||||
|
|
@ -335,7 +338,7 @@ StepStatus ProtocolLogic::StartSeqStep() {
|
||||||
StepStatus ProtocolLogic::DelayedRestartWait() {
|
StepStatus ProtocolLogic::DelayedRestartWait() {
|
||||||
if (Elapsed(heartBeatPeriod)) { // this basically means, that we are waiting until there is some traffic on
|
if (Elapsed(heartBeatPeriod)) { // this basically means, that we are waiting until there is some traffic on
|
||||||
while (uart->read() != -1)
|
while (uart->read() != -1)
|
||||||
; // clear the input buffer
|
; // clear the input buffer
|
||||||
// switch to StartSeq
|
// switch to StartSeq
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
@ -723,12 +726,13 @@ void ProtocolLogic::FormatLastResponseMsgAndClearLRB(char *dst) {
|
||||||
for (uint8_t i = 0; i < lrb; ++i) {
|
for (uint8_t i = 0; i < lrb; ++i) {
|
||||||
uint8_t b = lastReceivedBytes[i];
|
uint8_t b = lastReceivedBytes[i];
|
||||||
// Check for printable character, including space
|
// Check for printable character, including space
|
||||||
if (b < 32 || b > 127)
|
if (b < 32 || b > 127) {
|
||||||
b = '.';
|
b = '.';
|
||||||
|
}
|
||||||
*dst++ = b;
|
*dst++ = b;
|
||||||
}
|
}
|
||||||
*dst = 0; // terminate properly
|
*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) {
|
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) {
|
for (uint8_t i = 0; i < size; ++i) {
|
||||||
uint8_t b = txbuff[i];
|
uint8_t b = txbuff[i];
|
||||||
// Check for printable character, including space
|
// Check for printable character, including space
|
||||||
if (b < 32 || b > 127)
|
if (b < 32 || b > 127) {
|
||||||
b = '.';
|
b = '.';
|
||||||
|
}
|
||||||
tmp[i + 1] = b;
|
tmp[i + 1] = b;
|
||||||
}
|
}
|
||||||
tmp[size + 1] = 0;
|
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.
|
// 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
|
// 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
|
// 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();
|
SwitchToIdle();
|
||||||
} else if (ExpectsResponse()) {
|
} else if (ExpectsResponse()) {
|
||||||
// if the previous cycle was Idle and now we have planned a new command -> avoid returning Finished
|
// 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 {
|
uint8_t ProtocolLogic::CommandInProgress() const {
|
||||||
if (currentScope != Scope::Command)
|
if (currentScope != Scope::Command) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
return (uint8_t)ReqMsg().code;
|
return (uint8_t)ReqMsg().code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -862,7 +868,7 @@ void ProtocolLogic::ResetRetryAttempts() {
|
||||||
retryAttempts = MAX_RETRIES;
|
retryAttempts = MAX_RETRIES;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __attribute__((noinline)) ProtocolLogic::ResetCommunicationTimeoutAttempts() {
|
void ProtocolLogic::ResetCommunicationTimeoutAttempts() {
|
||||||
SERIAL_ECHOLNPGM("RSTCommTimeout");
|
SERIAL_ECHOLNPGM("RSTCommTimeout");
|
||||||
dataTO.Reset();
|
dataTO.Reset();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,22 +52,22 @@ class ProtocolLogic;
|
||||||
/// ProtocolLogic stepping statuses
|
/// ProtocolLogic stepping statuses
|
||||||
enum StepStatus : uint_fast8_t {
|
enum StepStatus : uint_fast8_t {
|
||||||
Processing = 0,
|
Processing = 0,
|
||||||
MessageReady, ///< a message has been successfully decoded from the received bytes
|
MessageReady, ///< a message has been successfully decoded from the received bytes
|
||||||
Finished, ///< Scope finished successfully
|
Finished, ///< Scope finished successfully
|
||||||
Interrupted, ///< received "Finished" message related to a different command than originally issued (most likely the MMU restarted while doing something)
|
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
|
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
|
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)
|
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
|
CommandError, ///< the command in progress stopped due to unrecoverable error, user interaction required
|
||||||
VersionMismatch, ///< the MMU reports its firmware version incompatible with our implementation
|
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
|
PrinterError, ///< printer's explicit error - MMU is fine, but the printer was unable to complete the requested operation
|
||||||
CommunicationRecovered,
|
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 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");
|
static_assert(heartBeatPeriod < linkLayerTimeout && linkLayerTimeout < dataLayerTimeout, "Incorrect ordering of timeouts");
|
||||||
|
|
||||||
|
|
@ -229,9 +229,9 @@ private:
|
||||||
ErrorCode explicitPrinterError;
|
ErrorCode explicitPrinterError;
|
||||||
|
|
||||||
enum class State : uint_fast8_t {
|
enum class State : uint_fast8_t {
|
||||||
Stopped, ///< stopped for whatever reason
|
Stopped, ///< stopped for whatever reason
|
||||||
InitSequence, ///< initial sequence running
|
InitSequence, ///< initial sequence running
|
||||||
Running ///< normal operation - Idle + Command processing
|
Running ///< normal operation - Idle + Command processing
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Scope : uint_fast8_t {
|
enum class Scope : uint_fast8_t {
|
||||||
|
|
@ -347,25 +347,25 @@ private:
|
||||||
/// Activate the planned state once the immediate response to a sent request arrived
|
/// Activate the planned state once the immediate response to a sent request arrived
|
||||||
bool ActivatePlannedRequest();
|
bool ActivatePlannedRequest();
|
||||||
|
|
||||||
uint32_t lastUARTActivityMs; ///< timestamp - last ms when something occurred on the UART
|
uint32_t lastUARTActivityMs; ///< timestamp - last ms when something occurred on the UART
|
||||||
DropOutFilter dataTO; ///< Filter of short consecutive drop outs which are recovered instantly
|
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<uint8_t, 16> lastReceivedBytes; ///< remembers the last few bytes of incoming communication for diagnostic purposes
|
std::array<uint8_t, 16> lastReceivedBytes; ///< remembers the last few bytes of incoming communication for diagnostic purposes
|
||||||
uint8_t lrb;
|
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
|
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__
|
#ifndef __AVR__
|
||||||
uint8_t txbuff[Protocol::MaxRequestSize()]; ///< In Buddy FW - a static transmit buffer needs to exist as DMA cannot be used from CCMRAM.
|
uint8_t txbuff[Protocol::MaxRequestSize()]; ///< In Buddy FW - a static transmit buffer needs to exist as DMA cannot be used from CCMRAM.
|
||||||
|
|
|
||||||
|
|
@ -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 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.
|
/// When the MMU successfully establishes communication, the state changes to Active.
|
||||||
enum class xState : uint_fast8_t {
|
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.
|
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
|
} // namespace MMU2
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue